v07i053: 2.11 News Source, Part03/09

sources-request at mirror.UUCP sources-request at mirror.UUCP
Fri Nov 7 02:59:16 AEST 1986


Submitted by: seismo!rick (Rick Adams)
Mod.sources: Volume 7, Issue 53
Archive-name: 2.11news/Part13

# To extract, sh this file
#
#	news 2.11 source part 3 of 9
#
if test ! -d src
then
	mkdir src
fi
echo x - src/inews.c 1>&2
sed 's/.//' >src/inews.c <<'*-*-END-of-src/inews.c-*-*'
-/*
- * This software is Copyright (c) 1986 by Rick Adams.
- *
- * Permission is hereby granted to copy, reproduce, redistribute or
- * otherwise use this software as long as: there is no monetary
- * profit gained specifically from the use or reproduction or this
- * software, it is not sold, rented, traded or otherwise marketed, and
- * this copyright notice is included prominently in any copy
- * made.
- *
- * The author make no claims as to the fitness or correctness of
- * this software for any use whatsoever, and it is provided as is. 
- * Any use of this software is at the user's own risk.
- *
- * inews - insert, receive, and transmit news articles.
- *
- */
-
-#ifdef SCCSID
-static char	*SccsId = "@(#)inews.c	2.69	10/30/86";
-#endif /* SCCSID */
-
-#include "iparams.h"
-#include <errno.h>
-
-#ifdef BSD4_2
-# include <sys/dir.h>
-# include <sys/file.h>
-#else	/* !BSD4_2 */
-# include "ndir.h"
-# ifdef USG
-# include <fcntl.h>
-# endif /* USG */
-# ifdef LOCKF
-# include <unistd.h>
-# endif /* LOCKF */
-#endif /* !BSD4_2 */
-/* local defines for inews */
-
-#define OPTION	0	/* pick up an option string */
-#define STRING	1	/* pick up a string of arguments */
-
-#define UNKNOWN 0001	/* possible modes for news program */
-#define UNPROC	0002	/* Unprocessed input */
-#define PROC	0004	/* Processed input */
-#define	CONTROL	0010	/* Control Message */
-#define	CREATENG 0020	/* Create a new newsgroup */
-
-char	forgedname[NAMELEN];	/* A user specified -f option. */
-int spool_news = FALSE;
-extern char histline[];
-/* Fake sys line in case they forget their own system */
-struct srec dummy_srec = { "MEMEME", "", "all", "", "" };
-
-char *Progname = "inews";	/* used by xerror to identify failing program */
-
-struct {			/* options table. */
-	char	optlet;		/* option character. */
-	char	filchar;	/* if to pickup string, fill character. */
-	int	flag;		/* TRUE if have seen this opt. */
-	int	oldmode;	/* OR of legal input modes. */
-	int	newmode;	/* output mode. */
-	char	*buf;		/* string buffer */
-} *optpt, options[] = { /*
-optlet	filchar		flag	oldmode	newmode		buf	*/
-'t',	' ',		FALSE,	UNPROC,	UNKNOWN,	header.title,
-'n',	NGDELIM,	FALSE,	UNPROC,	UNKNOWN,	header.nbuf,
-'d',	'\0',		FALSE,	UNPROC,	UNKNOWN,	header.distribution,
-'e',	' ',		FALSE,	UNPROC,	UNKNOWN,	header.expdate,
-'p',	'\0',		FALSE,	UNKNOWN|PROC,	PROC,	filename,
-'f',	'\0',		FALSE,	UNPROC,	UNKNOWN,	forgedname,
-'F',	' ',		FALSE,	UNPROC,	UNKNOWN,	header.followid,
-'c',	' ',		FALSE,	UNKNOWN,UNKNOWN,	header.ctlmsg,
-'C',	' ',		FALSE,	UNKNOWN,CREATENG,	header.ctlmsg,
-#define hflag	options[9].flag
-'h',	'\0',		FALSE,	UNPROC,	UNKNOWN,	filename,
-#define oflag	options[10].flag
-'o',	'\0',		FALSE,	UNPROC, UNKNOWN,	header.organization,
-#define Mflag	options[11].flag
-'M',	'\0',		FALSE,	UNPROC, UNKNOWN,	filename,
-'a',	'\0',		FALSE,	UNPROC, UNKNOWN,	header.approved,
-'U',	'\0',		FALSE,	PROC, PROC,		filename,
-'S',	'\0',		FALSE,	UNKNOWN|PROC, 	UNPROC,	filename,
-'x',	'\0',		FALSE,	UNPROC, UNKNOWN,	not_here,
-'r',	'\0',		FALSE,	UNPROC, UNKNOWN,	header.replyto,
-'\0',	'\0',		0,	0,	0,		(char *)NULL
-};
-
-FILE *mailhdr();
-extern int errno;
-
-struct timeb Now;
-
-/*
- *	Authors:
- *		Matt Glickman	glickman at ucbarpa.Berkeley.ARPA
- *		Mark Horton	mark at cbosgd.UUCP
- *		Stephen Daniels	swd at mcnc.UUCP
- *		Tom Truscott	trt at duke.UUCP
- *		Rick Adams	rick at seismo.CSS.GOV
- *	IHCC version adapted by:
- *		Larry Marek	larry at ihuxf.UUCP
- */
-main(argc, argv)
-int	argc;
-register char **argv;
-{
-	int	state;		/* which type of argument to pick up	*/
-	int	tlen, len;	/* temps for string processing routine	*/
-	register char *ptr;	/* pointer to rest of buffer		*/
-	int	filchar;	/* fill character (state = STRING)	*/
-	char	*user = NULL, *home = NULL;	/* environment temps	*/
-	struct passwd	*pw;	/* struct for pw lookup			*/
-	struct group	*gp;	/* struct for group lookup		*/
-	register int	i;
-	FILE	*mfd;		/* mail file file-descriptor		*/
-	char	cbuf[BUFLEN];	/* command buffer			*/
-
-	/* uuxqt doesn't close all it's files */
-	for (i = 3; !close(i); i++)
-		;
-	/* set up defaults and initialize. */
-	mode = UNKNOWN;
-	infp = stdin;
-	pathinit();
-	ptr = rindex(*argv, '/');
-	if (!ptr)
-		ptr = *argv - 1;
-	actfp = xfopen(ACTIVE, "r+");
-#ifdef BSD4_2
-	if (flock(fileno(actfp), LOCK_SH|LOCK_NB) < 0 && errno == EWOULDBLOCK)
-#else	/* !BSD4_2 */
-#ifdef	LOCKF
-	if (lockf(fileno(actfp), F_TLOCK, 0) < 0 && errno == EAGAIN)
-#else	/* !LOCKF */
-	sprintf(bfr, "%s.lock", ACTIVE);
-	if (LINK(ACTIVE,bfr) < 0 && errno == EEXIST)
-#endif /* V7 */
-#endif	/* !BSD4_2 */
-		spool_news = TRUE;
-	else {
-#ifdef SPOOLNEWS
-		if (argc > 1 && !strcmp(*(argv+1), "-S")) {
-			argc--;
-			argv++;
-		} else
-			spool_news = TRUE;
-
-#endif /* SPOOLNEWS */
-#if !defined(BSD4_2) && !defined(LOCKF)
-	(void) UNLINK(bfr);
-#endif	/* !BSD4_2 && !LOCKF */
-	}
-	if (argc > 1 && !strcmp(*(argv+1), "-U")) {
-		dounspool();
-		/* NOT REACHED */
-	}
-
-	if (!strncmp(ptr+1, "rnews", 5)) {
-		mode = PROC;
-		if (spool_news) {
-			dospool((char *)NULL, FALSE);
-			/* NOT REACHED */
-		}
-#ifdef NICENESS
-		nice(NICENESS);
-#endif /* NICENESS */
-	} else
-		if (argc < 2)
-			goto usage;
-
-	state = OPTION;
-	header.title[0] = header.nbuf[0] = filename[0] = '\0';
-
-	/* check for existence of special files */
-	if (!rwaccess(ARTFILE)) {
-		mfd = mailhdr((struct hbuf *)NULL, exists(ARTFILE) ? "Unwritable files!" : "Missing files!");
-		if (mfd != NULL) {
-#ifdef HIDDENNET
-			fprintf(mfd,"System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, ARTFILE);
-#else /* !HIDDENNET */
-			fprintf(mfd,"System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, ARTFILE);
-#endif /* !HIDDENNET */
-			(void) sprintf(cbuf, "touch %s;chmod 666 %s", ARTFILE, ARTFILE);
-			(void) system(cbuf);
-			if (rwaccess(ARTFILE))
-				fprintf(mfd, "The problem has been taken care of.\n");
-			else
-				fprintf(mfd, "Corrective action failed - check suid bits.\n");
-			(void) mclose(mfd);
-		}
-	}
-	if (!rwaccess(ACTIVE)) {
-		mfd = mailhdr((struct hbuf *)NULL, exists(ACTIVE) ? "Unwritable files!" : "Missing files!");
-		if (mfd != NULL) {
-#ifdef HIDDENNET
-			fprintf(mfd,"System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, ARTFILE);
-#else /* !HIDDENNET */
-			fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, ACTIVE);
-#endif /* !HIDDENNET */
-			(void) sprintf(cbuf, "touch %s;chmod 666 %s", ACTIVE, ACTIVE);
-			(void) system(cbuf);
-			if (rwaccess(ACTIVE))
-				fprintf(mfd, "The problem has been taken care of.\n");
-			else
-				fprintf(mfd, "Corrective action failed - check suid bits.\n");
-			(void) mclose(mfd);
-		}
-	}
-	SigTrap = FALSE;	/* true if a signal has been caught */
-	if (mode != PROC) {
-		(void) signal(SIGHUP, onsig);
-		(void) signal(SIGINT, onsig);
-	}
-	savmask = umask(N_UMASK);	/* set up mask */
-	uid = getuid();
-	gid = getgid();
-	duid = geteuid();
-	dgid = getegid();
-	(void) ftime(&Now);
-	if (uid == 0 && duid == 0) {
-		/*
-		 * Must go through with this kludge since
-		 * some systems do not honor the setuid bit
-		 * when root invokes a setuid program.
-		 */
-		if ((pw = getpwnam(NEWSUSR)) == NULL)
-			xerror("Cannot get NEWSU pw entry");
-
-		duid = pw->pw_uid;
-		if ((gp = getgrnam(NEWSGRP)) == NULL)
-			xerror("Cannot get NEWSG gr entry");
-		dgid = gp->gr_gid;
-		(void) setgid(dgid);
-		(void) setuid(duid);
-	}
-
-#ifndef IHCC
-	/*
-	 * We force the use of 'getuser()' to prevent forgery of articles
-	 * by just changing $LOGNAME
-	 */
-	if (isatty(fileno(stderr))) {
-		if ((user = getenv("USER")) == NULL)
-			user = getenv("LOGNAME");
-		if ((home = getenv("HOME")) == NULL)
-			home = getenv("LOGDIR");
-	}
-#endif
-	if (user == NULL || home == NULL)
-		getuser();
-	else {
-		if (username == NULL || username[0] == 0) {
-			username = AllocCpy(user);
-		}
-		userhome = AllocCpy(home);
-	}
-	getuser();
-
-	/* loop once per arg. */
-
-	++argv;		/* skip first arg, which is prog name. */
-
-	while (--argc) {
-	    if (state == OPTION) {
-		if (**argv != '-') {
-			xerror("Bad option string \"%s\"", *argv);
-		}
-		while (*++*argv != '\0') {
-			for (optpt = options; optpt->optlet != '\0'; ++optpt) {
-				if (optpt->optlet == **argv)
-					goto found;
-			}
-			/* unknown option letter */
-usage:
-			fprintf(stderr, "usage: inews -t title");
-			fprintf(stderr, " [ -n newsgroups ]");
-			fprintf(stderr, " [ -e expiration date ]\n");
-			fprintf(stderr, "\t[ -f sender]\n\n");
-			xxit(1);
-
-		    found:;
-			if (optpt->flag == TRUE || (mode != UNKNOWN &&
-			    (mode&optpt->oldmode) == 0)) {
-				xerror("Bad %c option", **argv);
-			}
-			if (mode == UNKNOWN)
-				mode = optpt->newmode;
-			filchar = optpt->filchar;
-			optpt->flag = TRUE;
-			state = STRING;
-			ptr = optpt->buf;
-			len = BUFLEN;
-		}
-
-		argv++;		/* done with this option arg. */
-
-	    } else {
-
-		/*
-		 * Pick up a piece of a string and put it into
-		 * the appropriate buffer.
-		 */
-		if (**argv == '-') {
-			state = OPTION;
-			argc++;	/* uncount this arg. */
-			continue;
-		}
-
-		if ((tlen = strlen(*argv)) >= len)
-			xerror("Argument string too long");
-		(void) strcpy(ptr, *argv++);
-		ptr += tlen;
-		if (*(ptr-1) != filchar)
-			*ptr++ = filchar;
-		len -= tlen + 1;
-		*ptr = '\0';
-	    }
-	}
-
-	/*
-	 * ALL of the command line has now been processed. (!)
-	 */
-
-	if (*filename) {
-		(void) fclose(stdin);
-		infp = freopen(filename, "r", stdin);
-		if (infp == NULL)
-			xerror("freopen(%s): %s", filename, errmsg(errno));
-	} else
-		infp = stdin;
-
-	tty = isatty(fileno(infp));
-
-	if (mode == CREATENG)
-		createng();
-
-	if (header.ctlmsg[0] != '\0' && header.title[0] == '\0')
-		(void) strcpy(header.title, header.ctlmsg);
-
-	if (*header.nbuf) {
-		lcase(header.nbuf);
-		ptr = index(header.nbuf, '\0');
-		if (ptr[-1] == NGDELIM)
-			*--ptr = '\0';
-	}
-	(void) nstrip(header.title);
-	(void) nstrip(header.expdate);
-	(void) nstrip(header.followid);
-	if (mode != PROC) {
-		if (hflag) {
-			header.path[0] = '\0';
-			(void) hread(&header, infp, FALSE);
-			/* there are certain fields we won't let him specify. */
-			if (header.from[0])
-				(void) strcpy(forgedname, header.from);
-			if (!header.approved[0])
-				Mflag = FALSE;
-			header.from[0] = '\0';
-			header.sender[0] = '\0';
-			if (header.subdate[0] && cgtdate(header.subdate) < 0)
-				header.subdate[0] = '\0';
-		}
-
-		if (header.ident[0] == '\0')
-			getident(&header);
-
-		if (forgedname[0]) {
-			register char *p1;
-			if (Mflag)
-				sprintf(header.path, "%s!%s",
-					FULLSYSNAME, username);
-			else if (!header.path[0]) {
-				(void) strcpy(header.path, forgedname);
-
-				if ((p1 = strpbrk(header.path, "@ (<")) != NULL)
-					*p1 = '\0';
-			}
-			if (!Mflag && !strpbrk(forgedname, "@ (<"))
-				(void) sprintf(header.from,"%s@%s%s",
-					forgedname, FULLSYSNAME, MYDOMAIN);
-			else
-				(void) strncpy(header.from, forgedname, BUFLEN);
-
-			(void) sprintf(header.sender, "%s@%s%s",
-				username, FULLSYSNAME, MYDOMAIN);
-		} else {
-			gensender(&header, username);
-		}
-#ifdef MYORG
-		if (header.organization[0] == '\0' && !Mflag &&
-			header.sender[0] == '\0') {
-			strncpy(header.organization, MYORG, BUFLEN);
-			if (strncmp(header.organization, "Frobozz", 7) == 0)
-				header.organization[0] = '\0';
-			if (ptr = getenv("ORGANIZATION"))
-				strncpy(header.organization, ptr, BUFLEN);
-			/*
-			 * Note that the organization can also be turned off by
-			 * setting it to the null string, either in MYORG or
-			 * $ORGANIZATION in the environment.
-			 */
-			if (header.organization[0] == '/') {
-				mfd = fopen(header.organization, "r");
-				if (mfd) {
-					(void) fgets(header.organization, sizeof header.organization, mfd);
-					(void) fclose(mfd);
-				} else {
-					header.organization[0] = '\0';
-					logerr("Couldn't open %s",
-						header.organization);
-				}
-				ptr = index(header.organization, '\n');
-				if (ptr)
-					*ptr = '\0';
-			}
-		}
-#endif /* MYORG */
-	}
-
-	/* Authorize newsgroups. */
-	if (mode == PROC) {
-#ifdef BATCH
-		checkbatch();
-#endif /* BATCH */
-		(void) signal(SIGHUP, SIG_IGN);
-		(void) signal(SIGINT, SIG_IGN);
-		(void) signal(SIGQUIT, SIG_IGN);
-		header.ident[0] = '\0';
-		if (hread(&header, infp, TRUE) == NULL)
-			error("Inbound news is garbled");
-		input();
-	}
-	/* always check history */
-
-	if (history(&header)) {
-		log("Duplicate article %s rejected. Path: %s",
-			header.ident, header.path);
-		xxit(0);
-	}
-
-	/* Easy way to make control messages, since all.all.ctl is unblessed */
-	if (mode != PROC && prefix(header.title, "cmsg ") && header.ctlmsg[0] == 0)
-		(void) strcpy(header.ctlmsg, &header.title[5]);
-	is_ctl = mode != CREATENG &&
-		(ngmatch(header.nbuf, "all.all.ctl,") || header.ctlmsg[0]);
-#ifdef DEBUG
-	fprintf(stderr,"is_ctl set to %d\n", is_ctl);
-#endif
-
-	if (mode != CREATENG) {
-		if (!*header.title)
-			error("No title, ng %s from %s", header.nbuf,
-				header.from);
-		if (!*header.nbuf)
-			(void) strcpy(header.nbuf, DFLTNG);
-	}
-
-	if (mode <= UNPROC) {
-#ifdef FASCIST
-		if (uid && uid != ROOTID && fascist(user, header.nbuf))
-			xerror("User %s is not authorized to post to newsgroup %s",
-				user, header.nbuf);
-#endif /* FASCIST */
-		ctlcheck();
-	}
-
-	if (mode == CREATENG)
-		createng();
-
-	/* Determine input. */
-	if (mode != PROC)
-		input();
-	if (header.intnumlines == 0 && !is_ctl)
-		error("%s rejected: no text lines", header.ident);
-
-	dates(&header);
-
-	/* Do the actual insertion. */
-	insert();
-}
-
-dospool(batchcmd, dolhwrite)
-char *batchcmd;
-int dolhwrite;
-{
-	register int c;
-	register FILE *sp;
-	register struct tm *tp;
-	time_t t;
-	char buf[BUFLEN];
-	extern struct tm *gmtime();
-
-	(void) time(&t);
-	tp = gmtime(&t);
-	/* This file name "has to" be unique  (right?) */
-#ifdef USG
-	(void) sprintf(buf, "%s/.rnews/%2.2d%2.2d%2.2d%2.2d%2.2d%x",
-#else
-#ifdef VMS
-	/* Eunice doesn't like dots in directory names */
-	(void) sprintf(buf, "%s/+rnews/%02d%02d%02d%02d%02d%x",
-#else /* V7 */
-	(void) sprintf(buf, "%s/.rnews/%02d%02d%02d%02d%02d%x",
-#endif /* V7 */
-#endif /* VMS */
-		SPOOLDIR,
-		tp->tm_year, tp->tm_mon+1, tp->tm_mday,
-		tp->tm_hour, tp->tm_min, getpid());
-	sp = xfopen(buf, "w");
-	if (batchcmd != NULL)
-		fprintf(sp, "%s\n", batchcmd);
-	if (dolhwrite)
-		lhwrite(&header, sp);
-	while ((c = getc(infp)) != EOF)
-		putc(c, sp);
-	fclose(sp);
-	xxit(0);
-	/* NOTREACHED */
-}
-
-/*
- *	Create a newsgroup
- */
-createng()
-{
-	register char *cp;
-
-	/*
-	 * Only certain users are allowed to create newsgroups
-	 */
-	if (uid != ROOTID && uid != duid && uid) {
-		fprintf(stderr, "Please contact one of the local netnews people\n\tto create this group for you");
-		xxit(1);
-	}
-	if (header.distribution[0] == '\0')
-#ifdef ORGDISTRIB
-		strcpy(header.distribution, ORGDISTRIB);
-#else /* !ORGDISTRIB */
-		strcpy(header.distribution, "local");
-#endif /* !ORGDISTRIB */
-
-	(void) strcpy(header.nbuf, header.ctlmsg);
-	if ((cp=index(header.nbuf, ' ')) != NULL)
-		*cp = '\0';
-
-	if (header.approved[0] == '\0')
-		(void) sprintf(header.approved, "%s@%s%s",
-				username, FULLSYSNAME, MYDOMAIN);
-	(void) sprintf(bfr, "%s/inews -n %s.ctl -c newgroup %s -d %s -a \"%s\"",
-		LIB, header.nbuf, header.ctlmsg, header.distribution,
-		header.approved);
-	if (tty) {
-		printf("Please type in a paragraph describing the new newsgroup.\n");
-		printf("End with control D as usual.\n");
-	}
-	printf("%s\n", bfr);
-	(void) fflush(stdout);
-	(void) system(bfr);
-	exit(0);
-	/*NOTREACHED*/
-}
-
-char firstbufname[BUFLEN];
-/*
- *	Link ARTICLE into dir for ngname and update active file.
- */
-long
-localize(ngname)
-char	*ngname;
-{
-	char afline[BUFLEN];
-	long ngsize;
-	long fpos;
-	int e;
-	char *cp;
-
-	lock();
-	(void) rewind(actfp); clearerr(actfp);
-
-	for(;;) {
-		fpos = ftell(actfp);
-		if (fgets(afline, sizeof afline, actfp) == NULL) {
-			unlock();
-			logerr("Can't find \"%s\" in active file", ngname);
-			return FALSE;		/* No such newsgroup locally */
-		}
-		if (prefix(afline, ngname)) {
-			(void) sscanf(afline, "%s %ld", bfr, &ngsize);
-			if (strcmp(bfr, ngname) == 0) {
-				if (ngsize < 0 || ngsize > 99998) {
-					logerr("found bad ngsize %ld ng %s, setting to 1", ngsize, bfr);
-					ngsize = 1;
-				}
-				break;
-			}
-		}
-	}
-	for (;;) {
-		cp = dirname(ngname);
-
-		(void) sprintf(bfr, "%s/%ld", cp, ngsize+1);
-#ifdef VMS
-		/*
-		 * The effect of this code is to store the article in the first
-		 * newsgroup's directory and to put symbolic links elsewhere.
-		 * If this is the first group, firstbufname is not yet filled
-		 * in. It should be portable to other link-less systems.
-		 * epimass!jbuck
-		 */
-		if (firstbufname[0]) {
-			if (vmslink(firstbufname, bfr) == 0)
-				break;
-		} else if (rename(ARTICLE, bfr) == 0)
-			break;
-#else /* !VMS */
-		if (link(ARTICLE, bfr) == 0)
-			break;
-#endif /* !VMS */
-		if (!exists(cp))
-			mknewsg(cp, ngname);
-#ifdef VMS
-		if (firstbufname[0]) {
-			if (vmslink(firstbufname, bfr) == 0)
-				break;
-		} else if (rename(ARTICLE, bfr) == 0) 
-			break;
-#else /* !VMS */
-		if (link(ARTICLE, bfr) == 0)
-			break;
-#endif /* !VMS */
-		e = errno;	/* keep log from clobbering it */
-		log("Cannot install article as %s: %s", bfr, errmsg(errno));
-		if (e != EEXIST) {
-			logerr("Link into %s failed (%s); check dir permissions.",
-			    bfr, errmsg(e));
-			unlock();
-			return FALSE;
-		}
-		ngsize++;
-	}
-
-	/*
-	 * This works around a bug in the 4.1bsd stdio
-	 * on fseeks to non even offsets in r+w files
-	 */
-	if (fpos&1)
-		(void) rewind(actfp);
-
-	(void) fseek(actfp, fpos, 0);
-#ifdef USG
-	/*
-	 * U G L Y   K L U D G E
-	 * This utter piece of tripe is the only way I know of to get
-	 * around the fact that ATT BROKE standard IO in System 5.2.
-	 * Basically, you can't open a file for "r+" and then try and
-	 * write to it. This works on all "real" USGUnix systems, It will
-	 * probably break on some obscure look alike that doesnt use the
-	 * real ATT stdio.h
-	 * Don't blame me, blame ATT. stdio should have already done the
-	 * following line for us, but it doesn't
-	 */
-	 actfp->_flag |= _IOWRT;
-#endif /* USG */
-	/* Has to be same size as old because of %05d.
-	 * This will overflow with 99999 articles.
-	 */
-	fprintf(actfp, "%s %05ld", ngname, ngsize+1);
-	(void) fflush(actfp);
-	if (ferror(actfp))
-		xerror("Active file write failed");
-	unlock();
-	if (firstbufname[0] == '\0')
-		(void) strcpy(firstbufname, bfr);
-	(void) sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
-	addhist(bfr);
-	return ngsize+1;
-}
-
-/*
- *	Localize for each newsgroup and broadcast.
- */
-insert()
-{
-	register char *ptr;
-	register FILE *tfp;
-	register int c;
-	struct srec srec;	/* struct for sys file lookup	*/
-	struct tm *tm, *gmtime();
-	int is_invalid = FALSE;
-	int exitcode = 0;
-	long now;
-#ifdef DOXREFS
-	register char *nextref = header.xref;
-#endif /* DOXREFS */
-
-	/* Clean up Newsgroups: line */
-	if (!is_ctl && mode != CREATENG)
-		is_invalid = ngfcheck(mode == PROC);
-
-	(void) time(&now);
-	tm = gmtime(&now);
-	if (header.expdate[0])
-		addhist(" ");
-#ifdef USG
-	sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d\t",
-#else /* !USG */
-	sprintf(bfr,"%02d/%02d/%d %02d:%02d\t",
-#endif /* !USG */
-		tm->tm_mon+1, tm->tm_mday, tm->tm_year,tm->tm_hour, tm->tm_min);
-	addhist(bfr);
-	log("%s %s ng %s subj '%s' from %s",
-		spool_news ? "queued" : (mode==PROC ? "received" : "posted"),
-		header.ident, header.nbuf, header.title, header.from);
-
-	/* Write article to temp file. */
-	tfp = xfopen(mktemp(ARTICLE), "w");
-
-	if (is_invalid) {
-		logerr("No valid newsgroups found, moved to junk");
-		if (localize("junk"))
-			savehist(histline);
-		exitcode = 1;
-		goto writeout;
-	}
-
-#ifdef ZAPNOTES
-	if (strcmp(header.title, "Re: Orphaned Response") == 0) {
-		logerr("Orphaned Response, moved to junk");
-		if (localize("junk"))
-			savehist(histline);
-		exitcode = 1;
-		goto writeout;
-	}
-#endif	/* ZAPNOTES */
-
-	if (time((time_t *)0) > (cgtdate(header.subdate) + HISTEXP) ){
-		logerr("Article too old, moved to junk");
-		if (localize("junk"))
-			savehist(histline);
-		exitcode = 1;
-		goto writeout;
-	}
-
-	if (is_mod[0] != '\0' 	/* one of the groups is moderated */
-		&& header.approved[0] == '\0') { /* and unapproved */
-		struct hbuf mhdr;
-		FILE *mfd;
-		register char *p;
-		char modadd[BUFLEN];
-#ifdef DONTFOWARD
-		if(mode == PROC) {
-			logerr("Unapproved article in moderated group %s",
-				is_mod);
-			if (localize("junk"))
-				savehist(histline);
-			goto writeout;
-		}
-#endif /* DONTFORWARD */
-		fprintf(stderr,"%s is moderated and may not be posted to",
-			is_mod);
-		fprintf(stderr," directly.\nYour article is being mailed to");
-		fprintf(stderr," the moderator who will post it for you.\n");
-		/* Let's find a path to the backbone */
-		sprintf(bfr, "%s/mailpaths", LIBDIR);
-		mfd = xfopen(bfr, "r");
-		do {
-			if (fgets(bfr, sizeof bfr, mfd) == NULL)
-				xerror("Can't find backbone in %s/mailpaths",
-					LIBDIR);
-		} while (!prefix(bfr, "backbone"));
-		if (sscanf(bfr, "%*s %s", modadd) != 1)
-			xerror("backbone address corrupted");
-		/* fake a header for mailhdr */
-		mhdr.from[0] = '\0';
-		mhdr.replyto[0] = '\0';
-		p = is_mod;
-		while (*++p)
-			if (*p == '.')
-				*p = '-';
-		sprintf(bfr, "Submission for %s", is_mod);
-		sprintf(mhdr.path, modadd, is_mod);
-		mfd = mailhdr(&mhdr, bfr);
-		if (mfd == NULL)
-			xerror("Can't send mail to %s", mhdr.path);
-		lhwrite(&header, mfd);
-		while ((c = getc(infp)) != EOF)
-			putc(c, mfd);
-		mclose(mfd);
-		log("Article mailed to %s", mhdr.path);
-		xxit(0);
-	}
-
-	if (spool_news && mode != PROC) {
-		fprintf(stderr,"Your article has been spooled for later processing.\n");
-		dospool((char *)NULL, TRUE);
-		/* NOT REACHED */
-	}
-
-	if (is_ctl) {
-		exitcode = control(&header);
-		if (localize("control") && exitcode != 0)
-			savehist(histline);
-	} else {
-		if (s_find(&srec, FULLSYSNAME) == FALSE) {
-			logerr("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE);
-			srec = dummy_srec;
-		}
-#ifdef DOXREFS
-		(void) strncpy(nextref, FULLSYSNAME, BUFLEN);
-#endif /* DOXREFS */
-		for (ptr = nbuf; *ptr;) {
-			if (ngmatch(ptr,srec.s_nbuf) || index(ptr,'.') == NULL){
-#ifdef DOXREFS
-				while (*nextref++)
-					;
-				(void) sprintf(--nextref, " %s:%ld", ptr, localize(ptr));
-#else /* !DOXREFS */
-				(void) localize(ptr);
-#endif /* !DOXREFS */
-			}
-			while (*ptr++)
-				;
-		}
-		if (firstbufname[0] == '\0') {
-			logerr("Newsgroups in active, but not sys");
-			(void) localize("junk");
-		}
-	}
-#ifdef DOXREFS
-	if (index(header.nbuf, NGDELIM) == NULL)
-		header.xref[0] = '\0';
-#endif /* DOXREFS */
-
-writeout:
-	/* Part 1 of kludge to get around article truncation problem */
-	if ( (c=getc(infp)) != EOF) {
-		ungetc(c, infp);
-		if (c == ' ' || c == '\t') {
-			header.intnumlines++;
-			(void) sprintf(header.numlines, "%d",
-				header.intnumlines);
-		}
-	}
-	/* End of part 1 */
-	if (header.expdate[0] != '\0' && mode != PROC) {
-		/* Make sure it's fully qualified */
-		long t = cgtdate(header.expdate);
-		strcpy(header.expdate, arpadate(&t));
-	}
-
-	lhwrite(&header, tfp);
-	if ((c = getc(infp)) != EOF) {
-		/* Part 2 of kludge to get around article truncation problem */
-		if (c == ' ' || c == '\t' )
-			putc('\n', tfp);
-		/* End of part 2 */
-		ungetc(c, infp);
-		while (fgets(bfr, BUFLEN, infp) != NULL)
-			fputs(bfr, tfp);
-		if (bfr[strlen(bfr)-1] != '\n')
-			putc('\n',tfp);
-	}
-	if (ferror(tfp))
-		xerror("Write failed for temp file");
-	(void) fclose(tfp);
-	(void) fclose(infp);
-	if(exitcode == 0) {
-		int pid;
-		/* article has passed all the checks, so work in background */
-		if (mode != PROC)
-			if ((pid=vfork()) < 0)
-				xerror("Can't fork");
-			else if (pid > 0)
-				exit(0);
-#ifdef SIGTTOU
-		signal(SIGTTOU, SIG_IGN);
-#endif /* SIGTTOU */
-		savehist(histline);
-		broadcast();
-	}
-	xxit(mode == PROC ? 0 : exitcode);
-}
-
-input()
-{
-	register char *cp;
-	register int c;
-	register int empty = TRUE;
-	FILE *tmpfp;
-	int consec_newlines = 0;
-	int linecount = 0;
-	int linserted = 0;
-
-	tmpfp = xfopen(mktemp(INFILE), "w");
-	while (!SigTrap && fgets(bfr, BUFLEN, infp) != NULL) {
- 		if (mode == PROC) {	/* zap trailing empty lines */
-#ifdef ZAPNOTES
-			if (empty && bfr[0] == '#' && bfr[2] == ':'
-				&& header.nf_id[0] == '\0'
-				&& header.nf_from[0] == '\0' ) {
-				(void) strcpy(header.nf_id, bfr);
-				(void) nstrip(header.nf_id);
-				(void) fgets(bfr, BUFLEN, infp);
-				(void) strcpy(header.nf_from, bfr);
-				(void) nstrip(header.nf_from);
-				(void) fgets(bfr, BUFLEN, infp);
-
-				if (header.numlines[0]) {
-					header.intnumlines -= 2;
-					(void) sprintf(header.numlines, "%d", header.intnumlines);
-				}
-
-				/* Strip trailing " - (nf)" */
-				if ((cp = rindex(header.title, '-')) != NULL
-				    && !strcmp(--cp, " - (nf)"))
-					*cp = '\0';
-				log("Stripped notes header on %s", header.ident);
-				continue;
-			}
-#endif /* ZAPNOTES */
- 			if (bfr[0] == '\n' ||
-				/* Bandage for older versions of inews */
-				bfr[1] == '\n' && !isascii(bfr[0])) {
- 				consec_newlines++;	/* count it, in case */
- 				continue;		/* but don't write it*/
- 			}
- 			/* foo! a non-empty line. write out all saved lines. */
- 			while (consec_newlines > 0) {
-				putc('\n', tmpfp);
-				consec_newlines--;
-				linecount++;
-			}
- 		}
-		if (mode != PROC && tty && strcmp(bfr, ".\n") == 0)
-			break;
-		for (cp = bfr; c = toascii(*cp); cp++) {
-			if (isprint(c) || isspace(c) || c == '\b')
-				putc(c, tmpfp);
-			if (c == '\n')
-				linecount++;
-		}
-		if (bfr[0] == '>')
-			linserted++;
-		empty = FALSE;
-	}
-	if (*filename)
-		(void) fclose(infp);
-	if (mode != PROC && linserted > (linecount-linserted))
-		error("Article rejected: %s included more text than new text",
-			username);
-
-	if (mode != PROC && !is_ctl && header.sender[0] == '\0') {
-		int siglines = 0;
-		char sbuf[BUFLEN];
-		(void) sprintf(bfr, "%s/%s", userhome, ".signature");
-		if (access(bfr, 4) == 0) {
-			if ((infp = fopen(bfr, "r")) == NULL) {
-				(void) fprintf(stderr,
-    "inews: \"%s\" left off (must be readable by \"inews\" owner)\n", bfr);
-				goto finish;
-			}
-
-			while (fgets(sbuf, sizeof sbuf, infp) != NULL)
-				if (++siglines > 4)
-					break;
-			if (siglines > 4)
-				fprintf(stderr,".signature not included (> 4 lines)\n");
-			else {
-				rewind(infp);
-				fprintf(tmpfp, "-- \n");	/* To separate */
-				linecount++;
-				while ((c = getc(infp)) != EOF) {
-					putc(c, tmpfp);
-					if (c == '\n')
-						linecount++;
-				}
-			}
-			(void) fclose(infp);
-		}
-	}
-
-finish:
-	if (ferror(tmpfp))
-		xerror("write failed to temp file");
-	(void) fclose(tmpfp);
-	if (SigTrap) {
-		if (tty)
-			fprintf(stderr, "Interrupt\n");
-		if (tty && !empty)
-			fwait(fsubr(newssave, (char *) NULL, (char *) NULL));
-		if (!tty)
-			log("Blown away by an interrupt %d", SigTrap);
-		xxit(1);
-	}
-	if (tty)
-		fprintf(stderr, "EOT\n");
-	fflush(stdout);
-	infp = fopen(INFILE, "r");
-	if (header.numlines[0]) {
-		/*
-		 * Check line count if there's already one attached to
-		 * the article.  Could make this a fatal error -
-		 * throwing it away if it got chopped, in hopes that
-		 * another copy will come in later with a correct
-		 * line count.  But that seems a bit much for now.
-		 */
-		if (linecount != header.intnumlines) {
-			if (linecount == 0)
-				error("%s rejected. linecount expected %d, got 0", header.ident, header.intnumlines);
-			if (linecount > header.intnumlines ||
-			    linecount+consec_newlines < header.intnumlines)
-				log("linecount expected %d, got %d", header.intnumlines, linecount+consec_newlines);
-		}
-		/* adjust count for blank lines we stripped off */
-		if (consec_newlines) {
-			header.intnumlines -= consec_newlines;
-			if (header.intnumlines < 0 )
-				header.intnumlines = 0; /* paranoia */
-			(void) sprintf(header.numlines, "%d", header.intnumlines);
-		}
-
-	} else {
-		/* Attach a line count to the article. */
-		header.intnumlines = linecount;
-		(void) sprintf(header.numlines, "%d", linecount);
-	}
-}
-
-/*
- * Make the directory for a new newsgroup.  ngname should be the
- * full pathname of the directory.  Do the other stuff too.
- * The various games with setuid and chown are to try to make sure
- * the directory is owned by NEWSUSR and NEWSGRP, which is tough to
- * do if you aren't root.  This will work on a UCB system (which allows
- * setuid(geteuid()) or a USG system (which allows you to give away files
- * you own with chown), otherwise you have to change your kernel to allow
- * one of these things or run with your dirs 777 so that it doesn't matter
- * who owns them.
- */
-mknewsg(fulldir, ngname)
-char	*fulldir;
-char	*ngname;
-{
-#ifdef USG
-	register char *p;
-	char parent[200];
-	char sysbuf[200];
-	struct stat sbuf;
-#endif /* USG */
-
-	if (ngname == NULL || !isalpha(ngname[0]))
-		xerror("Tried to make illegal newsgroup %s", ngname);
-
-#ifdef USG
-	/*
-	 * If the parent is 755 the setuid(getuid)
-	 * will fail, and since mkdir is suid, and our real uid is random,
-	 * the mkdir will fail.  So we have to temporarily chmod it to 777.
-	 */
-	(void) strcpy(parent, fulldir);
-	while (p = rindex(parent, '/')) {
-		*p = '\0';
-		if (stat(parent, &sbuf) == 0) {
-			(void) chmod(parent, 0777);
-			break;
-		}
-	}
-#endif /* USG */
-
-	/* Create the directory */
-	mkparents(fulldir);
-	if (mkdir(fulldir, 0777) < 0)
-		xerror("Cannot mkdir %s: %s", fulldir, errmsg(errno));
-
-#ifdef USG
-	(void) chmod(parent, (int)sbuf.st_mode);	/* put it back */
-	/*
-	 * Give away the directories we just created which were assigned
-	 * our real uid.
-	 */
-	(void) setuid(uid);
-	(void) chown(fulldir, duid, dgid);
-	(void) strcpy(sysbuf, fulldir);
-	while (p = rindex(sysbuf, '/')) {
-		*p = '\0';
-		/* stop when get to last known good parent */
-		if (strcmp(sysbuf, parent) == 0)
-			break;
-		(void) chown(sysbuf, duid, dgid);
-	}
-	(void) setuid(duid);
-#endif /* USG */
-
-	log("make newsgroup %s in dir %s", ngname, fulldir);
-}
-
-/*
- * If any parent directories of this dir don't exist, create them.
- */
-mkparents(dname)
-char *dname;
-{
-	char buf[200];
-	register char *p;
-
-	(void) strcpy(buf, dname);
-	p = rindex(buf, '/');
-	if (p)
-		*p = '\0';
-	if (exists(buf))
-		return;
-	mkparents(buf);
-	if (mkdir(buf, 0777) < 0)
-		xerror("Can not mkdir %s: %s", buf, errmsg(errno));
-}
-
-cancel()
-{
-	register FILE *fp;
-
-	log("cancel article %s", filename);
-	fp = fopen(filename, "r");
-	if (fp == NULL) {
-		log("article %s not found", filename);
-		return;
-	}
-	if (hread(&header, fp, TRUE) == NULL)
-		error("Article is garbled.");
-	(void) fclose(fp);
-	(void) unlink(filename);
-}
-
-dounspool()
-{
-	register DIR	*dirp;
-	register struct direct *dir;
-	register int foundsome;
-#ifdef VMS
-	sprintf(bfr, "%s/+rnews", SPOOLDIR);
-#else /* !VMS */
-	sprintf(bfr, "%s/.rnews", SPOOLDIR);
-#endif /* !VMS */
-
-	if (chdir(bfr) < 0)
-		xerror("chdir(%s):%s", bfr, errmsg(errno));
-
-	do {
-		foundsome = 0;
-		dirp = opendir(".");
-		if (dirp == NULL)	/* Boy are things screwed up */
-			xerror("opendir can't open .:%s", errmsg(errno));
-
-		while ((dir=readdir(dirp)) != NULL) {
-			if (dir->d_name[0] == '.')
-				continue;
-			sprintf(bfr,"%s -S -p %s", RNEWS, dir->d_name);
-			system(bfr);
-			(void) unlink(dir->d_name);
-			foundsome++;
-		}
-		closedir(dirp);
-	} while (foundsome); /* keep rereading the directory until it's empty */
-
-	xxit(0);
-}
*-*-END-of-src/inews.c-*-*
echo x - src/ifuncs.c 1>&2
sed 's/.//' >src/ifuncs.c <<'*-*-END-of-src/ifuncs.c-*-*'
-/*
- * This software is Copyright (c) 1986 by Rick Adams.
- *
- * Permission is hereby granted to copy, reproduce, redistribute or
- * otherwise use this software as long as: there is no monetary
- * profit gained specifically from the use or reproduction or this
- * software, it is not sold, rented, traded or otherwise marketed, and
- * this copyright notice is included prominently in any copy
- * made.
- *
- * The author make no claims as to the fitness or correctness of
- * this software for any use whatsoever, and it is provided as is. 
- * Any use of this software is at the user's own risk.
- *
- * ifuncs - functions used by inews.
- */
-
-#ifdef SCCSID
-static char	*SccsId = "@(#)ifuncs.c	2.57	10/29/86";
-#endif /* SCCSID */
-
-#include "iparams.h"
-#include <errno.h>
-
-/*LINTLIBRARY*/
-
-#define AFSIZ	4000	/* size of text in the active file for initial malloc */
-
-/*
- * Transmit this article to all interested systems.
- */
-
-#ifdef u370
-static struct srec srec;
-#endif /* u370 */
-
-static struct hbuf h, hh;
-
-#ifdef MULTICAST
-#define	MAXMCAST	20
-#define	MAXMCS		10
-
-struct multicast {
-	char mc_name[SBUFLEN];		/* "multi-cast" name */
-	short mc_syscnt;
-	char mc_tosys[MAXMCAST][SBUFLEN];
-} mcast[MAXMCS];
-
-static int mccount;
-#endif /* MULTICAST */
-
-#ifndef DBM
-char *histfile();
-#endif /* !DBM */
-
-#ifdef VMS
-/*
- * For VMS/Eunice there are no links: article was moved to firstbufname
- * before broadcast is reached.  So we read it from there.
- */
-extern char firstbufname[];
-#endif
-
-broadcast()
-{
-	register char *hptr;
-	register char *sptr;
-	register FILE *fp;
-#ifndef u370
-	struct srec srec;
-#endif
-	char sentbuf[LBUFLEN];
-	int nsent = 0;
-	char *sentsys;
-
-	/* h is a local copy of the header we can scribble on */
-#ifdef VMS
-	fp = xfopen (firstbufname, "r");
-#else
-	fp = xfopen(ARTICLE, "r");
-#endif
-	if (hread(&h, fp, TRUE) == NULL)
-		xerror("Cannot reread article");
-	(void) fclose(fp);
-
-	(void) strcpy(sentbuf, h.ident);
-	(void) strcat(sentbuf, " sent to ");
-	sentsys = index(sentbuf, 0);
-	nsent = 0;
-	/* break path into list of systems. */
-	sptr = hptr = h.path;
-	while ((hptr=strpbrk(hptr, NETCHRS)) != NULL) {
-		*hptr++ = '\0';
-		sptr = hptr;
-	}
-	*sptr = '\0';
-
-#ifdef MULTICAST
-	mccount = 0;
-#endif /* MULTICAST */
-
-	/* loop once per system. */
-	s_openr();
-	while (s_read(&srec)) {
-		char *dist = h.distribution;
-#ifdef HIDDENNET
-		if (strncmp(srec.s_name, LOCALSYSNAME, SNLN) == 0)
-			continue;
-#endif /* HIDDENNET */
-		if (strncmp(srec.s_name, FULLSYSNAME, SNLN) == 0)
-			continue;
-		if (sptr = srec.s_nosend) {
-			while (*sptr) {
-				while (*sptr && *sptr != ',')
-					sptr++;
-				if (*sptr == ',')
-					*sptr++ = '\0';
-			}
-			*++sptr = '\0';
-		}
-		hptr = h.path;
-		while (*hptr != '\0') {
-			if (strncmp(srec.s_name, hptr, SNLN) == 0)
-				goto contin;
-			if (sptr = srec.s_nosend) {
-				while (*sptr != '\0') {
-					if (strncmp(sptr, hptr, SNLN) == 0)
-						goto contin;
-					while (*sptr++)
-						;
-				}
-			}
-			while (*hptr++ != '\0')
-				;
-		}
-		if (!ngmatch(h.nbuf, srec.s_nbuf))
-			continue;
-		if (*dist == '\0')
-			dist = "world";
-		if (!ngmatch(dist, srec.s_nbuf) && !ngmatch(srec.s_nbuf, dist))
-			    continue;
-
-		if (nsent) {
-			hptr = sentsys;
-			while ((sptr = index(hptr, ',')) != NULL) {
-				*sptr = '\0';
-				if (strcmp(hptr, srec.s_name) == 0) {
-					*sptr = ',';
-					goto contin;
-				}
-				*sptr++ = ',';
-				for (hptr = sptr; isspace(*hptr); hptr++)
-					;
-			}
-			if (strcmp(hptr, srec.s_name) == 0)
-				continue;
-		}
-		/* now we've found a system to send this article to */
-#ifdef MULTICAST
-		if (index(srec.s_flags, 'M')) {
-			/* do a "multi-cast" transmit */
-			register struct multicast *m;
-
-			if (strlen(srec.s_name) >= SBUFLEN ||
-			    strlen(srec.s_xmit) >= SBUFLEN)
-				xerror("system name too long for multicast");
-			for (m = mcast; m < &mcast[mccount]; m++)
-				if (strcmp(srec.s_xmit, m->mc_name) == 0)
-					break;
-			if (m >= &mcast[MAXMCS])
-				xerror("Too many multicasts");
-			if (m == &mcast[mccount]) {
-				mccount++;
-				m->mc_syscnt = 0;
-				strcpy(m->mc_name, srec.s_xmit);
-			}
-			if (m->mc_syscnt >= MAXMCAST)
-				xerror("Too many systems for multicast");
-			strcpy(m->mc_tosys[m->mc_syscnt++], srec.s_name);
-		} else {
-			register struct multicast *m;
-			register char **yptr;
-			char *sysptrs[MAXMCAST];
-			int mc;
-
-			mc = 0;
-			for (m = mcast; m < &mcast[mccount]; m++)
-				if (strcmp(m->mc_name, srec.s_name) == 0) {
-					yptr = sysptrs;
-					while (mc < m->mc_syscnt)
-						*yptr++ = m->mc_tosys[mc++];
-					break;
-				}
-#ifdef VMS
-			if (!transmit(&srec, xfopen(firstbufname,"r"), 1,
-				sysptrs, mc))
-#else /* !VMS */
-			if (!transmit(&srec, xfopen(ARTICLE,"r"), 1, sysptrs,
-				mc))
-#endif /* !VMS */
-				continue;
-		}
-#else /* !MULTICAST */
-#ifdef VMS
-		if (!transmit(&srec, xfopen(firstbufname, "r"),
-#else /* !VMS */
-		if (!transmit(&srec, xfopen(ARTICLE, "r"),
-#endif /* !VMS */
-			(strncmp(h.nbuf, "to.", 3) != 0),
-			(char **) NULL, FALSE))
-				continue;
-#endif /* !MULTICAST */
-		if (nsent)
-			(void) strcat(sentbuf, ", ");
-		(void) strcat(sentbuf, srec.s_name);
-		nsent++;
-	contin:;
-	}
-	if (nsent)
-		log(sentbuf);
-	s_close();
-}
-
-/*
- * Transmit file to system.
- */
-#define PROC 0004
-#ifndef MULTICAST
-/* ARGSUSED */
-#endif /* !MULTICAST */
-transmit(sp, ifp, maynotify, sysnames, mc)
-register struct srec *sp;
-register FILE *ifp;
-int maynotify;
-char **sysnames;
-int mc;
-{
-	register FILE *ofp;
-	register int c;
-	register char *ptr;
-	char TRANS[BUFLEN];
-	char *argv[20];
-	register int pid;
-	extern char firstbufname[];
-
-/* A:	afmt: the other machine runs an A news, so we xmit in A format */
-	int afmt = (index(sp->s_flags, 'A') != NULL);
-/* B:	use B format (this is the default - don't use this letter elsewise). */
-/* F:	append name to file */
-	int appfile = (index(sp->s_flags, 'F') != NULL);
-/* L:	local: don't send the article unless it was generated locally */
-	int local = ((ptr = index(sp->s_flags, 'L')) != NULL);
-/* H:	interpolate history line into command, use existing file */
-	int history = (index(sp->s_flags, 'H') != NULL);
-/* m:	moderated: only send if group is moderated */
-	int sendifmoderated = (index(sp->s_flags, 'm') != NULL);
-/* u:	unmoderated: only send if group is unmoderated */
-	int sendifunmoderated = (index(sp->s_flags, 'u') != NULL);
-/* M:	multi-cast: this is taken care of above, but don't reuse flag */
-#ifdef MULTICAST
-/* O:	multi-cast only, don't send article if not multicast hosts */
-	int multisend = (index(sp->s_flags, 'O') != NULL);
-#endif /* MULTICAST */
-/* N:	notify: don't send the article, just tell him we have it */
-	int notify = maynotify && (index(sp->s_flags, 'N') != NULL);
-/* S:	noshell: don't fork a shell to execute the xmit command */
-	int noshell = (index(sp->s_flags, 'S') != NULL);
-/* U:	useexist: use the -c option to uux to use the existing copy */
-	int useexist = (index(sp->s_flags, 'U') != NULL);
-/* I:	append messageid to file. implies F flag */
-	int appmsgid = maynotify && (index(sp->s_flags, 'I') != NULL);
-
-	if (notify)
-		appfile = appmsgid = FALSE;
-
-	if (!appfile)
-		appfile = appmsgid;
-
-	if (local && mode == PROC) {
-		local = 0;
-		while (isdigit(*++ptr))
-			local = local * 10 + *ptr - '0';
-		for (ptr = h.path; *ptr != '\0' && local >= 0; local--)
-			while (*ptr++ != '\0')
-				;
-		if (local < 0) {
-			(void) fclose(ifp);
-			return FALSE;
-		}
-	}
-
-	/*
-	** Do not transmit to system specified in -x flag.
-	*/
-	if (not_here[0] && strcmp(not_here, sp->s_name) == 0) {
-		(void) fclose(ifp);
-		return FALSE;
-	}
-
-#ifdef DEBUG
-	printf("Transmitting to '%s'\n", sp->s_name);
-#endif /* DEBUG */
-
-#ifdef MULTICAST
-	if (multisend && mc == 0) {
-		(void) fclose(ifp);
-		return FALSE;
-	}
-#endif /* MULTICAST */
-
-	if ((sendifmoderated && is_mod[0] == '\0') ||
-	    (sendifunmoderated && is_mod[0] != '\0')) {
-		fclose(ifp);
-		return FALSE;
-	}
-
-	if (appmsgid || (!appfile && !useexist && !history)) {
-		if (!hread(&hh, ifp, TRUE)) {
-			logerr("Bad header, not transmitting %s re %s to %s",
-				hh.ident, hh.title, sp->s_name);
-			(void) fclose(ifp);
-			return FALSE;
-		}
-		if (hh.nbuf[0] == '\0') {
-			fprintf(stderr, "Article not subscribed to by %s\n", sp->s_name);
-			(void) fclose(ifp);
-			return FALSE;
-		}
-		(void) sprintf(TRANS, "%s/trXXXXXX", SPOOL);
-	}
-
-	if (notify) {
-		char oldid[50];
-		(void) sprintf(hh.title, "ihave %s %s", hh.ident, FULLSYSNAME);
-		(void) strcpy(hh.ctlmsg, hh.title);
-		(void) strcpy(hh.numlines, "0");
-		(void) sprintf(hh.nbuf, "to.%s.ctl", sp->s_name);
-		(void) strcpy(oldid, hh.ident);
-		getident(&hh);
-		log("tell %s about %s, notif. id %s",
-			sp->s_name, oldid, hh.ident);
-	}
-
-	if (appfile) {
-		if (firstbufname[0] == '\0') {
-			extern char histline[];
-			localize("junk");
-			savehist(histline);
-			xerror("No file name to xmit from");
-		}
-		if (sp->s_xmit[0] == '\0')
-			sprintf(sp->s_xmit, "%s/%s%s", BATCHDIR, sp->s_name,
-				appmsgid ? ".ihave" : "");
-#ifdef IHCC
-		(void) sprintf(TRANS, "%s/%s/%s", logdir(HOME), BATCHDIR, sp->s_xmit);
-		ofp = fopen(TRANS, "a");
-#else /* !IHCC */
-		ofp = fopen(sp->s_xmit, "a");
-#endif /* !IHCC */
-		if (ofp == NULL)
-			xerror("Cannot append to %s", sp->s_xmit);
-		fprintf(ofp, "%s", appmsgid ? hh.ident : firstbufname);
-#ifdef MULTICAST
-		while (--mc >= 0)
-			fprintf(ofp, " %s", *sysnames++);
-#endif /* !MULTICAST */
-		putc('\n', ofp);
-		(void) fclose(ofp);
-		(void) fclose(ifp);
-		return TRUE;
-	}
-	else if (useexist) {
-		if (firstbufname[0] == '\0')
-			xerror("No file name to xmit from");
-		if (*sp->s_xmit == '\0')
-#ifdef UXMIT
-			(void) sprintf(bfr, UXMIT, sp->s_name, firstbufname);
-#else
-			xerror("UXMIT not defined for U flag");
-#endif
-		else
-#ifdef MULTICAST
-			makeargs(bfr, sp->s_xmit, firstbufname, sysnames, mc);
-#else
-			(void) sprintf(bfr, sp->s_xmit, firstbufname);
-#endif
-		(void) fclose(ifp);
-	} else if (history) {
-		extern char histline[];
-
-		if (*sp->s_xmit == '\0')
-			xerror("no xmit command with H flag");
-#ifdef MULTICAST
-		makeargs(bfr, sp->s_xmit, histline, sysnames, mc);
-#else
-		(void) sprintf(bfr, sp->s_xmit, histline);
-#endif
-	} else {
-		ofp = xfopen(mktemp(TRANS), "w");
-		if (afmt) {
-#ifdef OLD
-			fprintf(ofp, "A%s\n%s\n%s!%s\n%s\n%s\n", oident(hh.ident), hh.nbuf, FULLSYSNAME,
-				hh.path, hh.subdate, hh.title);
-#else /* !OLD */
-			logerr("Must have OLD defined to use A flag for xmit");
-			return FALSE;
-#endif /* !OLD */
-		} else
-			hwrite(&hh, ofp);
-		if (!notify)
-			while ((c = getc(ifp)) != EOF)
-				putc(c, ofp);
-		if (ferror(ofp))
-			xerror("write failed on transmit");
-		(void) fclose(ifp);
-		(void) fclose(ofp);
-		if (*sp->s_xmit == '\0')
-			(void) sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
-		else
-#ifdef MULTICAST
-			makeargs(bfr, sp->s_xmit, TRANS, sysnames, mc);
-#else /* !MULTICAST */
-			(void) sprintf(bfr, sp->s_xmit, TRANS);
-#endif /* !MULTICAST */
-	}
-
-	/* At this point, the command to be executed is in bfr. */
-	if (noshell) {
-		if (pid = vfork())
-			fwait(pid);
-		else {
-			(void) close(0);
-			(void) open(TRANS, 0);
-			ptr = bfr;
-			for (pid = 0; pid < 19; pid++) {
-				while (isspace(*ptr))
-					*ptr++ = 0;
-				argv[pid] = ptr;
-				while (!isspace(*++ptr) && *ptr)
-					;
-				if (!*ptr)
-					break;
-			}
-			argv[++pid] = 0;
-			(void) setgid(gid);
-			(void) setuid(uid);
-			execv(argv[0], argv);
-			xerror("Can't execv %s", argv[0]);
-		}
-	} else {
-		if (!history && sp->s_xmit[0] && !index(bfr, '<')) {
-			char newcmd[LBUFLEN];
-
-			(void) sprintf(newcmd, "(%s) <%s", bfr,
-			    useexist ? firstbufname : TRANS);
-			system(newcmd);
-		} else
-			system(bfr);
-	}
-	if (!appfile && !useexist && !history)
-		(void) unlink(TRANS);
-	(void) fclose(ifp);
-	return TRUE;
-}
-
-#ifdef MULTICAST
-makeargs(buf, cmd, arg2, sysargs, sac)
-char *buf;
-char *cmd;
-char *arg2;
-register char **sysargs;
-int sac;
-{
-	register char *p = cmd;
-	register char *q;
-	register ac = 0;
-	register char *b = buf;
-
-	q = p;
-	do {
-		if (q = index(q, ' '))
-			*q = '\0';
-		if (index(p, '%')) {
-			switch (++ac) {
-			case 1:
-				while (--sac >= 0) {
-					sprintf(b, p, *sysargs++);
-					b = index(b, '\0');
-				}
-				break;
-			case 2:
-				sprintf(b, p, arg2);
-				b = index(b, '\0');
-				break;
-			default:
-				if (q)
-					*q = ' ';
-				xerror("badly formed command: %s", cmd);
-			}
-		} else {
-			strcpy(b, p);
-			b = index(b, '\0');
-		}
-		if (q) {
-			*q = ' ';
-			p = q;
-			while (isspace(*q))
-				q++;
-		}
-	} while (q != NULL);
-}
-#endif /* MULTICAST */
-
-typedef struct {
-	char *dptr;
-	int dsize;
-} datum;
-
-/*
- * Return TRUE if we have seen this file before, else FALSE.
- */
-history(hp)
-struct hbuf *hp;
-{
-#ifdef DBM
-	datum lhs, rhs;
-	datum fetch();
-#else /* !DBM */
-	register FILE *hfp;
-	register char *p;
-#endif /* !DBM */
-	char lcident[BUFLEN];
-	extern char histline[];
-
-#ifdef DEBUG
-	fprintf(stderr,"history(%s)\n", hp->ident);
-#endif /* DEBUG */
-	/*
-	 * Make the article ID case insensitive.
-	 */
-	(void) strcpy(lcident, hp->ident);
-	lcase(lcident);
-
-	idlock(lcident);
-#ifdef DBM
-	initdbm(ARTFILE);
-	lhs.dptr = lcident;
-	lhs.dsize = strlen(lhs.dptr) + 1;
-	rhs = fetch(lhs);
-	if (rhs.dptr)
-		return(TRUE);
-#else /* !DBM */
-	hfp = xfopen(histfile(lcident), "r");
-	while (fgets(bfr, BUFLEN, hfp) != NULL) {
-		p = index(bfr, '\t');
-		if (p == NULL)
-			p = index(bfr, '\n');
-		if (p != NULL)	/* can happen if nulls in file */
-			*p = 0;
-		lcase(bfr);
-
-		if (strcmp(bfr, lcident) == 0) {
-			(void) fclose(hfp);
-			idunlock();
-#ifdef DEBUG
-			fprintf(stderr,"history returns true\n");
-#endif /* DEBUG */
-			return TRUE;
-		}
-	}
-	(void) fclose(hfp);
-#endif /* !DBM */
-	histline[0] = '\0';
-	addhist(hp->ident);
-	addhist("\t");
-#ifdef DEBUG
-	fprintf(stderr,"history returns false\n");
-#endif
-	return FALSE;
-}
-
-char histline[PATHLEN];
-
-addhist(msg)
-char *msg;
-{
-	(void) strcat(histline, msg);
-}
-
-savehist(hline)
-char *hline;
-{
-	register FILE *hfp;
-	datum lhs, rhs;
-	long fpos;
-	register char *p;
-
-	hfp = xfopen(ARTFILE, "a");
-	(void) fseek(hfp, 0L, 2); /* Unisoft 5.1 doesn't seek to EOF on 'a' */
-	fpos = ftell(hfp);
-	fprintf(hfp, "%s\n", hline);
-	(void) fclose(hfp);
-#ifdef DBM
-	/* We assume that history has already been called, calling dbminit. */
-	p = index(hline, '\t');
-	if (p)
-		*p = 0;
-	lcase(hline);
-	lhs.dptr = hline;
-	lhs.dsize = strlen(lhs.dptr) + 1;
-	rhs.dptr = (char *)&fpos;
-	rhs.dsize = sizeof fpos;
-	store(lhs, rhs);
-#else /* !DBM */
-	/* also append to proper history subfile */
-	hfp = xfopen(histfile(hline), "a");
-	fprintf(hfp, "%s\n", hline);
-	(void) fclose(hfp);
-#endif /* !DBM */
-	idunlock();
-}
-
-/*
- * Save partial news.
- */
-/* ARGSUSED */
-newssave(fd, dummy)
-FILE *fd;
-char *dummy;
-{
-	register FILE *tofd, *fromfd;
-	char sfname[BUFLEN];
-	register int c;
-	time_t tim;
-
-	if (fd == NULL)
-		fromfd = xfopen(INFILE, "r");
-	else
-		fromfd = fd;
-	(void) umask(savmask);
-	(void) setgid(gid);
-	(void) setuid(uid);
-
-	(void) sprintf(sfname, "%s/%s", userhome, PARTIAL);
-	if ((tofd = fopen(sfname, "a")) == NULL)
-		xerror("Cannot save partial news in %s", sfname);
-	(void) time(&tim);
-	fprintf(tofd, "----- News saved at %s\n", arpadate(&tim));
-	while ((c = getc(fromfd)) != EOF)
-		putc(c, tofd);
-	(void) fclose(fromfd);
-	(void) fclose(tofd);
-	printf("News saved in %s\n", sfname);
-	xxit(1);
-}
-
-/*
- * Handle dates in header.
- */
-
-dates(hp)
-struct hbuf *hp;
-{
-	time_t edt;
-
-	if (*hp->subdate) {
-		if (cgtdate(hp->subdate) < 0) {
-			error("Cannot parse submittal date '%s'", hp->subdate);
-		}
-	} else {
-		(void) time(&edt);
-		(void) strcpy(hp->subdate, arpadate(&edt));
-	}
-}
-
-#define LOCKSIZE	128
-char lockname[LOCKSIZE];
-
-idlock(str)
-char *str;
-{
-	register int i;
-	register char *cp, *scp;
-	char tempname[LOCKSIZE];
-	time_t now;
-	struct stat sbuf;
-	extern int errno;
-#ifdef	VMS
-	int fd;
-
-	(void) sprintf(lockname, "/tmp/%s.l.1", str);
-	while ((fd = creat(lockname, 0444)) < 0) {
-#else /* !VMS */
-	(void) strcpy(tempname, "/tmp/LTMP.XXXXXX");
-	(void) mktemp(tempname);
-	(void) strcpy(lockname, "/tmp/L");
-	i = strlen(lockname);
-	cp = &lockname[i];
-	scp = str - 1;
-	while (i++ < LOCKSIZE && *++scp != '\0')
-		if (*scp == '/')	/* slash screws up the open */
-			*cp++ = '.';
-		else
-			*cp++ = *scp;
-	*cp = '\0';
-#ifdef FOURTEENMAX
-	lockname[5 /* /tmp/ */ + 14] = '\0';
-#endif
-	i = creat(tempname, 0666);
-	if (i < 0)
-		xerror("Cannot creat %s: errno %d", tempname, errno);
-	(void) close(i);
-	while (link(tempname, lockname)) {
-#endif /* !VMS */
-		(void) time(&now);
-		if (stat(lockname, &sbuf) < 0)
-			xerror("Directory permission problem in /tmp");
-
-		if (sbuf.st_mtime + 10*60 < now) {
-			(void) unlink(lockname);
-			logerr("Article %s locked up", str);
-			break;
-		}
-		log("waiting on lock for %s", lockname);
-		sleep((unsigned)60);
-	}
-#ifdef VMS
-	(void) close(fd);
-#endif
-	(void) unlink(tempname);
-}
-
-idunlock()
-{
-	(void) unlink(lockname);
-}
-
-/*
- * Put a unique name into header.ident.
- */
-getident(hp)
-struct hbuf *hp;
-{
-	long seqn;
-	register FILE *fp;
-
-	lock();
-	fp = xfopen(SEQFILE, "r");
-	(void) fgets(bfr, BUFLEN, fp);
-	(void) fclose(fp);
-	seqn = atol(bfr) + 1;
-/*
- * For Eunice, this breaks if SEQFILE is not in Unix format.
- */
-	fp = xfopen(SEQFILE, "r+w");
-	fprintf(fp, "%ld\n", seqn);
-	(void) fclose(fp);
-	unlock();
-#ifdef HIDDENNET
-	if (strcmp(LOCALSYSNAME, FULLSYSNAME))
-		(void) sprintf(hp->ident, "<%ld@%s.%s%s>", seqn, LOCALSYSNAME, FULLSYSNAME,
-		MYDOMAIN);
-	else
-#endif /* !HIDDENNET */
-	(void) sprintf(hp->ident, "<%ld@%s%s>", seqn, FULLSYSNAME, MYDOMAIN);
-}
-
-/*
- * Check that header.nbuf contains only valid newsgroup names;
- * exit with error if not valid.
- */
-ngfcheck(isproc)
-{
-	register FILE *	f;
-	register char *	cp;
-	register int	i, j;
-	register int	ngcount, okcount, havealiased;
-	register int	pass;
-	char *		ngs[sizeof header.nbuf / 2];
-	char		uses[sizeof header.nbuf / 2];
-	char		tbuf[sizeof header.nbuf];
-	char		abuf[BUFLEN];
-
-	havealiased = ngcount = 0;
-	is_mod[0] = '\0';
-	/*
-	** Split header.nbuf into constituent newsgroups.
-	** Zap "local" newsgroups of articles from remote sites.
-	*/
-	cp = tbuf;
-	(void) strcpy(cp, header.nbuf);
-	for ( ; ; ) {
-		while (*cp == NGDELIM || *cp == ' ')
-			++cp;
-		if (*cp == '\0')
-			break;
-		ngs[ngcount] = cp;
-		do {
-			++cp;
-		} while (*cp != '\0' && *cp != NGDELIM && *cp != ' ');
-		if (*cp != '\0')
-			*cp++ = '\0';
-		/*
-		** Check for local only distribution on incoming
-		** newsgroups.  This might occur if someone posted to
-		** general,net.unix
-		*/
-		if (isproc && index(ngs[ngcount], '.') == NULL &&
-			index(header.nbuf, '.') != NULL) {
-				logerr("Local group '%s' removed",
-					ngs[ngcount]);
-				continue;
-		}
-		uses[ngcount] = 1;	/* it should go in "Newsgroups" line */
-		++ngcount;
-	}
-	/*
-	** Check groups against active file.
-	*/
-recheck:
-	okcount = 0;
-	rewind(actfp); clearerr(actfp);
-	while (okcount < ngcount && fgets(bfr, BUFLEN, actfp) == bfr) {
-		if ((cp = index(bfr, ' ')) == NULL)
-			continue;	/* strange line in input! */
-		/* newsgroup 12345 12345 X */
-		/*  cp +    01234567890123 */
-		if (!isproc && cp[13]  == 'n')
-			continue;	/* can't post to this group! */
-		*cp = '\0';
-		for (i = 0; i < ngcount; ++i)
-			if (uses[i] >= 1 && strcmp(bfr, ngs[i]) == 0) {
-				uses[i] = 2;	/* it should be localized too */
-				if (cp[13] == 'm')
-					strcpy(is_mod, bfr);
-				++okcount;
-			}
-	}
-#ifdef ALWAYSALIAS
-	okcount = 0;
-#endif /* ALWAYSALIAS */
-	/*
-	** Handle groups absent from active file.
-	*/
-	if (havealiased == 0 && okcount < ngcount) {
-		/*
-		** See if remaining groups are in our alias list.
-		*/
-		f = xfopen(ALIASES, "r");
-		while (okcount < ngcount && fscanf(f, "%s %s", abuf, bfr) == 2)
-			for (i = 0; i < ngcount; ++i) {
-#ifndef ALWAYSALIAS
-				if (uses[i] == 2)
-					continue;
-#endif /* ALWAYSALIAS */
-				if (strcmp(ngs[i], abuf) != 0)
-					continue;
-				if (isproc)
-					cp = "Aliased newsgroup %s to %s";
-				else
-					cp = "Please change %s to %s";
-				logerr(cp, abuf, bfr);
-				ngs[i] = AllocCpy(bfr);
-				uses[i] = 2;
-				++havealiased;
-				++okcount;
-			}
-		(void) fclose(f);
-		for (i = 0; i < ngcount; ++i) {
-			if (uses[i] == 2)
-				continue;
-			if (isproc)
-				cp = "Unknown newsgroup '%s' not localized";
-			else
-				cp = "Unknown newsgroup '%s'";
-			logerr(cp, ngs[i]);
-#ifdef ALWAYSALIAS
-			++okcount;	/* so we know to exit below */
-		}
-		if (!isproc && okcount > 0)
-#else /* !ALWAYSALIAS */
-		}
-		if (!isproc)
-#endif /* !ALWAYSALIAS */
-			newssave(infp, (char *) NULL);
-		/*
-		 * Unfortunately, if you alias an unmoderated group to a
-		 * moderated group, you must recheck the active file to see
-		 * if the new group is moderated. Rude but necessary.
-		 */
-		if (havealiased)
-			goto recheck;	
-	}
-	/*
-	** Zap duplicates.
-	*/
-	for (i = 0; i < ngcount - 1; ++i) {
-		if (uses[i] == 0)
-			continue;
-		for (j = i + 1; j < ngcount; ++j) {
-			if (uses[j] == 0)
-				continue;
-			if (strcmp(ngs[i], ngs[j]) != 0)
-				continue;
-			logerr("Duplicate '%s' removed", ngs[j]);
-			if (uses[i] < uses[j])
-				uses[i] = uses[j];
-			uses[j] = 0;
-		}
-	}
-	for (pass = 1; pass <= 2; ++pass) {
-		register int	avail;
-
-		if (pass == 1) {
-			/*
-			** Rewrite header.nbuf.
-			*/
-			cp = header.nbuf;
-			avail = sizeof header.nbuf;
-		} else {
-			/*
-			** Fill in nbuf.
-			*/
-			cp = nbuf;
-			avail = sizeof nbuf;
-		}
-		for (i = 0; i < ngcount; ++i) {
-			if (uses[i] < pass)
-				continue;
-			j = strlen(ngs[i]);
-			if (j + 2 > avail) {
-				logerr("Redone Newsgroups too long");
-				break;
-			}
-			(void) strcpy(cp, ngs[i]);
-			cp += j;
-			*cp++ = (pass == 1) ? NGDELIM : '\0';
-			avail -= (j + 1);
-		}
-		if (pass == 1) {
-			if (cp == header.nbuf)
-				*cp = '\0';
-			else	*(cp - 1) = '\0';
-		} else	*cp = '\0';
-	}
-	/*
-	** Free aliases.
-	*/
-	for (i = 0; i < ngcount; ++i)
-		if (ngs[i] < tbuf || ngs[i] > &tbuf[sizeof tbuf - 1])
-			free(ngs[i]);
-	return nbuf[0] == '\0';
-}
-
-/*
- * Figure out who posted the article (which is locally entered).
- * The results are placed in the header structure hp.
- */
-gensender(hp, logname)
-struct hbuf *hp;
-char *logname;
-{
-	register char *fn, *p;
-	char buf[BUFLEN];
-	char *fullname(), *getenv();
-	int fd, n;
-
-	if ((fn = getenv("NAME")) == NULL) {
-		(void) sprintf(buf, "%s/%s", userhome, ".name");
-		if ((fd = open(buf, 0)) >= 0) {
-			n = read(fd, buf, sizeof buf);
-			(void) close(fd);
-			if (n > 0 && buf[0] >= 'A') {
-				for (p = fn = buf; *p; p++)
-					if (*p < ' ')
-						*p = '\0';
-			}
-		}
-	}
-
-	if (fn == NULL)
-		fn = fullname(logname);
-
-	(void) sprintf(hp->path, "%s", logname);
-	(void) sprintf(hp->from, "%s@%s%s (%s)", logname, FULLSYSNAME, MYDOMAIN, fn);
-}
-
-/*
- * Trap interrupts.
- */
-onsig(n)
-int n;
-{
-	static int numsigs = 0;
-	/*
-	 * Most UNIX systems reset caught signals to SIG_DFL.
-	 * This bad design requires that the trap be set again here.
-	 * Unfortunately, if the signal recurs before the trap is set,
-	 * the program will die, possibly leaving the lock in place.
-	 */
-	if (++numsigs > 100) {
-		logerr("inews ran away looping on signal %d", n);
-		xxit(1);
-	}
-	(void) signal(n, onsig);
-	SigTrap = n;
-}
-
-#ifdef BATCH
-/*
- * If the stdin begins with "#", we assume we have been fed a batched
- * shell script which looks like this:
- *	#! rnews 1234
- *	article with 1234 chars
- *	#! rnews 4321
- *	article with 4321 chars
- *
- * In this case we just exec the unbatcher and let it unpack and call us back.
- *
- * Note that there is a potential security hole here.  If the batcher is
- * /bin/sh, someone could ship you arbitrary stuff to run as shell commands.
- * The main protection you have is that the effective uid will be news, not
- * uucp and not the super user.  (That, plus the fact that BATCH is set to
- * "unbatch" as the system is distributed.)  If you want to run a batched link
- * and you are security conscious, do not use /bin/sh as the unbatcher.
- * the thing to do is to change BATCH in your localize.sh file from /bin/sh
- * to some restricted shell which can only run rnews.
- */
-checkbatch()
-{
-	int c;
-
-	c = getc(infp);
-	if (c != EOF)
-		(void) ungetc(c, infp);
-	clearerr(infp);
-	if (c == '#') {
-		char cmd[BUFLEN], unbatcher[BUFLEN], arg1[BUFLEN], arg2[BUFLEN];
-		register char *cp;
-		int n;
-
-		reset_infp();
-		/*
-		 * For efficiency, try and recognize the most common
-		 * forms of batching and exec them directly
-		 */
-		n = read(0, cmd, BUFLEN-1);
-		if (n <= 0)	/* Can't happen */
-			xerror("can't read stdin to unbatch");
-		cmd[n] = '\0';
-		cp = index(cmd, '\n');
-		if (cp)
-			*cp = '\0';
-		/* now put stdin at the "right" place for the exec */
-		(void) lseek(0,1L+(long)(cp - cmd), 0);
-		if( strncmp(cmd, "#! cunbatch", 11) == 0) {
-			(void) strcpy(unbatcher, "/bin/sh");
-			(void) strcpy(arg1, "-c");
-			(void) sprintf(arg2, "%s/compress -d | %s/%s",
-				LIB, LIB, BATCH);
-		} else if (strncmp(cmd, "#! c7unbatch", 12) == 0) {
-			(void) strcpy(unbatcher, "/bin/sh");
-			(void) strcpy(arg1, "-c");
-			(void) sprintf(arg2,
-				"%s/decode | %s/compress -d | %s/%s",
-				LIB, LIB, LIB, BATCH);
-		} else {
-			(void) lseek(0, 0L, 0);
-			(void) sprintf(unbatcher, "%s/%s", LIB, BATCH);
-			arg1[0] = '\0';
-			arg2[0] = '\0';
-		}
-		execl(unbatcher, "news-unpack", arg1, arg2, (char *)0);
-		xerror("Unable to exec %s to unpack news.", unbatcher);
-	}
-}
-
-/*
- * We've already done a read on stdin, and we want to seek back to the
- * beginning.  We want the real file descriptor (beyond buffers) to
- * reflect the true beginning.  Do whatever is necessary.
- */
-reset_infp()
-{
-	register FILE *ofd;
-	register int c;
-	char *ofdname;
-	long lseek();
-
-	/* First try to seek back - if so, it's a cheap way back. */
-	if (lseek(0, 0L, 0) == 0L)
-		return;
-
-	/* Can't seek, so have to copy input to a file and use that. */
-	ofdname = "/tmp/inewsXXXXXX";
-	(void) mktemp(ofdname);
-	ofd = fopen(ofdname, "w");
-	while ((c=getc(infp)) != EOF)
-		putc(c, ofd);
-	if (ferror(ofd))
-		xerror("write failed on temp file %s", ofdname);
-	(void) fclose(ofd);
-	(void) fclose(infp);
-
-	/* Now for a few lower level hacks to reopen stdin and make
-	 * absolutely sure that the right fd's are done for the exec.
-	 */
-	(void) close(0);		/* make sure stdin is really closed. */
-	(void) open(ofdname, 0);
-	(void) unlink(ofdname);		/* to avoid cleaning it up later. */
-}
-#endif /* BATCH */
-
-/*
- *	Exit and cleanup.
- */
-xxit(status)
-int status;
-{
-	(void) unlink(INFILE);
-	(void) unlink(ARTICLE);
-	while (lockcount > 0)
-		unlock();
-	idunlock();
-	exit(status);
-}
-
-rwaccess(fname)
-char *fname;
-{
-	int fd;
-
-	fd = open(fname, 2);
-	if (fd < 0)
-		return 0;
-	(void) close(fd);
-	return 1;
-}
-
-exists(fname)
-char *fname;
-{
-	int fd;
-
-	fd = open(fname, 0);
-	if (fd < 0)
-		return 0;
-	(void) close(fd);
-	return 1;
-}
-
-int	lockcount = 0;			/* no. of times we've called lock */
-
-#ifdef	VMS
-
-#define	SUBLOCK	"/tmp/netnews.lck.1"
-
-/*
- * Newsystem locking.
- * These routines are different for VMS because we can not
- * effectively simulate links, and VMS supports multiple
- * version numbers of files
- */
-lock()
-{
-	register int i;
-	register int fd;
-
-	if (lockcount++ == 0) {
-		i = DEADTIME;
-		while ((fd = creat(SUBLOCK, 0444)) < 0) {
-			if (--i < 0) {
-				(void) unlink(SUBLOCK);
-				logerr("News system locked up");
-			}
-			if (i < -3)
-				xerror("Unable to unlock news system");
-			sleep((unsigned)1);
-		}
-		(void) close(fd);
-	}
-}
-
-unlock()
-{
-	if (--lockcount == 0)
-		(void) unlink(SUBLOCK); 
-}
-
-#else /* !VMS */
-
-/*
- * Newsystem locking.
- */
-
-#if defined(BSD4_2) || defined(LOCKF)
-#ifdef LOCKF
-#include <unistd.h>
-#else /* !LOCKF */
-#include <sys/file.h>
-#endif /* !LOCKF */
-static int LockFd = -1;
-lock()
-{
-	LockFd = open(SUBFILE,0);
-	/* This will sleep until the other program releases the lock */
-	/* We may need to alarm out of this, but I don't think so */
-#ifdef LOCKF
-	(void) lockf(LockFd, F_LOCK, 0);
-#else
-	(void) flock(LockFd, LOCK_EX);
-#endif
-}
-
-unlock()
-{
-	(void) close(LockFd);
-}
-#else /* !BSD4_2 */
-lock()
-{
-	register int i;
-	extern int errno;
-
-	if (lockcount++ == 0) {
-		i = DEADTIME;
-		while (link(SUBFILE, LOCKFILE)) {
-			if (errno != EEXIST)
-				break;
-			if (--i < 0)
-				xerror("News system locked up");
-			sleep((unsigned)1);
-		}
-	}
-}
-
-unlock()
-{
-	if (--lockcount == 0)
-		(void) unlink(LOCKFILE);
-}
-#endif /* !BSD4_2 */
-#endif /* !VMS */
-
-/*
- * Generate the name of the person responsible for posting this article,
- * in order to check that two articles were posted by the same person.
- */
-char *
-senderof(hp)
-struct hbuf *hp;
-{
-	register char *r, *q, *tp;
-	char *tailpath();
-
-	if (hp->sender[0])
-		tp = hp->sender;
-	else if (hp->from[0])
-		tp = hp->from;
-	else
-		tp = tailpath(hp);
-
-	/* Remove full name */
-	q = index(tp, ' ');
-	if (q)
-		*q = '\0';
-
-	r = AllocCpy(tp);
-	if (q != NULL)
-		*q = ' ';
-	return r;
-}
-
-/* VARARGS1 */
-error(message, arg1, arg2, arg3)
-char *message;
-long arg1, arg2, arg3;
-{
-	char buffer[LBUFLEN];
-
-	fflush(stdout);
-	(void) sprintf(buffer, message, arg1, arg2, arg3);
-	logerr(buffer);
-	xxit(mode == PROC ? 0 : 1);
-}
*-*-END-of-src/ifuncs.c-*-*
echo x - src/patchlevel.h 1>&2
sed 's/.//' >src/patchlevel.h <<'*-*-END-of-src/patchlevel.h-*-*'
-0
*-*-END-of-src/patchlevel.h-*-*
echo x - src/localize.sh 1>&2
sed 's/.//' >src/localize.sh <<'*-*-END-of-src/localize.sh-*-*'
*-*-END-of-src/localize.sh-*-*
exit



More information about the Mod.sources mailing list