[mod.sources] v07i056: 2.11 News Source, Part07/09

sources-request@mirror.TMC.COM (11/07/86)

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

# To extract, sh this file
#	news 2.11 source part 7 of 9
if test ! -d src
then
	mkdir src
fi
echo x - src/funcs2.c 1>&2
sed 's/.//' >src/funcs2.c <<'*-*-END-of-src/funcs2.c-*-*'
-/*
- * This software is Copyright (c) 1985 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.
- *
- *
- * funcs2 - functions used by both inews and readnews.
- */
-
-#ifdef SCCSID
-static char	*SccsId = "@(#)funcs2.c	1.16	10/23/86";
-#endif /* SCCSID */
-
-#include "params.h"
-
-#ifdef SunIII
-#ifndef INTERNET
-#define	INTERNET
-#endif /* !INTERNET */
-#endif /* SunIII */
-
-/*LINTLIBRARY*/
-
-/*
- * Get user name and home directory.
- */
-getuser()
-{
-	static int flag = TRUE;
-	register struct passwd *p;
-
-	if (flag) {
-		if ((p = getpwuid(uid)) == NULL)
-			xerror("Cannot get user's name");
-		if ( username == NULL || username[0] == 0)
-			username = AllocCpy(p->pw_name);
-		userhome = AllocCpy(p->pw_dir);
-		flag = FALSE;
-	}
-	(void) strcpy(header.path, username);
-}
-
-static	FILE	*sysfile;
-
-char *fldget();
-
-static int sfline;
-
-/*
- * Open SUBFILE.
- */
-s_openr()
-{
-	sysfile = xfopen(SUBFILE, "r");
-	sfline = 0;
-}
-
-/*
- * Read SUBFILE.
- */
-s_read(sp)
-register struct srec *sp;
-{
-	register char *p;
-	register int  c;
-	char *e;
-	int chop_spaces = 0;
-again:
-	p = bfr;
-        /*
-         * Read  the  SUBFILE  (/usr/lib/news/sys)  from   the   current
-	 * position  to  the  first  unescaped newline.  If a newline is
-	 * escaped with a backslash (\) continue reading but throw  away
-	 * the backslash and newline; read the next line skipping spaces
-	 * and tabs until the first non-space/tab character, then  start
-	 * looking   for   a   newline   again.   Skipping  the  leading
-	 * spaces/tabs after a escaped newline  keeps  the  news  groups
-	 * together.  If  a  line  begins  with a newline, just skip it.
-	 */
-	for (e=p+LBUFLEN; p < e && (c=getc(sysfile)) != EOF; p++) {
-		*p = c;
-		if (c == '\n') {
-			sfline++;
-			if (p == bfr || p[-1] != '\\') {
-				p[1] = '\0';
-				break;
-			} else {
-				chop_spaces++;
-				p -= 2;
-			}
-		} else if (chop_spaces) {
-			if (c == '\t' || c == ' ')
-				p--;
-			else
-				chop_spaces = 0;
-		}
-	}
-	if (c == EOF) {
-		return FALSE;
-	}
-	p = bfr;
-	while (*p == ' ' || *p == '\t') /* skip leading white space */
-		p++;
-	if (*p == '\n')
-		goto again;	     /* skip newlines */
-	if (!nstrip(p))
-		xerror("SUBFILE (%s) line %d too long.", SUBFILE, sfline);
-	if (*p == '#')
-		goto again;
-	sp->s_xmit[0] = '\0';
-	sp->s_flags[0] = '\0';
-	sp->s_nosend = (char *)0;
-
-	p = fldget(sp->s_name, p);
-	if (*p++ == '\0')
-		xerror("Bad SUBFILE (%s) line %d.", SUBFILE, sfline);
-/*
- * A sys file line reading "ME" means the name of the local system.
- */
-	if (strcmp(sp->s_name, "ME") == 0)
-		(void) strcpy(sp->s_name, FULLSYSNAME);
-	e = index(sp->s_name, '/');
-	if (e) {
-		*e++ = '\0';
-		sp->s_nosend = e;
-	}
-	p = fldget(sp->s_nbuf, p);
-	lcase(sp->s_nbuf);
-	if (*p++ == '\0')
-		return TRUE;
-
-	p = fldget(sp->s_flags, p);
-	if (*p++ == '\0')
-		return TRUE;
-
-	(void) fldget(sp->s_xmit, p);
-	return TRUE;
-}
-
-char *
-fldget(q, p)
-register char *q, *p;
-{
-	while (*p && *p != ':') {
-		if (*p == '\\' && p[1]==':')
-			p++;
-		*q++ = *p++;
-	}
-	*q = '\0';
-	return p;
-}
-
-/*
- * Find the SUBFILE record for a system.
- */
-s_find(sp, system)
-register struct srec *sp;
-char *system;
-{
-	s_openr();
-	while (s_read(sp))
-		if (strncmp(system, sp->s_name, SNLN) == 0) {
-			s_close();
-			return TRUE;
-		}
-	s_close();
-	return FALSE;
-}
-
-/*
- * Close sysfile.
- */
-s_close()
-{
-	(void) fclose(sysfile);
-}
-
-extern struct timeb Now;
-
-time_t
-cgtdate(datestr)
-char *datestr;
-{
-	char	junk[40],month[40],day[30],tod[60],year[50];
-	static time_t lasttime;
-	static char lastdatestr[BUFLEN] = "";
-
-	if ( lastdatestr[0] && strcmp(datestr, lastdatestr) == 0)
-		return lasttime;
-	lasttime = getdate(datestr, &Now);
-	if (lasttime < 0 &&
-	  sscanf(datestr, "%s %s %s %s %s", junk, month, day, tod, year) == 5) {
-		(void) sprintf(bfr, "%s %s, %s %s", month, day, year, tod);
-		lasttime = getdate(bfr, &Now);
-	}
-	strncpy(lastdatestr, datestr, BUFLEN);
-	return lasttime;
-}
-
-lcase(s)
-register char *s;
-{
-	register char *ptr;
-
-	for (ptr = s; *ptr; ptr++)
-		if (isupper(*ptr))
-			*ptr = tolower(*ptr);
-}
-
-/*
- * Return a compact representation of the person who posted the given
- * message.  A sender or internet name will be used, otherwise
- * the last part of the path is used preceded by an optional ".."
- */
-char *
-tailpath(hp)
-struct hbuf *hp;
-{
-	char *p, *r;
-	static char resultbuf[BUFLEN];
-	char pathbuf[PATHLEN];
-	char *malloc();
-
-	/*
-	 * This only happens for articles posted by old news software
-	 * in non-internet format.
-	 */
-	resultbuf[0] = '\0';
-	(void) strncpy(pathbuf, hp->path, PATHLEN);
-	p = index(pathbuf, ' ');
-	if (p)
-		*p = '\0';	/* Chop off trailing " (name)" */
-	r = rindex(pathbuf, '!');
-	if (r == 0) {
-		r = pathbuf;
-	} else {
-		while (r > pathbuf && *--r != '!')
-			;
-		if (r > pathbuf) {
-			r++;
-			(void) strcpy(resultbuf, "..!");
-		}
-	}
-	(void) strcat(resultbuf, r);
-	return resultbuf;
-}
-
-/*
- * arpadate is like ctime(3) except that the time is returned in
- * an acceptable ARPANET time format instead of ctime format.
- */
-char *
-arpadate(longtime)
-time_t *longtime;
-{
-	register char *p, *q, *ud;
-	register int i;
-	static char b[40];
-	extern struct tm *gmtime();
-	extern char *asctime();
-
-	/*  Get current time. This will be used resolve the timezone. */
-	ud = asctime(gmtime(longtime));
-
-	/*  Crack the UNIX date line in a singularly unoriginal way. */
-	q = b;
-
-#ifdef notdef
-/* until every site installs the fix to getdate.y, the day
-   of the week can cause time warps */
-	p = &ud[0];		/* Mon */
-	*q++ = *p++;
-	*q++ = *p++;
-	*q++ = *p++;
-	*q++ = ','; *q++ = ' ';
-#endif
-
-	p = &ud[8];		/* 16 */
-	if (*p == ' ')
-		p++;
-	else
-		*q++ = *p++;
-	*q++ = *p++; *q++ = ' ';
-
-	p = &ud[4];		/* Sep */
-	*q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = ' ';
-
-	p = &ud[22];		/* 1979 */
-	*q++ = *p++; *q++ = *p++; *q++ = ' ';
-
-	p = &ud[11];		/* 01:03:52 */
-	for (i = 8; i > 0; i--)
-		*q++ = *p++;
-
-	*q++ = ' ';
-	*q++ = 'G';		/* GMT */
-	*q++ = 'M';
-	*q++ = 'T';
-	*q = '\0';
-
-	return b;
-}
-
-char *
-replyname(hptr)
-struct hbuf *hptr;
-{
-	register char *ptr;
-	static char tbuf[PATHLEN];
-
-	ptr = hptr->path;
-	if (prefix(ptr, FULLSYSNAME) &&
-		index(NETCHRS, ptr[strlen(FULLSYSNAME)]))
-		ptr = index(ptr, '!') + 1;
-#ifdef INTERNET
-	if (hptr->from[0])
-		ptr = hptr->from;
-	if (hptr->replyto[0])
-		ptr = hptr->replyto;
-#endif
-	(void) strcpy(tbuf, ptr);
-	ptr = index(tbuf, '(');
-	if (ptr) {
-		while (ptr[-1] == ' ')
-			ptr--;
-		*ptr = 0;
-	}
-#ifdef	SunIII
-	if (ptr = rindex(tbuf, '.')) {
-		if (prefix(++ptr, "OZ")) {
-			/* some people only allow it in lower case ... */
-			strcpy(ptr, "oz");
-			return tbuf;
-		}
-		if (prefix(ptr, "UUCP") || prefix(ptr, "ARPA") ||
-		    prefix(ptr, "DEC") || prefix(ptr, "CSNET")) {
-			strcat(tbuf, "@munnari.oz");	/* via sun to munnari */
-			return tbuf;
-		}
-	}
-	/*
-	 * must(?) have come from a uucp site, lets look see if path passes
-	 * through munnari, and if so delete the fake uucp path after that.
-	 */
-	for (ptr = tbuf ;; ptr++) {
-		if (prefix(ptr, "munnari!")) {
-			strcpy(tbuf, ptr+8);
-			break;
-		}
-		ptr = index(ptr, '!');
-		if (ptr == (char *)0)
-			break;
-	}
-	/*
-	 * now, just send the address we have left to munnari, and
-	 * hope that something sensible will be done with it there.
-	 * (This works in more cases than you'd think ...)
-	 */
-	strcat(tbuf, "@munnari.oz");
-#else /* !SunIII */
-#ifndef INTERNET
-	/*
-	 * Play games stripping off multiple berknet
-	 * addresses (a!b!c:d:e => a!b!d:e) here.
-	 */
-	for (ptr=tbuf; *ptr; ptr++) {
-		register char *ptr2;
-
-		if (index(NETCHRS, *ptr) && *ptr == ':' &&
-		    (ptr2=index(ptr+1, ':')))
-			(void) strcpy(ptr, ptr2);
-	}
-#else	/* INTERNET */
-	{
-	char mbuf[BUFLEN], modadd[BUFLEN];
-	FILE *mfd;
-	/* Let's find a path to the backbone */
-	sprintf(mbuf, "%s/mailpaths", LIBDIR);
-	mfd = xfopen(mbuf, "r");
-	do {
-		if (fgets(mbuf, sizeof mbuf, mfd) == NULL)
-			xerror("Can't find internet in %s/mailpaths",
-				LIBDIR);
-	} while (!prefix(mbuf, "internet"));
-	if (sscanf(mbuf, "%*s %s", modadd) != 1)
-		xerror("backbone address corrupted");
-	(void) fclose(mfd);
-	(void)strcpy(mbuf, tbuf);
-	/* If we are lucky, there is no ! or @ in the forward address */
-	if (strpbrk(modadd, "!@") == NULL) {
-		sprintf(tbuf, modadd, mbuf);
-	} else {
-		char *cp = index(mbuf, '@');
-		if (index(modadd, '@') == NULL && cp) {
-			/* we have to rearrange the address so no @ are in it */
-			char atbuf[BUFLEN];
-			*cp++ = '\0';
-			sprintf(atbuf, "%s!%s", cp, mbuf);
-			sprintf(tbuf, modadd, atbuf);
-		} else if (cp) {
-			/* some days you don't get lucky. presume the % hack */
-			*cp = '%';
-			sprintf(tbuf, modadd, mbuf);
-		}
-	}
-	}
-#endif /* INTERNET */
-#endif /* !SunIII */
-	return tbuf;
-}
-
-#ifdef DBM
-typedef struct {
-	char *dptr;
-	int dsize;
-} datum;
-#endif /* DBM */
-
-/*
- * Given an article ID, find the line in the history file that mentions it.
- * Return the text of the line, or NULL if not found.  A pointer to a
- * static area is returned.
- */
-char *
-findhist(artid)
-char *artid;
-{
-	static char lbuf[256];
-	char oidbuf[BUFSIZ];
-	FILE *hfp;
-	register char *p;
-#ifdef DBM
-	datum lhs, rhs;
-	datum fetch();
-	long fpos; /* We have to use an explicit variable to insure alignment */
-#else /* !DBM */
-	char *histfile();
-#endif /* !DBM */
-
-	/* Try to understand old artid's as well.  Assume .UUCP domain. */
-	if (artid[0] != '<') {
-		p = index(artid, '.');
-		if (p)
-			*p++ = '\0';
-		(void) sprintf(oidbuf, "<%s@%s.UUCP>", p, artid);
-		if (p)
-			*--p = '.';
-	} else
-		(void) strcpy(oidbuf, artid);
-	lcase(oidbuf);
-#ifdef DBM
-	initdbm(ARTFILE);
-	lhs.dptr = oidbuf;
-	lhs.dsize = strlen(lhs.dptr) + 1;
-	rhs = fetch(lhs);
-	if (rhs.dptr == NULL)
-		return NULL;
-	hfp = xfopen(ARTFILE, "r");
-	/* The bcopy is NECESSARY to insure alignment on some machines */
-	bcopy(rhs.dptr, (char *)&fpos, sizeof (long));
-	fseek(hfp, fpos, 0);
-#else /* !DBM */
-	hfp = xfopen(histfile(oidbuf), "r");
-#endif /* !DBM */
-	while (fgets(lbuf, BUFLEN, hfp) != NULL) {
-		p = index(lbuf, '\t');
-		if (p == NULL)
-			p = index(lbuf, '\n');
-		*p = 0;
-		if (strcmp(lbuf, artid) == 0 || strcmp(lbuf, oidbuf) == 0) {
-			(void) fclose(hfp);
-			*p = '\t';
-			*(lbuf + strlen(lbuf) - 1) = 0;	/* zap the \n */
-			return lbuf;
-		}
-#ifdef DBM
-		break;
-#endif /* DBM */
-	}
-	(void) fclose(hfp);
-	return NULL;
-}
-
-/*
- * Hunt up the article "artid", and return the newsgroup/artnum
- * where it can be found.
- */
-char *
-findfname(artid)
-char *artid;
-{
-	char *line, *p, *q;
-	char *findhist();
-	static char fname[BUFLEN];
-
-	line = findhist(artid);
-	if (line) {
-		/* Look for it stored as an article, where it should be */
-		p = index(line, '\t');
-		p = index(p+1, '\t');
-		p++;
-		if (*p) {
-			q = index(p, ' ');
-			if (q)
-				*q = 0;
-			(void) strcpy(fname, p);
-			return fname;
-		}
-	}
-	return NULL;
-}
-
-/*
- * Hunt up the article "artid", fopen it for read, and return a
- * file descriptor to it.  We look everywhere we can think of.
- */
-FILE *
-hfopen(artid)
-char *artid;
-{
-	char *p;
-	char *findhist();
-	FILE *rv = NULL;
-	char fname[BUFLEN];
-
-	p = findfname(artid);
-	if (p) {
-		(void) strcpy(fname, dirname(p));
-		rv = fopen(fname, "r");	/* NOT xfopen! */
-		if (rv == NULL)
-			xerror("Cannot hfopen article %s", artid);
-	}
-	return rv;
-}
-
-#ifdef DBM
-/*
-** Avoid problems of multiple dbminit calls.
-*/
-initdbm(name)
-char *name;
-{
-	static int called = 0;
-
-	if (called != 0)
-		return;
-	called = 1;
-	(void) dbminit(name);
-}
-#endif
-
-#ifndef BSD4_2
-/*
- * move n bytes from a to b
- */
-bcopy(a, b, n)
-register char *a, *b;
-register n;
-{
-	while (--n >= 0)
-		*b++ = *a++;
-}
-#endif
-
-#if !defined(BSD4_2) && !defined(BSD4_1C)
-rename(from,to)
-register char *from, *to;
-{
-	(void) unlink(to);
-	if (link(from, to) < 0)
-		return -1;
-
-	(void) unlink(from);
-	return 0;
-}
-#endif /* !BSD4_2 && ! BSD4_1C */
-
-#ifndef DBM
-/*
-** Generate the appropriate history subfile name
-*/
-char *
-histfile(hline)
-char *hline;
-{
-	char *p;
-	char chr;	/* least significant digit of article number */
-	static char subfile[BUFLEN];
-
-	p = strchr(hline, '@');
-	if (p != NULL && p > hline)
-		chr = *(p - 1);
-	else
-		chr = '0';
-	if (!isdigit(chr))
-		chr = '0';
-	sprintf(subfile, "%s.d/%c", ARTFILE, chr);
-	if (access(subfile, 04) < 0)
-		return(ARTFILE);
-	return(subfile);
-}
-#endif /* !DBM */
-
-#ifdef VMS
-/*
- * These functions open an article with one level of indirection,
- * to support symbolic links. xart_open exits if the open fails.
- */
-FILE *
-xart_open (filename,mode)
-char *filename,*mode;
-{
-	FILE *fp = art_open (filename, mode);
-	extern int errno;
-	if (fp == NULL)
-		xerror("Cannot open article %s (%s): %s\n",
-			 filename, mode, errmsg(errno));
-	return fp;
-}
-
-FILE *
-art_open (filename,mode)
-char *filename,*mode;
-{
-	char linkfile[BUFSIZ];
-	FILE *fp;
-
-	if ((fp = fopen (filename, mode)) == NULL)
-		return NULL;
-	if (fgets (linkfile, BUFSIZ, fp) == NULL || linkfile[0] != '/') {
-		rewind (fp);
-		return fp;
-	}
-/* Chase the symbolic link. */
-	(void) fclose (fp);
-	if ((fp = fopen (linkfile, mode)) == NULL)
-/* Clean up dangling link, if we have the power. Ignore error if we don't. */
-		(void) unlink (filename);
-	return fp;
-}
-#endif /* VMS */
*-*-END-of-src/funcs2.c-*-*
echo x - src/getdate.y 1>&2
sed 's/.//' >src/getdate.y <<'*-*-END-of-src/getdate.y-*-*'
-%token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
-%{
-	/* 	Steven M. Bellovin (unc!smb)			*/
-	/*	Dept. of Computer Science			*/
-	/*	University of North Carolina at Chapel Hill	*/
-	/*	@(#)getdate.y	2.13	9/16/86 */
-
-#include <sys/types.h>
-#ifdef USG
-struct timeb
-{
-	time_t	time;
-	unsigned short millitm;
-	short	timezone;
-	short	dstflag;
-};
-#else
-#include <sys/timeb.h>
-#endif
-#include <ctype.h>
-
-#include "defs.h"
-#if defined(BSD4_2) || defined (BSD4_1C)
-#include <sys/time.h>
-#else sane
-#include <time.h>
-#endif sane
-
-#define	NULL	0
-#define daysec (24L*60L*60L)
-	static int timeflag, zoneflag, dateflag, dayflag, relflag;
-	static time_t relsec, relmonth;
-	static int hh, mm, ss, merid, daylight;
-	static int dayord, dayreq;
-	static int month, day, year;
-	static int ourzone;
-#define AM 1
-#define PM 2
-#define DAYLIGHT 1
-#define STANDARD 2
-#define MAYBE    3
-%}
-
-%%
-timedate: 		/* empty */
-	| timedate item;
-
-item:	tspec =
-		{timeflag++;}
-	| zone =
-		{zoneflag++;}
-	| dtspec =
-		{dateflag++;}
-	| dyspec =
-		{dayflag++;}
-	| rspec =
-		{relflag++;}
-	| nspec;
-
-nspec:	NUMBER =
-		{if (timeflag && dateflag && !relflag) year = $1;
-		else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
-
-tspec:	NUMBER MERIDIAN =
-		{hh = $1; mm = 0; ss = 0; merid = $2;}
-	| NUMBER ':' NUMBER =
-		{hh = $1; mm = $3; merid = 24;}
-	| NUMBER ':' NUMBER MERIDIAN =
-		{hh = $1; mm = $3; merid = $4;}
-	| NUMBER ':' NUMBER NUMBER =
-		{hh = $1; mm = $3; merid = 24;
-		daylight = STANDARD; ourzone = $4%100 + 60*$4/100;}
-	| NUMBER ':' NUMBER ':' NUMBER =
-		{hh = $1; mm = $3; ss = $5; merid = 24;}
-	| NUMBER ':' NUMBER ':' NUMBER MERIDIAN =
-		{hh = $1; mm = $3; ss = $5; merid = $6;}
-	| NUMBER ':' NUMBER ':' NUMBER NUMBER =
-		{hh = $1; mm = $3; ss = $5; merid = 24;
-		daylight = STANDARD; ourzone = $6%100 + 60*$6/100;};
-
-zone:	ZONE =
-		{ourzone = $1; daylight = STANDARD;}
-	| DAYZONE =
-		{ourzone = $1; daylight = DAYLIGHT;};
-
-dyspec:	DAY =
-		{dayord = 1; dayreq = $1;}
-	| DAY ',' =
-		{dayord = 1; dayreq = $1;}
-	| NUMBER DAY =
-		{dayord = $1; dayreq = $2;};
-
-dtspec:	NUMBER '/' NUMBER =
-		{month = $1; day = $3;}
-	| NUMBER '/' NUMBER '/' NUMBER =
-		{month = $1; day = $3; year = $5;}
-	| MONTH NUMBER =
-		{month = $1; day = $2;}
-	| MONTH NUMBER ',' NUMBER =
-		{month = $1; day = $2; year = $4;}
-	| NUMBER MONTH =
-		{month = $2; day = $1;}
-	| NUMBER MONTH NUMBER =
-		{month = $2; day = $1; year = $3;};
-
-
-rspec:	NUMBER UNIT =
-		{relsec +=  60L * $1 * $2;}
-	| NUMBER MUNIT =
-		{relmonth += $1 * $2;}
-	| NUMBER SUNIT =
-		{relsec += $1;}
-	| UNIT =
-		{relsec +=  60L * $1;}
-	| MUNIT =
-		{relmonth += $1;}
-	| SUNIT =
-		{relsec++;}
-	| rspec AGO =
-		{relsec = -relsec; relmonth = -relmonth;};
-%%
-
-static int mdays[12] =
-	{31, 0, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31};
-#define epoch 1970
-
-extern struct tm *localtime();
-time_t dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
-int mm, dd, yy, h, m, s, mer, zone, dayflag;
-{
-	time_t tod, jdate;
-	register int i;
-	time_t timeconv();
-
-	if (yy < 0) yy = -yy;
-	if (yy < 100) yy += 1900;
-	mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
-	if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
-		dd < 1 || dd > mdays[--mm]) return (-1);
-	jdate = dd-1;
-        for (i=0; i<mm; i++) jdate += mdays[i];
-	for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
-	jdate *= daysec;
-	jdate += zone * 60L;
-	if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
-	jdate += tod;
-	if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
-		jdate += -1*60*60;
-	return (jdate);
-}
-
-time_t dayconv(ord, day, now) int ord, day; time_t now;
-{
-	register struct tm *loctime;
-	time_t tod;
-	time_t daylcorr();
-
-	tod = now;
-	loctime = localtime(&tod);
-	tod += daysec * ((day - loctime->tm_wday + 7) % 7);
-	tod += 7*daysec*(ord<=0?ord:ord-1);
-	return daylcorr(tod, now);
-}
-
-time_t timeconv(hh, mm, ss, mer) register int hh, mm, ss, mer;
-{
-	if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
-	switch (mer) {
-		case AM: if (hh < 1 || hh > 12) return(-1);
-			 return (60L * ((hh%12)*60L + mm)+ss);
-		case PM: if (hh < 1 || hh > 12) return(-1);
-			 return (60L * ((hh%12 +12)*60L + mm)+ss);
-		case 24: if (hh < 0 || hh > 23) return (-1);
-			 return (60L * (hh*60L + mm)+ss);
-		default: return (-1);
-	}
-}
-time_t monthadd(sdate, relmonth) time_t sdate, relmonth;
-{
-	struct tm *ltime;
-	time_t dateconv();
-	time_t daylcorr();
-	int mm, yy;
-
-	if (relmonth == 0) return 0;
-	ltime = localtime(&sdate);
-	mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
-	yy = mm/12;
-	mm = mm%12 + 1;
-	return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
-		ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
-}
-
-time_t daylcorr(future, now) time_t future, now;
-{
-	int fdayl, nowdayl;
-
-	nowdayl = (localtime(&now)->tm_hour+1) % 24;
-	fdayl = (localtime(&future)->tm_hour+1) % 24;
-	return (future-now) + 60L*60L*(nowdayl-fdayl);
-}
-
-static char *lptr;
-
-yylex()
-{
-	extern int yylval;
-	int sign;
-	register char c;
-	register char *p;
-	char idbuf[20];
-	int pcnt;
-
-	for (;;) {
-		while (isspace(*lptr)) lptr++;
-
-		if (isdigit(c = *lptr) || c == '-' || c == '+') {
-			if (c== '-' || c == '+') {
-				if (c=='-') sign = -1;
-				else sign = 1;
-				if (!isdigit(*++lptr)) {
-					/* yylval = sign; return (NUMBER); */
-					return yylex();	/* skip the '-' sign */
-				}
-			} else sign = 1;
-			yylval = 0;
-			while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
-			yylval *= sign;
-			lptr--;
-			return (NUMBER);
-
-		} else if (isalpha(c)) {
-			p = idbuf;
-			while (isalpha(c = *lptr++) || c=='.')
-				*p++ = c;
-			*p = '\0';
-			lptr--;
-			return (lookup(idbuf));
-		}
-
-		else if (c == '(') {
-			pcnt = 0;
-			do {
-				c = *lptr++;
-				if (c == '\0') return(c);
-				else if (c == '(') pcnt++;
-				else if (c == ')') pcnt--;
-			} while (pcnt > 0);
-		}
-
-		else return (*lptr++);
-	}
-}
-
-struct table {
-	char *name;
-	int type, value;
-};
-
-struct table mdtab[] = {
-	{"January", MONTH, 1},
-	{"February", MONTH, 2},
-	{"March", MONTH, 3},
-	{"April", MONTH, 4},
-	{"May", MONTH, 5},
-	{"June", MONTH, 6},
-	{"July", MONTH, 7},
-	{"August", MONTH, 8},
-	{"September", MONTH, 9},
-	{"Sept", MONTH, 9},
-	{"October", MONTH, 10},
-	{"November", MONTH, 11},
-	{"December", MONTH, 12},
-
-	{"Sunday", DAY, 0},
-	{"Monday", DAY, 1},
-	{"Tuesday", DAY, 2},
-	{"Tues", DAY, 2},
-	{"Wednesday", DAY, 3},
-	{"Wednes", DAY, 3},
-	{"Thursday", DAY, 4},
-	{"Thur", DAY, 4},
-	{"Thurs", DAY, 4},
-	{"Friday", DAY, 5},
-	{"Saturday", DAY, 6},
-	{0, 0, 0}};
-
-#define HRS *60
-#define HALFHR 30
-struct table mztab[] = {
-	{"a.m.", MERIDIAN, AM},
-	{"am", MERIDIAN, AM},
-	{"p.m.", MERIDIAN, PM},
-	{"pm", MERIDIAN, PM},
-	{"nst", ZONE, 3 HRS + HALFHR},		/* Newfoundland */
-	{"n.s.t.", ZONE, 3 HRS + HALFHR},
-	{"ast", ZONE, 4 HRS},		/* Atlantic */
-	{"a.s.t.", ZONE, 4 HRS},
-	{"adt", DAYZONE, 4 HRS},
-	{"a.d.t.", DAYZONE, 4 HRS},
-	{"est", ZONE, 5 HRS},		/* Eastern */
-	{"e.s.t.", ZONE, 5 HRS},
-	{"edt", DAYZONE, 5 HRS},
-	{"e.d.t.", DAYZONE, 5 HRS},
-	{"cst", ZONE, 6 HRS},		/* Central */
-	{"c.s.t.", ZONE, 6 HRS},
-	{"cdt", DAYZONE, 6 HRS},
-	{"c.d.t.", DAYZONE, 6 HRS},
-	{"mst", ZONE, 7 HRS},		/* Mountain */
-	{"m.s.t.", ZONE, 7 HRS},
-	{"mdt", DAYZONE, 7 HRS},
-	{"m.d.t.", DAYZONE, 7 HRS},
-	{"pst", ZONE, 8 HRS},		/* Pacific */
-	{"p.s.t.", ZONE, 8 HRS},
-	{"pdt", DAYZONE, 8 HRS},
-	{"p.d.t.", DAYZONE, 8 HRS},
-	{"yst", ZONE, 9 HRS},		/* Yukon */
-	{"y.s.t.", ZONE, 9 HRS},
-	{"ydt", DAYZONE, 9 HRS},
-	{"y.d.t.", DAYZONE, 9 HRS},
-	{"hst", ZONE, 10 HRS},		/* Hawaii */
-	{"h.s.t.", ZONE, 10 HRS},
-	{"hdt", DAYZONE, 10 HRS},
-	{"h.d.t.", DAYZONE, 10 HRS},
-
-	{"gmt", ZONE, 0 HRS},
-	{"g.m.t.", ZONE, 0 HRS},
-	{"bst", DAYZONE, 0 HRS},		/* British Summer Time */
-	{"b.s.t.", DAYZONE, 0 HRS},
-	{"eet", ZONE, 0 HRS},		/* European Eastern Time */
-	{"e.e.t.", ZONE, 0 HRS},
-	{"eest", DAYZONE, 0 HRS},	/* European Eastern Summer Time */
-	{"e.e.s.t.", DAYZONE, 0 HRS},
-	{"met", ZONE, -1 HRS},		/* Middle European Time */
-	{"m.e.t.", ZONE, -1 HRS},
-	{"mest", DAYZONE, -1 HRS},	/* Middle European Summer Time */
-	{"m.e.s.t.", DAYZONE, -1 HRS},
-	{"wet", ZONE, -2 HRS },		/* Western European Time */
-	{"w.e.t.", ZONE, -2 HRS },
-	{"west", DAYZONE, -2 HRS},	/* Western European Summer Time */
-	{"w.e.s.t.", DAYZONE, -2 HRS},
-
-	{"jst", ZONE, -9 HRS},		/* Japan Standard Time */
-	{"j.s.t.", ZONE, -9 HRS},	/* Japan Standard Time */
-					/* No daylight savings time */
-
-	{"aest", ZONE, -10 HRS},	/* Australian Eastern Time */
-	{"a.e.s.t.", ZONE, -10 HRS},
-	{"aesst", DAYZONE, -10 HRS},	/* Australian Eastern Summer Time */
-	{"a.e.s.s.t.", DAYZONE, -10 HRS},
-	{"acst", ZONE, -(9 HRS + HALFHR)},	/* Australian Central Time */
-	{"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
-	{"acsst", DAYZONE, -(9 HRS + HALFHR)},	/* Australian Central Summer */
-	{"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
-	{"awst", ZONE, -8 HRS},		/* Australian Western Time */
-	{"a.w.s.t.", ZONE, -8 HRS},	/* (no daylight time there, I'm told */
-	{0, 0, 0}};
-
-struct table unittb[] = {
-	{"year", MUNIT, 12},
-	{"month", MUNIT, 1},
-	{"fortnight", UNIT, 14*24*60},
-	{"week", UNIT, 7*24*60},
-	{"day", UNIT, 1*24*60},
-	{"hour", UNIT, 60},
-	{"minute", UNIT, 1},
-	{"min", UNIT, 1},
-	{"second", SUNIT, 1},
-	{"sec", SUNIT, 1},
-	{0, 0, 0}};
-
-struct table othertb[] = {
-	{"tomorrow", UNIT, 1*24*60},
-	{"yesterday", UNIT, -1*24*60},
-	{"today", UNIT, 0},
-	{"now", UNIT, 0},
-	{"last", NUMBER, -1},
-	{"this", UNIT, 0},
-	{"next", NUMBER, 2},
-	{"first", NUMBER, 1},
-	/* {"second", NUMBER, 2}, */
-	{"third", NUMBER, 3},
-	{"fourth", NUMBER, 4},
-	{"fifth", NUMBER, 5},
-	{"sixth", NUMBER, 6},
-	{"seventh", NUMBER, 7},
-	{"eigth", NUMBER, 8},
-	{"ninth", NUMBER, 9},
-	{"tenth", NUMBER, 10},
-	{"eleventh", NUMBER, 11},
-	{"twelfth", NUMBER, 12},
-	{"ago", AGO, 1},
-	{0, 0, 0}};
-
-struct table milzone[] = {
-	{"a", ZONE, 1 HRS},
-	{"b", ZONE, 2 HRS},
-	{"c", ZONE, 3 HRS},
-	{"d", ZONE, 4 HRS},
-	{"e", ZONE, 5 HRS},
-	{"f", ZONE, 6 HRS},
-	{"g", ZONE, 7 HRS},
-	{"h", ZONE, 8 HRS},
-	{"i", ZONE, 9 HRS},
-	{"k", ZONE, 10 HRS},
-	{"l", ZONE, 11 HRS},
-	{"m", ZONE, 12 HRS},
-	{"n", ZONE, -1 HRS},
-	{"o", ZONE, -2 HRS},
-	{"p", ZONE, -3 HRS},
-	{"q", ZONE, -4 HRS},
-	{"r", ZONE, -5 HRS},
-	{"s", ZONE, -6 HRS},
-	{"t", ZONE, -7 HRS},
-	{"u", ZONE, -8 HRS},
-	{"v", ZONE, -9 HRS},
-	{"w", ZONE, -10 HRS},
-	{"x", ZONE, -11 HRS},
-	{"y", ZONE, -12 HRS},
-	{"z", ZONE, 0 HRS},
-	{0, 0, 0}};
-
-lookup(id) char *id;
-{
-#define gotit (yylval=i->value,  i->type)
-#define getid for(j=idvar, k=id; *j++ = *k++; )
-
-	char idvar[20];
-	register char *j, *k;
-	register struct table *i;
-	int abbrev;
-
-	getid;
-	if (strlen(idvar) == 3) abbrev = 1;
-	else if (strlen(idvar) == 4 && idvar[3] == '.') {
-		abbrev = 1;
-		idvar[3] = '\0';
-	}
-	else abbrev = 0;
-
-	if (islower(*idvar)) *idvar = toupper(*idvar);
-
-	for (i = mdtab; i->name; i++) {
-		k = idvar;
-		for (j = i->name; *j++ == *k++;) {
-			if (abbrev && j==i->name+3) return gotit;
-			if (j[-1] == 0) return gotit;
-		}
-	}
-
-	getid;
-	for (i = mztab; i->name; i++)
-		if (strcmp(i->name, idvar) == 0) return gotit;
-
-	for (j = idvar; *j; j++)
-		if (isupper(*j)) *j = tolower(*j);
-	for (i=mztab; i->name; i++)
-		if (strcmp(i->name, idvar) == 0) return gotit;
-
-	getid;
-	for (i=unittb; i->name; i++)
-		if (strcmp(i->name, idvar) == 0) return gotit;
-
-	if (idvar[strlen(idvar)-1] == 's')
-		idvar[strlen(idvar)-1] = '\0';
-	for (i=unittb; i->name; i++)
-		if (strcmp(i->name, idvar) == 0) return gotit;
-
-	getid;
-	for (i = othertb; i->name; i++)
-		if (strcmp(i->name, idvar) == 0) return gotit;
-
-	getid;
-	if (strlen(idvar) == 1 && isalpha(*idvar)) {
-		if (isupper(*idvar)) *idvar = tolower(*idvar);
-		for (i = milzone; i->name; i++)
-			if (strcmp(i->name, idvar) == 0) return gotit;
-	}
-
-	return(ID);
-}
-
-time_t getdate(p, now) char *p; struct timeb *now;
-{
-#define mcheck(f)	if (f>1) err++
-	time_t monthadd();
-	int err;
-	struct tm *lt;
-	struct timeb ftz;
-
-	time_t sdate, tod;
-
-	lptr = p;
-	if (now == ((struct timeb *) NULL)) {
-		now = &ftz;
-		ftime(&ftz);
-	}
-	lt = localtime(&now->time);
-	year = lt->tm_year;
-	month = lt->tm_mon+1;
-	day = lt->tm_mday;
-	relsec = 0; relmonth = 0;
-	timeflag=zoneflag=dateflag=dayflag=relflag=0;
-	ourzone = now->timezone;
-	daylight = MAYBE;
-	hh = mm = ss = 0;
-	merid = 24;
-
-	if (err = yyparse()) return (-1);
-
-	mcheck(timeflag);
-	mcheck(zoneflag);
-	mcheck(dateflag);
-	mcheck(dayflag);
-
-	if (err) return (-1);
-	if (dateflag || timeflag || dayflag) {
-		sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
-		if (sdate < 0) return -1;
-	}
-	else {
-		sdate = now->time;
-		if (relflag == 0)
-			sdate -= (lt->tm_sec + lt->tm_min*60 +
-				lt->tm_hour*(60L*60L));
-	}
-
-	sdate += relsec;
-	sdate += monthadd(sdate, relmonth);
-
-	if (dayflag && !dateflag) {
-		tod = dayconv(dayord, dayreq, sdate);
-		sdate += tod;
-	}
-
-	return sdate;
-}
-
-yyerror(s) char *s;
-{}
*-*-END-of-src/getdate.y-*-*
echo x - src/funcs.c 1>&2
sed 's/.//' >src/funcs.c <<'*-*-END-of-src/funcs.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.
- *
- * funcs - functions used by many programs
- */
-
-#ifdef SCCSID
-static char	*SccsId = "@(#)funcs.c	2.33	10/23/86";
-#endif /* SCCSID */
-
-/*LINTLIBRARY*/
-
-#include "params.h"
-#include <errno.h>
-#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
-#include <fcntl.h>
-#endif /* !v7 */
-
-extern char *Progname;
-
-/*
- * News group matching.
- *
- * nglist is a list of newsgroups.
- * sublist is a list of subscriptions.
- * sublist may have "meta newsgroups" in it.
- * All fields are NGDELIM separated,
- * and there is an NGDELIM at the end of each argument.
- *
- * Currently implemented glitches:
- * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
- * If subscription X matches Y, it also matches Y.anything.
- */
-ngmatch(nglist, sublist)
-register char *nglist, *sublist;
-{
-	register char *n, *s;
-	register int rc;
-
-	rc = FALSE;
-	for (n = nglist; *n != '\0' && rc == FALSE;) {
-		for (s = sublist; *s != '\0';) {
-			if (*s != NEGCHAR)
-				rc = rc || ptrncmp(s, n);
-			else
-				rc = rc && !ptrncmp(s+1, n);
-			while (*s++ != NGDELIM && *s != '\0')
-				;
-		}
-		while (*n++ != NGDELIM && *n != '\0')
-			;
-	}
-	return rc;
-}
-
-/*
- * Compare two newsgroups for equality.
- * The first one may be a "meta" newsgroup.
- */
-ptrncmp(ng1, ng2)
-register char *ng1, *ng2;
-{
-	while (*ng1 != NGDELIM && *ng1 != '\0') {
-		if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
-			ng1 += 3;
-			while (*ng2 != NGDELIM && *ng2 != '.' && *ng2 != '\0')
-				if (ptrncmp(ng1, ng2++))
-					return(TRUE);
-			return ptrncmp(ng1, ng2);
-		} else if (*ng1++ != *ng2++)
-			return FALSE;
-	}
-	return *ng2 == '.' || *ng2 == NGDELIM || *ng2 == '\0';
-}
-
-/*
- * Exec the shell.
- * This version resets uid, gid, and umask.
- * Called with fsubr(ushell, s, NULL)
- */
-/* ARGSUSED */
-ushell(s, dummy)
-char *s, *dummy;
-{
-	(void) umask(savmask);
-	(void) setgid(gid);
-	(void) setuid(uid);
-	xshell(s);
-}
-
-/*
- * Exec the shell.
- */
-
-#ifdef lint
-char	**environ;
-#else /* !lint */
-extern char	**environ;
-#endif /* !lint */
-
-xshell(s)
-char *s;
-{
-	char *env[100], **envp;
-	char a[BUFLEN + 2];
-	extern char filename[];
-	/* set $A */
-	(void) sprintf(a, "A=%s", filename);
-	env[0] = a;
-	for (envp = env + 1 ; *environ != NULL && envp < env + 98 ; environ++)
-		if ((*environ)[0] != 'A' || (*environ)[1] != '=')
-			*envp++ = *environ;
-	*envp = NULL;
-
-	execle(SHELL, SHELL, "-c", s, (char *)0, env);
-	xerror("No shell!");
-}
-
-/*
- * Fork and call a subroutine with two args.
- * Return pid without waiting.
- */
-fsubr(f, s1, s2)
-int (*f)();
-char *s1, *s2;
-{
-	register int pid;
-
-	/* this may NOT be a vfork */
-	while ((pid = fork()) == -1)
-		sleep((unsigned)1);
-	if (pid == 0) {
-		(*f)(s1, s2);
-		exit(0);
-	}
-	return pid;
-}
-
-/*
- * Wait on a child process.
- */
-fwait(pid)
-register int pid;
-{
-	register int w;
-	int status;
-	int (*onhup)(), (*onint)();
-
-	onint = signal(SIGINT, SIG_IGN);
-	onhup = signal(SIGHUP, SIG_IGN);
-	while ((w = wait(&status)) != pid && w != -1)
-		;
-	if (w == -1)
-		status = -1;
-	(void) signal(SIGINT, onint);
-	(void) signal(SIGHUP, onhup);
-	return status;
-}
-
-/*
- * Strip trailing newlines, blanks, and tabs from 's'.
- * Return TRUE if newline was found, else FALSE.
- */
-nstrip(s)
-register char *s;
-{
-	register char *p;
-	register int rc;
-
-	rc = FALSE;
-	p = s;
-	while (*p)
-		if (*p++ == '\n')
-			rc = TRUE;
-	while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
-	*++p = '\0';
-	return rc;
-}
-
-/*
- * Local open routine.
- */
-FILE *
-xfopen(name, fmode)
-register char *name, *fmode;
-{
-	register FILE *fp;
-	char	*fname;
-	extern int errno;
-
-	if ((fp = fopen(name, fmode)) == NULL) {
-#ifdef IHCC
-		/*
-		 * IHCC users only see the "filename" that was in trouble,
-		 * not the whole path.  (for security!)
-		 */
-		fname = rindex(name, '/') + 1;
-#else
-		fname = name;
-#endif
-		xerror("Cannot open %s (%s): %s", fname, fmode, errmsg(errno));
-	}
-	/* kludge for setuid not being honored for root */
-	if ((uid == 0) && (duid != 0) && ((*fmode == 'a') || (*fmode == 'w')))
-		(void) chown(name, duid, dgid);
-	return fp;
-}
-
-char *
-errmsg(code)
-int code;
-{
-	extern int sys_nerr;
-	extern char *sys_errlist[];
-	static char ebuf[6+5+1];
-
-	if (code > sys_nerr) {
-		(void) sprintf(ebuf, "Error %d", code);
-		return ebuf;
-	} else
-		return sys_errlist[code];
-}
-
-prefix(full, pref)
-register char *full, *pref;
-{
-	register char fc, pc;
-
-	while ((pc = *pref++) != '\0') {
-		fc = *full++;
-		if (isupper(fc))
-			fc = tolower(fc);
-		if (isupper(pc))
-			pc = tolower(pc);
-		if (fc != pc)
-			return FALSE;
-	}
-	return TRUE;
-}
-
-char *
-dirname(ngname)
-char *ngname;
-{
-	static char rbuf[BUFLEN];
-	register char *p;
-
-	(void) sprintf(rbuf, "%s/%s", SPOOL, ngname);
-
-	for (p=rbuf+strlen(SPOOL); *p; p++)
-		if (*p == '.')
-			*p = '/';
-	return rbuf;
-}
-
-/*
- * Return TRUE iff ngname is a valid newsgroup name
- */
-validng(ngname)
-char *ngname;
-{
-	register FILE *fp;
-	register char *p, *q;
-	char abuf[BUFLEN];
-
-	fp = xfopen(ACTIVE, "r");
-	while(fgets(abuf, BUFLEN, fp) != NULL) {
-		p = abuf;
-		q = ngname;
-		while (*p++ == *q++)
-			;
-		if (*--q == '\0' && *--p == ' ') {
-			(void) fclose(fp);
-			return TRUE;
-		}
-	}
-	(void) fclose(fp);
-	return FALSE;
-}
-
-/* VARARGS1 */
-xerror(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(1);
-}
-
-/* VARARGS1 */
-log(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
-char *fmt;
-long a1, a2, a3, a4, a5, a6, a7, a8, a9;
-{
-	_dolog(0, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
-}
-
-/* VARARGS1 */
-logerr(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
-char *fmt;
-long a1, a2, a3, a4, a5, a6, a7, a8, a9;
-{
-	_dolog(1, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
-}
-
-char *lfsuffix[] = {
-	"log",
-	"errlog",
-	0
-};
-
-/*
- * Log the given message, with printf strings and parameters allowed,
- * on the log file, if it can be written.  The date and an attempt at
- * figuring out the remote system name are also logged.
- */
-/* VARARGS1 */
-_dolog(which, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
-char *fmt;
-long a1, a2, a3, a4, a5, a6, a7, a8, a9;
-{
-	FILE *logfile;
-	register char *p, *logtime;
-	int i;
-	char logfname[BUFLEN];		/* the log file */
-	char rmtsys[BUFLEN];
-	char msg[LBUFLEN];
-	time_t t;
-
-	(void) strcpy(rmtsys, header.path);
-	p = index(rmtsys, '!');
-	if (p == NULL)
-		p = index(rmtsys, ':');
-	if (p)
-		*p = 0;
-	else {
-		p = rindex(rmtsys, '@');
-		if (p)
-			(void) strcpy(rmtsys, p+1);
-		else
-			(void) strcpy(rmtsys, "local");
-	}
-
-	(void) time(&t);
-	logtime = ctime(&t);
-	logtime[16] = 0;
-	logtime += 4;
-
-
-	(void) sprintf(msg, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
-
-	if (which)
-		fprintf(stderr,"%s: %s\n", Progname, msg);
-
-	for (i=0; i<=which;i++) {
-		(void) sprintf(logfname, "%s/%s", LIB, lfsuffix[i]);
-
-		if (access(logfname, 0) == 0 && (logfile = fopen(logfname, "a")) != NULL) {
-#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
-			int flags;
-			flags = fcntl(fileno(logfile), F_GETFL, 0);
-			(void) fcntl(fileno(logfile), F_SETFL, flags|O_APPEND);
-#else /* v7 */
-			(void) lseek(fileno(logfile), 0L, 2);
-#endif /* v7 */
-			if (i)
-				fprintf(logfile, "%s\t%s\t%s: %s\n", logtime,
-					header.ident[0] ? header.ident : username, Progname, msg);
-			else
-				fprintf(logfile, "%s\t%s\t%s\n", logtime,
-					rmtsys, msg);
-			(void) fclose(logfile);
-		}
-	}
-}
-#ifdef VMS
-
-/*
- * vmslink allows simulation of file linking under VMS.
- */
-vmslink(infile,outfile)
-char *infile, *outfile;
-{
-	FILE *fp;
-
-	if (access(outfile,0) == 0) {
-		errno = EEXIST;
-		return -1;
-	}
-
-	fp = fopen(outfile, "w");
-	if (fp == NULL) {
-		errno = EACCES;
-		return -1;
-	}
-
-	(void) fprintf(fp, "%s", infile);
-	(void) fclose(fp);
-
-	return 0;
-}
-
-/*
- * vmsdelete deletes all revisions of a file.  It attempts to
- * appear as unlink(2) under conventional Unix in other respects.
- */
-vmsdelete(file)
-char *file;
-{
-	int i;
-
-	i = unlink(file);
-	if (i != 0)
-		return i;
-
-	i = errno;
-	while (unlink(file) == 0)
-		;
-	errno = i;
-
-	return 0;
-}
-
-/*
- * Convert a Unix file to a VMS fixed record format file by
- * executing the 'unixtovms' command.
- */
-unixtovms(file)
-char *file;
-{
-	char buf[BUFLEN];
-	sprintf(buf, "exec /etc/unixtovms %s", file);
-	return system(buf);
-}
-
-/*
- * Convert a VMS fixed record format file to a Unix file by
- * executing the 'vmstounix' command.
- */
-vmstounix(file)
-char *file;
-{
-	char buf[BUFLEN];
-	sprintf(buf,"exec /etc/vmstounix %s", file);
-	return system(buf);
-}
-#endif /* VMS */
-
-#if !defined(BSD4_2) && !defined(BSD4_1C)
-/*
- * make a directory. Also make sure that the directory is owned
- * by the right userid
- */
-mkdir(path, perm)
-char *path;
-int perm;
-{
-	int pid, status;
-
-	if (pid=vfork()) {
-		status = fwait(pid);
-#if defined(USG) && !defined(CHEAP)
-		if (pid=vfork())
-			(void) fwait(pid);
-		else {
-			setgid(gid);
-			setuid(uid);
-			if (chown(path, duid, dgid) == 0)
-				(void) chmod(path, perm&(~N_UMASK));
-			_exit(0);
-		}
-#endif /* USG && !CHEAP */
-	} else {
-		(void) setgid(dgid);
-		if (setuid(duid) < 0)
-			(void) umask(0);
-		else
-			(void) umask(perm&N_UMASK);
-		(void) execlp("mkdir", "mkdir", path, (char *)NULL);
-		perror(path);
-		_exit(1);
-	}
-	return status;
-}
-#endif /* !BSD4_2 && ! BSD4_1C */
-#ifndef USG
-char *
-strpbrk(str, chars)
-register char *str, *chars;
-{
-	register char *cp;
-
-	do {
-		cp = chars - 1;
-		while (*++cp) {
-			if (*str == *cp)
-				return str;
-		}
-	} while (*str++);
-	return NULL;
-}
-#endif /* !USG */
-
-#ifdef FASCIST
-/*
- *  This routine checks to see if the posting user is allowed to
- *  post to the given newsgroup.  If the username is not in the file
- *  $LIBDIR/authorized then the default in the symbol FASCIST is used.
- *
- *  Format of the call:
- *     fascist(user, newgroups)
- *
- *  Returns:
- *     FALSE, if authorized
- *     TRUE, if not
- *
- *  Format of the file "authorized" is:
- *    user:allowed groups  
- *
- *  Example:
- *    root:net.all,mod.all
- *    naughty_person:junk,net.politics
- *    operator:!net.all,general,test,mod.unix
- *
- *  An open environment could have FASCIST set to "all"
- *  and then individual entries could be made in the authorized file
- *  to prevent certain individuals from posting to such a wide
- *  area.
- *
- *  Note that a distribution of "all" does NOT mean to allow postings
- *  only to local groups -- "all" includes "all.all".  
- *  Use "all,!all.all" to get this behavior
- *
- *	Eugene Spafford		spaf@gatech	May 22, 1985
- */
-
-fascist(user, newsgroups)
-register char *user, *newsgroups;
-{
-	FILE *facfd;
-	char facuser[BUFLEN], facgroups[BUFLEN], factemp[BUFLEN];
-	register char  *facptr;
-
-	/* First, open the necessary file...$LIBDIR/authorized and see if there
-	 * is an entry for this user 
-	 */
-
-	(void) strncpy(facgroups, FASCIST, BUFLEN);
-	sprintf(factemp, "%s/%s", LIBDIR, "authorized");
-	facfd = fopen(factemp, "r");
-
-	if (facfd != NULL) { /* If no such file, we go with the global default */
-		while (fscanf(facfd, "%[^:]:%s\n", facuser, factemp) != EOF)
-			if (strncmp(facuser, user, BUFLEN) == 0) {
-				(void) strcat(facgroups, ",");
-				(void) strcat(facgroups, factemp);
-				break;
-			}
-		fclose (facfd);
-	}
-#ifdef DEBUG
-	fprintf(stderr, "facgroups = %s\n", facgroups);
-	fprintf(stderr, "newsgroups = %s\n", newsgroups);
-#endif DEBUG
-
-	/* We step through the newsgroups being posted to and check each against
-	 * the restriction list.  *ALL* posted groups must match the restriction
-	 * list or we don't allow the posting.
-	 */
-
-	while (*newsgroups != '\0') {
-		facptr = factemp;
-		while (*newsgroups != '\0' && *newsgroups != NGDELIM)
-			*facptr++ = *newsgroups++;
-		*facptr = '\0';
-		if (*newsgroups == NGDELIM)
-			newsgroups++;
-
-#ifdef DEBUG
-		fprintf(stderr, "Checking newsgroup '%s'\n", factemp);
-#endif
-
-		if (ngmatch(factemp, facgroups) == FALSE)
-			return TRUE;
-	}
-
-	/* must be okay -- return */
-#ifdef DEBUG
-	fprintf (stderr, "Newsgroups approved for this poster.\n");
-#endif DEBUG
-	return FALSE;
-}
-#endif FASCIST
*-*-END-of-src/funcs.c-*-*
echo x - src/checknews.c 1>&2
sed 's/.//' >src/checknews.c <<'*-*-END-of-src/checknews.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.
- *
- * checknews - news checking program
- */
-
-#ifdef SCCSID
-static char	*SccsId = "@(#)checknews.c	2.25	5/27/86";
-#endif /* SCCSID */
-
-char *Progname = "checknews";		/* used by xerror */
-
-#include "params.h"
-
-char	bfr[LBUFLEN];			/* general-use scratch area	*/
-char	optbuf[BUFLEN];			/* NEWSOPTS buffer		*/
-int	line = -1, y, e, n, q;
-int	verbose;			/* For debugging.		*/
-int	nflag;				/* for spec. newsgroup		*/
-char	narggrp[BUFLEN];		/* spec newsgroup		*/
-FILE	*rcfp, *actfp;
-char	newsrc[BUFLEN],*rcline[LINES],rcbuf[LBUFLEN],*argvrc[LINES];
-struct hbuf header;
-char	coptbuf[BUFLEN],datebuf[BUFLEN];
-int	mode = 1;
-#ifndef SHELL
-char	*SHELL;
-#endif
-
-main(argc, argv)
-int argc;
-register char **argv;
-{
-	register char *ptr;	/* pointer to rest of buffer		*/
-	char *user, *home;
-	struct passwd *pw;
-	struct group *gp;
-	int sflag = 0, optflag = FALSE, space = FALSE;
-	int i;
-
-	y = 0;
-	n = 0;
-	e = 0;
-	q = 0;
-	nflag = 0;
-	pathinit();
-	if (--argc > 0) {
-		for (argv++; **argv; ++*argv) {
-			switch(**argv) {
-			case 'y':
-				y++;
-				break;
-			case 'q':
-				q++;
-				break;
-			case 'v':
-				verbose++;
-				break;
-			case 'n':
-				n++;
-				break;
-			case 'N':
-				nflag++;
-				strcpy(narggrp,argv[1]);
-				strcat(narggrp,",");
-				break;
-			case 'e':
-			case 'f':
-				e++;
-				break;
-			}
-		}
-	}
-	if (!n && !e && !y && !q)
-		y++;
-	if (nflag)
-		argv++;
-
-#ifndef V6
-	if ((user = getenv("USER")) == NULL)
-		user = getenv("LOGNAME");
-	if ((home = getenv("HOME")) == NULL)
-		home = getenv("LOGDIR");
-	if (user == NULL || home == NULL)
-		getuser();
-	else {
-		username = AllocCpy(user);
-		userhome = AllocCpy(home);
-	}
-	if (ptr = getenv("NEWSOPTS"))
-		strcpy(rcbuf, ptr);
-	else
-		*rcbuf = '\0';
-	if (*rcbuf) {
-		strcat(rcbuf, " \1");
-		ptr = rcbuf;
-		while (*++ptr)
-			if (isspace(*ptr))
-				*ptr = '\0';
-		for (ptr = rcbuf;; ptr++) {
-			if (!*ptr)
-				continue;
-			if (*ptr == '\1')
-				break;
-			if (++line > LINES)
-				xerror("Too many options.");
-			if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL)
-				xerror("Not enough memory.");
-			argvrc[line] = rcline[line];
-			strcpy(rcline[line], ptr);
-			while (*ptr)
-				ptr++;
-		}
-	}
-#else
-	getuser();
-#endif
-	ptr = getenv("NEWSRC");
-	if (ptr == NULL)
-		sprintf(newsrc, "%s/%s", userhome, NEWSRC);
-	else
-		strcpy(newsrc, ptr);
-	if ((rcfp = fopen(newsrc, "r")) != NULL) {
-		while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
-			if (!(space = isspace(*rcbuf)))
-				optflag = FALSE;
-			if (!strncmp(rcbuf, "options ", 8))
-				optflag = TRUE;
-			if (optflag) {
-				strcat(rcbuf, "\1");
-				if (space)
-					ptr = rcbuf - 1;
-				else
-					ptr = &rcbuf[7];
-				while (*++ptr)
-					if (isspace(*ptr))
-						*ptr = '\0';
-				if (space)
-					ptr = rcbuf;
-				else
-					ptr = &rcbuf[8];
-				for (;; ptr++) {
-					if (!*ptr)
-						continue;
-					if (*ptr == '\1')
-						break;
-					if (++line > LINES)
-						xerror("Too many options.");
-					if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL)
-						xerror("Not enough memory.");
-					argvrc[line] = rcline[line];
-					strcpy(rcline[line], ptr);
-					while (*ptr)
-						ptr++;
-				}
-			}
-		}
-		fclose(rcfp);
-	}
-	header.nbuf[0] = 0;
-	if (line != -1) {
-#ifdef DEBUG
-		for (i = 0; i <= line; i++)
-			fprintf(stderr, "options:  %s\n", rcline[i]);
-#endif
-		process(line+2, argvrc);
-		do {
-#ifdef DEBUG
-			fprintf(stderr, "Freeing %d\n", line);
-#endif
-			free(rcline[line]);
-		} while (line--);
-	}
-
-	if (!*header.nbuf) {
-		strcpy(header.nbuf, DFLTSUB);
-		ngcat(header.nbuf);
-	}
-	strcat(header.nbuf, ADMSUB);
-	ngcat(header.nbuf);
-	if (*header.nbuf)
-		lcase(header.nbuf);
-	makehimask(header.nbuf, "junk");
-	makehimask(header.nbuf, "control");
-	makehimask(header.nbuf, "test");
-	if (access(newsrc, 0)) {
-		if (verbose > 1)
-			printf("No newsrc\n");
-		yep(argv);
-	}
-	if ((rcfp = fopen(newsrc, "r")) == NULL)
-		xerror("Cannot open .newsrc file");
-	while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
-		if (!nstrip(rcbuf))
-			xerror(".newsrc line too long");
-		if (++line >= LINES)
-			xerror("Too many .newsrc lines");
-		if ((rcline[line] = malloc(strlen(rcbuf)+1)) == NULL)
-			xerror("Not enough memory");
-		strcpy(rcline[line], rcbuf);
-	}
-	if ((actfp = fopen(ACTIVE, "r")) == NULL)
-		xerror("Cannot open active newsgroups file");
-
-#ifdef DEBUG
-	fprintf(stderr, "header.nbuf = %s\n", header.nbuf);
-#endif
-	nchk(argv);
-	exit(0);
-}
-
-nchk(argv)
-char **argv;
-{
-	register int i;
-	register char *ptr;
-	long l;
-	long narts;
-	char saveptr;
-	int isnews = 0;
-	char aline[BUFLEN];
-
-#ifdef DEBUG
-	fprintf(stderr, "nchk()\n");
-#endif
-	while (fgets(aline, sizeof aline, actfp) != NULL) {
-		sscanf(aline, "%s %ld", bfr, &narts);
-#ifdef DEBUG
-		fprintf(stderr, "bfr = '%s'\n", bfr);
-#endif
-		ngcat(bfr);
-		if (!ngmatch(bfr, nflag ? narggrp : header.nbuf))
-			continue;
-		ngdel(bfr);
-		i = findrcline(bfr);
-		if (i < 0) {
-			if (verbose>1)
-				printf("No newsrc line for newsgroup %s\n", bfr);
-			strcpy(rcbuf, " 0");
-		} else
-			strcpy(rcbuf, rcline[i]);
-		ptr = rcbuf;
-
-		if (index(rcbuf, '!') != NULL)
-			continue;
-		if (index(rcbuf, ',') != NULL) {
-			if (verbose > 1)
-				printf("Comma in %s newsrc line\n", bfr);
-			else {
-				isnews++;
-				continue;
-			}
-		}
-		while (*ptr)
-			ptr++;
-		while (!isdigit(*--ptr) && *ptr != ':' && ptr >= rcbuf)
-			;
-		if (*ptr == ':')
-			continue;
-		if (ptr < rcbuf) {
-			if (verbose > 1)
-				printf("Ran off beginning of %s newsrc line.\n", bfr);
-			yep(argv);
-		}
-		while (isdigit(*--ptr))
-			;
-		sscanf(++ptr, "%ld", &l);
-		if (narts > l) {
-			if (verbose) {
-				printf("News: %s ...\n", bfr);
-				if (verbose < 2)
-					y = 0;
-			}
-			yep(argv);
-		}
-contin:;
-	}
-	if (isnews)
-		yep(argv);
-	if (n)
-		printf("No news is good news.\n");
-}
-
-yep(argv)
-char **argv;
-{
-	if (y) {
-		if (verbose)
-			printf("There is probably news");
-		else
-			printf("There is news");
-		if (nflag) {
-			narggrp[strlen(narggrp)-1] = '.';
-			printf(" in %s\n",narggrp);
-		}
-		else
-			printf(".\n");
-	}
-	if (e) {
-#ifdef V6
-		execv("/usr/bin/readnews", argv);
-#else
-		execvp("readnews", argv);
-#endif
-		perror("Cannot exec readnews.");
-	}
-	if (q)
-		exit(1);
-	else
-		exit(0);
-}
-
-xerror(message, arg1, arg2)
-char *message;
-int arg1, arg2;
-{
-	char buffer[128];
-
-	sprintf(buffer, message, arg1, arg2);
-	fprintf(stderr, "checknews: %s.\n", buffer);
-	exit(1);
-}
-
-/*
- * Append NGDELIM to string.
- */
-ngcat(s)
-register char *s;
-{
-	if (*s) {
-		while (*s++);
-		s -= 2;
-		if (*s++ == NGDELIM)
-			return;
-	}
-	*s++ = NGDELIM;
-	*s = '\0';
-}
-
-/*
- * News group matching.
- *
- * nglist is a list of newsgroups.
- * sublist is a list of subscriptions.
- * sublist may have "meta newsgroups" in it.
- * All fields are NGDELIM separated,
- * and there is an NGDELIM at the end of each argument.
- *
- * Currently implemented glitches:
- * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
- * If subscription X matches Y, it also matches Y.anything.
- */
-ngmatch(nglist, sublist)
-register char *nglist, *sublist;
-{
-	register char *n, *s;
-	register int rc;
-
-	rc = FALSE;
-	for (n = nglist; *n != '\0' && rc == FALSE;) {
-		for (s = sublist; *s != '\0';) {
-			if (*s != NEGCHAR)
-				rc |= ptrncmp(s, n);
-			else
-				rc &= ~ptrncmp(s+1, n);
-			while (*s++ != NGDELIM);
-		}
-		while (*n++ != NGDELIM);
-	}
-	return(rc);
-}
-
-/*
- * Compare two newsgroups for equality.
- * The first one may be a "meta" newsgroup.
- */
-ptrncmp(ng1, ng2)
-register char *ng1, *ng2;
-{
-	while (*ng1 != NGDELIM) {
-		if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
-			ng1 += 3;
-			while (*ng2 != NGDELIM && *ng2 != '.')
-				if (ptrncmp(ng1, ng2++))
-					return(TRUE);
-			return (ptrncmp(ng1, ng2));
-		} else if (*ng1++ != *ng2++)
-			return(FALSE);
-	}
-	return (*ng2 == '.' || *ng2 == NGDELIM);
-}
-
-/*
- * Get user name and home directory.
- */
-getuser()
-{
-	static int flag = TRUE;
-	register struct passwd *p;
-
-	if (flag) {
-		if ((p = getpwuid(getuid())) == NULL)
-			xerror("Cannot get user's name");
-		if (username == NULL || *username == '\0')
-			username = AllocCpy(p->pw_name);
-		userhome = AllocCpy(p->pw_dir);
-		flag = FALSE;
-	}
-}
-
-/*
- * Strip trailing newlines, blanks, and tabs from 's'.
- * Return TRUE if newline was found, else FALSE.
- */
-nstrip(s)
-register char *s;
-{
-	register char *p;
-	register int rc;
-
-	rc = FALSE;
-	p = s;
-	while (*p)
-		if (*p++ == '\n')
-			rc = TRUE;
-	while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
-	*++p = '\0';
-	return(rc);
-}
-
-/*
- * Delete trailing NGDELIM.
- */
-ngdel(s)
-register char *s;
-{
-	if (*s++) {
-		while (*s++);
-		s -= 2;
-		if (*s == NGDELIM)
-			*s = '\0';
-	}
-}
-
-lcase(s)
-register char *s;
-{
-	register char *ptr;
-
-	for (ptr = s; *ptr; ptr++)
-		if (isupper(*ptr))
-			*ptr = tolower(*ptr);
-}
-
-/*
- * finds the line in your .newsrc file (actually the in-core "rcline"
- * copy of it) and returns the index into the array where it was found.
- * -1 means it didn't find it.
- *
- * We play clever games here to make this faster.  It's inherently
- * quadratic - we spend lots of CPU time here because we search through
- * the whole .newsrc for each line.  The "prev" variable remembers where
- * the last match was found; we start the search there and loop around
- * to the beginning, in the hopes that the calls will be roughly in order.
- */
-int
-findrcline(name)
-char *name;
-{
-	register char *p, *ptr;
-	register int cur;
-	register int i;
-	register int top;
-	static int prev = 0;
-
-	top = line; i = prev;
-loop:
-	for (; i <= top; i++) {
-		for (p = name, ptr = rcline[i]; (cur = *p++); ) {
-			if (cur != *ptr++)
-				goto contin2;
-		}
-		if (*ptr != ':' && *ptr != '!')
-			continue;
-		prev = i;
-		return i;
-contin2:
-		;
-	}
-	if (i > line && line > prev-1) {
-		i = 0;
-		top = prev-1;
-		goto loop;
-	}
-	return -1;
-}
-
-/*
- * Forbid newsgroup ng, unless he asked for it in nbuf.
- */
-makehimask(nbuf, ng)
-char *nbuf, *ng;
-{
-	if (!findex(nbuf, ng)) {
-		ngcat(nbuf);
-		strcat(nbuf, "!");
-		strcat(nbuf, ng);
-		ngcat(nbuf);
-	}
-}
-
-/*
- * Return true if the string searchfor is in string, but not if preceded by !.
- */
-findex(string, searchfor)
-char *string, *searchfor;
-{
-	register char first;
-	register char *p;
-
-	first = *searchfor;
-	for (p=index(string, first); p; p = index(p+1, first)) {
-		if (p>string && p[-1] != '!' && strncmp(p, searchfor, strlen(searchfor)) == 0)
-			return TRUE;
-	}
-	return FALSE;
-}
-
-xxit(i)
-{
-	exit(i);
-}
*-*-END-of-src/checknews.c-*-*
echo x - src/recnews.c 1>&2
sed 's/.//' >src/recnews.c <<'*-*-END-of-src/recnews.c-*-*'
-/*
- * recnews [to newsgroup] [from user]
- *
- * Process a news article which has been mailed to some group like msgs.
- * Such articles are in normal mail format and have never seen the insides
- * of netnews.  If the "to newsgroup" is included, the article is posted
- * to this newsgroup instead of trying to intuit it from the headers.
- * If the "from user" is included, the return address is forged to look
- * like that user instead of what getuid or a from line says.
- *
- * It is recommended that you always include the to newsgroup, since the
- * intuition code is flakey and out of date.  The from user is probably
- * appropriate for arpanet mailing lists being funnelled at ucbvax but
- * not otherwise.  Sample lines in /usr/lib/aliases (if you run delivermail):
- *	worldnews: "|/usr/lib/news/recnews net.general"
- *		Allows you to mail to worldnews rather than using inews.
- *		Intended for humans to mail to.
- *	post-unix-wizards: "|/usr/lib/news/recnews fa.unix-wizards unix-wizards"
- *		Causes mail to post-unix-wizards to be fed into fa.unix-wizards
- *		and the return address forged as unix-wizards on the local
- *		machine.  post-unix-wizards (on the local machine) should
- *		be part of the master mailing list somewhere (on a different
- *		machine.)
- *
- * Recnews is primarily useful in remote places on the usenet which collect
- * mail from mailing lists and funnel them into the network.  It is also
- * useful if you like to send mail to some user instead of invoking
- * inews -t .. -n .. when you want to submit an article.  (Many mailers give
- * you nice facilities like editing the message.)  It is not, however,
- * essential to use recnews to be able to join usenet.
- *
- * WARNING: recnews disables the "recording" check - it has to because
- * by the time inews is run, it's in the background and too late to
- * ask permission.  If you depend heavily on recordings you probably
- * should not allow recnews (and thus the mail interface) to be used.
-*
- * 1) We leave the from line alone.  Just escape the double quotes, but let the
- *    mailer do the rest.
- * 2) We give precedence to "From:" over "From " or ">From " in determining
- *    who the article is really from.
- *    Modifications by rad@tek
- */
-
-#ifdef SCCSID
-static char	*SccsId = "@(#)recnews.c	2.13	10/23/86";
-#endif /* SCCSID */
-
-#include "defs.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * Note: we assume there are 2 kinds of hosts using recnews:
- * Those that have delivermail (and hence this program will never
- * have to deal with more than one message at a time) and those on the arpanet
- * that do not (and hence all messages end with a sentinel).  It is
- * supposed that regular v7 type systems without delivermail or some
- * other automatic forwarding device will just use rnews.  We do
- * not attempt to tell where a message ends on all systems due to the
- * different conventions in effect.  (This COULD be fixed, I suppose.)
- */
-
-/*
- * Kinds of lines in a message.
- */
-#define FROM	001		/* From line */
-#define SUBJ	002		/* Subject */
-#define TO	003		/* To (newgroup based on this) */
-#define BLANK	004		/* blank line */
-#define EOM	005		/* End of message (4 ctrl A's) */
-#define HEADER	006		/* any unrecognized header */
-#define TEXT	007		/* anything unrecognized */
-#define INCLUSIVE 010		/* newsgroup is already in header */
-
-/*
- * Possible states program can be in.
- */
-#define SKIPPING	0100	/* In header of message */
-#define READING		0200	/* In body of message */
-
-#define BFSZ 250
-
-#define EOT	'\004'
-
-char	from[BFSZ];		/* mailing address for replies */
-char	sender[BFSZ];		/* mailing address of author, if different */
-char	to[BFSZ];		/* Destination of mail (msgs, etc) */
-char	subject[BFSZ];		/* subject of message */
-char	newsgroup[BFSZ];	/* newsgroups of message */
-int	fromset;		/* from passed on command line */
-char	cmdbuf[BFSZ];		/* command to popen */
-
-extern	char	*strcat(), *strcpy();
-extern	FILE	*popen();
-char	*any();
-
-main(argc, argv)
-int argc;
-char **argv;
-{
-	char buf[BFSZ], inews[BFSZ];
-	register char *p, *q;
-	register FILE *pipe = NULL;
-	register int state;
-
-	/* build inews command */
-#ifdef IHCC
-	sprintf(inews, "%s/%s/%s", logdir(HOME), LIBDIR, "inews");
-#else
-	sprintf(inews, "%s/%s", LIBDIR, "inews");
-#endif
-
-	if (argc > 1)
-		strcpy(to, argv[1]);
-	if (argc > 2)
-		strcpy(from, argv[2]);
-
-	/*
-	 * Flag that we know who message is from to avoid trying to 
-	 * decipher the From line.
-	 */
-	if (argc > 2 && (argv[2][0] != '\0'))
-		fromset++;
-
-#ifdef debug
-	printf("argv[0] is <%s>, argv[1] is <%s>, argv[2] is <%s>\n",
-		argv[0], argv[1], argv[2]);
-#endif
-	state = SKIPPING;
-	while (fgets(buf, BFSZ, stdin) != NULL) {
-		if (state == READING) {
-			fputs(buf,pipe);
-			continue;
-		}
-		switch (type(buf)) {
-
-		case FROM:
-			frombreak(buf, from);
-			break;
-
-		case SUBJ:
-			p = any(buf, " \t");
-			if (p == NULL)
-				p = buf + 8;
-			q = subject;
-			while (*++p) {
-				if (*p == '"')
-					*q++ = '\\';
-				*q++ = *p;
-			}
-			q[-1] = '\0';
-			break;
-
-		case TO:
-			if (to[0])
-				break;		/* already have one */
-			p = any(buf, " \t");
-			if (p == NULL)
-				p = buf + 3;
-			q = to;
-			while (*++p) {
-				if (*p == '"')
-					*q++ = '\\';
-				*q++ = *p;
-			}
-			q[-1] = '\0';
-			break;
-
-		case INCLUSIVE:
-			sprintf(cmdbuf,"exec %s -p", inews);
-			pipe = popen(cmdbuf,"w");
-			if (pipe == NULL){
-				perror("recnews: open failed");
-				exit(1);
-			}
-			state = READING;
-			fputs(buf,pipe);
-			break;
-			
-		/*
-		 * Kludge to compensate for messages without real headers
-		 */
-		case HEADER:
-			break;
-
-		case BLANK:
-			state = READING;
-			strcpy(newsgroup, to);
-			sprintf(cmdbuf, "exec %s -t \"%s\" -n \"%s\" -f \"%s\"",
-				inews, *subject ? subject : "(none)",
-				newsgroup, from);
-#ifdef debug
-			pipe = stdout;
-			printf("BLANK: %s\n", cmdbuf);
-#else
-			pipe = popen(cmdbuf, "w");
-			if (pipe == NULL) {
-				perror("recnews: popen failed");
-				exit(1);
-			}
-#endif
-			if (sender[0]) {
-				fputs(sender, pipe);
-				putc('\n', pipe);
-			}
-			break;
-
-		case TEXT:
-			strcpy(newsgroup, to);
-			state = READING;
-			if (subject[0] == 0) {
-				strcpy(subject, buf);
-				if (subject[strlen(subject)-1] == '\n')
-					subject[strlen(subject)-1] = '\0';
-			}
-			sprintf(cmdbuf, "exec \"%s\" -t \"%s\" -n \"%s\" -f \"%s\"",
-				inews, subject, newsgroup, from);
-#ifdef debug
-			pipe = stdout;
-			printf("TEXT: %s\n", cmdbuf);
-#else
-			pipe = popen(cmdbuf, "w");
-			if (pipe == NULL) {
-				perror("pipe failed");
-				exit(1);
-			}
-#endif
-			if (sender[0]){
-				fputs(sender, pipe);
-				putc('\n',pipe);
-			}
-			break;
-		}
-	}
-	exit(0);
-}
-
-type(p)
-register char *p;
-{
-	char *firstbl;
-	static char lasthdr = 1;		/* prev line was a header */
-
-	if ((*p == ' ' || *p == '\t') && lasthdr)
-		return HEADER;		/* continuation line */
-	firstbl = any(p, " \t");
-	while (*p == ' ' || *p == '?' || *p == '\t')
-		++p;
-
-	if (*p == '\n' || *p == 0)
-		return BLANK;
-	if (strncmp(p, ">From", 5) == 0 || strncmp(p, "From", 4) == 0)
-		return FROM;
-	if (strncmp(p, "Subj", 4)==0 || strncmp(p, "Re:", 3)==0 ||
-		strncmp(p, "re:", 3)==0)
-		return SUBJ;
-	if (strncmp(p, "To", 2)==0)
-		return TO;
-	if (strncmp(p, "\1\1\1\1", 4)==0)
-		return EOM;
-	if (firstbl && firstbl[-1] == ':' && isalpha(*p))
-		return HEADER;
-	lasthdr = 0;
-	return TEXT;
-}
-
-/*
- * Figure out who a message is from.
- */
-frombreak(buf, fbuf)
-register char *buf, *fbuf;
-{
-	register char *p, *q;
-
-	if (fbuf[0] && fromset) {	/* we already know who it's from */
-		if (sender[0] == 0 || buf[4] == ':') {
-#ifdef debug
-			printf("sender set to: %s", buf);
-#endif
-			strcpy(sender, buf);
-		}
-		return;
-	}
-	/*
-	 * Leave fancy Froms alone - this parsing is done by mail
-	 * Just quote the double quotes to prevent interpetation 
-	 * by the shell.
-	 * rad@tek
-	 */
-	p = any(buf, " \t");
-	if (p==NULL)
-		p = buf + 4;
-	q = fbuf;
-	while (*++p) {
-		if (*p == '"')
-			*q++ = '\\';
-		*q++ = *p;
-	}
-	q[-1] = '\0';
-	if ((p=(char *)index(fbuf,'\n')) != NULL)
-		*p = '\0';
-	if (buf[4] == ':')
-		fromset++;
-}
-
-/*
- * Return the ptr in sp at which a character in sq appears;
- * NULL if not found
- *
- */
-char *
-any(sp, sq)
-char *sp, *sq;
-{
-	register c1, c2;
-	register char *q;
-
-	while (c1 = *sp++) {
-		q = sq;
-		while (c2 = *q++)
-			if (c1 == c2)
-				return(--sp);
-	}
-	return(NULL);
-}
*-*-END-of-src/recnews.c-*-*
echo x - src/rextern.c 1>&2
sed 's/.//' >src/rextern.c <<'*-*-END-of-src/rextern.c-*-*'
-/*
- * rextern - external definitions for readnews
- */
-
-#ifdef SCCSID
-static char	*SccsId = "@(#)rextern.c	2.15	4/16/85";
-#endif /* SCCSID */
-
-/*LINTLIBRARY*/
-
-#include "rparams.h"
-
-int	uid, gid;			/* real user/group I.D.		*/
-int	duid, dgid;			/* effective user/group I.D.	*/
-int	SigTrap;			/* set if signal trapped	*/
-int	savmask;			/* old umask			*/
-int	mode;				/* mode of news program		*/
-struct hbuf header;			/* general-use header structure	*/
-char	bfr[LBUFLEN];			/* general-use scratch area	*/
-
-#ifndef ROOTID
-int	ROOTID;				/* special users id #		*/
-#endif
-
-char	*outfile = "/tmp/M1XXXXXX";	/* output file for -M and -c	*/
-char	*infile = "/tmp/M2XXXXXX";	/* -T output from Mail		*/
-int	ngrp, line = -1;
-
-char	filename[BUFLEN], coptbuf[BUFLEN], datebuf[BUFLEN];
-char	afline[BUFLEN];
-FILE	*rcfp, *actfp;
-time_t	atime;
-char	newsrc[BUFLEN], groupdir[BUFLEN], *rcline[LINES], rcbuf[LBUFLEN];
-char	*bitmap, *argvrc[LINES];
-long	bit, obit, last;
-int	readmode = NEXT;
-int	news = 0;		/* Was there any news to read */
-int	actdirect = FORWARD;	/* read direction in ACTIVE file */
-int	rcreadok = FALSE;	/* NEWSRC has been read OK */
-int	zapng = FALSE;		/* ! out this newsgroup on next updaterc */
-long	ngsize;			/* max article # in this newsgroup */
-long	minartno;		/* min article # in this newsgroup */
-
-#ifndef SHELL
-char	*SHELL;
-#endif
-
-#ifndef MAILER
-char	*MAILER;
-#endif
-
-char	*PAGER = "";
*-*-END-of-src/rextern.c-*-*
exit