2.9BSD/usr/contrib/news/src/rfuncs2.c

Compare this file to the similar file:
Show the results in this format:

/*
 * rfuncs2 - more routines needed by readr.
 */
static char *sccsid = "@(#)rfuncs2.c	1.9	4/25/83";

#include "rparams.h"

static char	lbuf[BUFLEN*2];

FILE *popen();

/*
 * nglist is the list of newsgroups in an article we want to follow up.
 * Do any special fascist processing to prevent certain kinds of followups.
 * In this case, there are two things we want to do:
 *	All followups to "net.general" are fed to "net.followup".
 *	However, if "net.general" is mentioned along with "net.news.group",
 *		just remove the net.general.
 */
launder(nglist)
char	*nglist;
{
	char	*cp, *op;
	char	outbuf[128];
	int	seen_group = 0;

	for (cp = index(nglist, 'n'); cp; cp = index(cp + 1, 'n'))
		if (strncmp("news.group", cp, 10) == 0)
			seen_group++;
	for (cp = index(nglist, 'n'); cp; cp = index(cp + 1, 'n'))
		if (strncmp("net.general", cp, 11) == 0) {
			/* 11 = strlen("net.general") */
			strcpy(outbuf, cp + 11);
			if (!seen_group) {
				strcpy(cp, "net.followup");
				cp += 12;  /* 12 = strlen("net.followup") */
			}
			if (cp[-1] == ',' && outbuf[0] == ',')
				cp--;
			strcpy(cp, outbuf);
		}
}


/*
 * Match title.
 */
titmat(h, titlist)
register struct hbuf *h;
register char	*titlist;
{
	register char	*p;
	register int	titlen;

	while (*titlist != '\0') {
		titlen = strlen(titlist);
		for (p = h->title; *p != '\0'; p++)
			if (strncmp(p, titlist, titlen) == 0) {
				return(TRUE);
			}
		titlist += titlen + 1;
	}
	return(FALSE);
}


/*
 * Save the news item in the user's file.
 * Fri Mar 12 20:04:43 EST 1982: (ittvax!swatt)
 *	Allow files with first character as '|' to write article
 *	to program across a pipe.
 */

#define PIPECHAR '|'

save(file, to)
register char	*file, *to;
{
	register FILE *ufp, *hfp;
	struct hbuf hh;
	int	isprogram = 0;
	int	isnew = 1;

	if ((hfp = fopen(file, "r")) == NULL) {
		printf("Can't get article.\n");
		return;
	}
	if (hread(&hh, hfp, TRUE) == NULL) {
		printf("Article is garbled.\n");
		return;
	}
	ufp = fopen(to, "r");
	if (ufp != NULL) {
		fclose(ufp);
		isnew = 0;
	}
	setgid(gid);
	setuid(uid);
	umask(savmask);

	if (*to == PIPECHAR) {
		if ((ufp = popen (&to[1], "w")) == NULL) {
			printf ("Cannot execute %s\n", &to[1]);
			return;
		}
		isprogram++;
	} else if ((ufp = fopen(to, "a")) == NULL) {
		printf("Cannot append to %s.\n", to);
		return;
	}
	/*
	 * V7MAIL code is here to conform to V7 mail format.
	 * If you need a different format to be able to
	 * use your local mail command (such as four ^A's
	 * on the end of articles) substitute it here.
	 */
#ifdef V7MAIL
	fprintf(ufp, "From %s %s",
#ifdef INTERNET
				hh.from,
#else
				hh.path,
#endif
					ctime(&hh.subtime));
#endif
	hprint(&hh, ufp, 2);
#ifdef V7MAIL
	tprint(hfp, ufp, TRUE);
	putc('\n', ufp);	/* force blank line at end (ugh) */
#else
	tprint(hfp, ufp, FALSE);
#endif
	fclose(hfp);
	if (isprogram)
		pclose (ufp);
	else
		fclose(ufp);
	if (!isprogram)
		printf("%s: %s\n", to, isnew ? "New file" : "Appended");
}


/*
 * Print out the rest of the article.
 */
tprint(ifp, ofp, checkfrom)
register FILE *ifp, *ofp;
int checkfrom;
{
	register int	c;

	while ((fgets(bfr, sizeof bfr, ifp)) != NULL && !sigtrap) {
		if (checkfrom && strncmp(bfr, "From ", 5) == 0)
			putc('>', ofp);
		fputs(bfr, ofp);
	}
	if (sigtrap)
		qfflush(ofp);
	fflush(ofp);
	fprintf(ofp, (sigtrap ? "\n\n" : "\n"));
	sigtrap = FALSE;
}


/*
 * Print the file header.
 */
hprint(hp, ofp, verbose)
register struct hbuf *hp;
int	verbose;
register FILE *ofp;
{
	register char	*p1, *p2;
	char	fname[BUFLEN];
	char *tailpath();

	fname[0] = '\0';		/* init name holder */

	if (verbose == 2) {
		lhwrite(hp, ofp);
		return;
	}

	if (lflag || eflag) {
		char buf1[80], buf2[200];
		char *cp;

		strcpy(bfr, groupdir);
		for (cp=bfr; *cp; cp++)
			if (*cp == '/')
				*cp = '.';
		sprintf(buf1, "%s/%d", bfr, bit);
		sprintf(buf2, "%-20s %s", buf1, hp->title);
		fprintf(ofp, "%.76s\n", buf2);
		return;
	}

	p1 = index(hp->from, '(');	/* Find the sender's full name. */
	if (p1 == NULL && hp->path[0])
		p1 = index(hp->path, '(');
	if (p1 != NULL) {
		strcpy(fname, p1+1);
		p2 = index(fname, ')');
		if (p2 != NULL)
			*p2 = '\0';
	}

	fprintf(ofp, "Subject: %s\n", hp->title);
	if (!hflag && hp->keywords[0])
		fprintf(ofp, "Keywords: %s\n", hp->keywords);
	if (verbose) {
		fprintf(ofp, "From: %s\n", hp->from);
		fprintf(ofp, "Path: %s\n", hp->path);
		if (hp->organization[0])
			fprintf(ofp, "Organization: %s\n", hp->organization);
	}
	else {
		if (p1 != NULL)
			*--p1 = '\0';		/* bump over the '(' */
#ifdef INTERNET
		/*
		 * Prefer Path line if it's in internet format, or if we don't
		 * understand internet format here, or if there is no reply-to.
		 */
		fprintf(ofp, "From: %s", hp->from);
#else
		fprintf(ofp, "Path: %s", tailpath(hp));
#endif
		if (fname[0] != '\0') {
			fprintf(ofp, " (%s", fname);
			if (hp->organization[0] && !hflag)
				fprintf(ofp, " @ %s", hp->organization);
			fprintf(ofp, ")");
		}
		fprintf(ofp, "\n");
		if (p1 != NULL)
			*p1 = ' ';
	}

	ngdel(strcpy(bfr, hp->nbuf));
	if (verbose) {
		fprintf(ofp, "Newsgroups: %s\n", bfr);
		fprintf(ofp, "Date: %s\n", hp->subdate);
		if (hp->sender[0])
			fprintf(ofp, "Sender: %s\n", hp->sender);
		if (hp->replyto[0])
			fprintf(ofp, "Reply-To: %s\n", hp->replyto);
		if (hp->followto[0])
			fprintf(ofp, "Followup-To: %s\n", hp->followto);
	}
	else if (index(bfr, ',') || strcmp(groupdir, "junk") == 0)
		fprintf(ofp, "Newsgroups: %s\n", bfr);

	if (pflag || ofp != stdout)
		putc('\n', ofp);
}


/*
 * If ofp != stdout, close it and run the script in coptbuf.
 */
cout(ofp)
FILE *ofp;
{
	register char	*p, *q, *r;

	if (ofp == stdout)
		return;
	fclose(ofp);
	p = coptbuf;
	q = lbuf;
	while ((*q = *p++) != '\0')
		if (*q++ == FMETA) {
			q--;
			r = outfile;
			while ((*q++ = *r++) != '\0')
				;
			q--;
		}
	fwait(fsubr(ushell, lbuf, (char *)NULL));
	unlink(outfile);
}


cdump(ofp)
register FILE *ofp;
{
	if (ofp == stdout)
		return;
	fclose(ofp);
	unlink(outfile);
}


/*
 * Quiet 'flush'.
 * Empty (without fflush()) the buffer for stream fp.
 */
/* ARGSUSED */
qfflush(fp)
FILE *fp;
{
	/* Alas, stdio does not permit this */
}


/*
 * Count the number of remaining lines in file fp.
 * Do not move the file pointer.
 */
linecnt(fp)
FILE *fp;
{
	long	curpos;
	register int	nlines = 0;
	register int	c;

	if (fp == NULL)
		return 0;
	curpos = ftell(fp);
	while ((c = getc(fp)) != EOF)
		if (c == '\n')
			nlines++;
	fseek(fp, curpos, 0);
	return nlines;
}


/*
 * Transmit file to system.
 */
transmit(sp, file)
register struct srec *sp;
char	*file;
{
	register FILE *ifp, *ofp;
	register int	c;
	struct hbuf hh;
	char	TRANS[BUFLEN];

#ifdef DEBUG
	fprintf(stderr, "xmit %s to %s using %s\n", file, sp->s_name, sp->s_xmit);
#endif
	ifp = xfopen(file, "r");
	if (hread(&hh, ifp, TRUE) == NULL)
		return;
	strcpy(TRANS, "/tmp/trXXXXXX");
	ofp = xfopen(mktemp(TRANS), "w");
	if (index(sp->s_flags, 'A') == NULL)
		hwrite(&hh, ofp);
	else
		ohwrite(&hh, ofp);
	while ((c = getc(ifp)) != EOF)
		putc(c, ofp);
	fclose(ifp);
	fclose(ofp);
	if (*sp->s_xmit == '\0' || index(sp->s_flags, 'F') || index(sp->s_flags, 'U'))
		sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
	else
		sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS);
#ifdef DEBUG
	fprintf(stderr, "%s\n", bfr);
#endif
	fwait(fsubr(pshell, bfr, (char *)NULL));
	unlink(TRANS);
}


/*
 * Cancel the article whose header is in hp, by posting a control message
 * to cancel it.  The scope of the control message depends on who would
 * really be willing to cancel it.  It is sent as far as it will do any good.
 * notauthor is true iff the person posting this article is not the
 * real author of the article being cancelled.
 */
cancel(ofp, hp, notauthor)
FILE *ofp;
struct hbuf *hp;
int	notauthor;
{
	FILE	*inews;
	struct utsname me;
	char	*p;
	char	distgroup[64];
	int	pid;

	fflush(stdout);
	pid = fork();
	if (pid > 0)
		return 0;
	uname(&me);
	strcpy(distgroup, hp->nbuf);
	p = index(distgroup, '.');
	if (notauthor)
		sprintf(distgroup, "to.%s", me.nodename);
	else
		sprintf(distgroup, "%s", hp->nbuf);
	sprintf(bfr, "%s -t 'cmsg cancel %s' -n %s < /dev/null",
	    INEWS, hp->ident, distgroup);
	if ((inews = popen(bfr, "w")) == NULL)
		fprintf(ofp, "Can't fork %s\n", INEWS);
	else
		pclose(inews);
	if (pid == 0)
		exit(0);
	return 0;
}


dash(num, ofp)
register int	num;
register FILE *ofp;
{
	register int	i;

	for (i = 0; i < num; i++)
		putc('-', ofp);
	putc('\n', ofp);
}


help(ofp)
register FILE *ofp;
{
	register FILE *fp;
	register int	c;

	if (cflag) {
oneline:
		fprintf(ofp, "(n)ext re(p)rint (w)rite (q)uit (r)eply\
 (c)ancel -[n] +[n] (f)ollowup (N)ext (U)nsubscribe (v)ersion\n");
		return;
	}
	if ((fp = fopen(HELPFILE, "r")) == NULL) {
		fprintf(ofp, "No help file.\n");
		goto oneline;
	}
	while ((c = getc(fp)) != EOF && !sigtrap)
		putc(c, ofp);
	fclose(fp);
}


pout(ofp)
FILE *ofp;
{
	register char	*p, *q, *r;

	p = PAGER;
	q = lbuf;
	while ((*q = *p++) != '\0')
		if (*q++ == FMETA) {
			q--;
			r = filename;
			while ((*q++ = *r++) != '\0')
				;
			q--;
		}
	fwait(fsubr(ushell, lbuf, (char *)NULL));
	fprintf(ofp, "\n");
}


/*
 * like strcat but be careful with quotes.  since there appears to be no way
 * to quote an apostrophe in sh, we change them to double quotes.
 */
strqcat(dest, src)
register char	*dest, *src;
{
	while (*dest++)
		;
	dest--;
	while (*src) {
		if (*src == '\'')
			*dest++ = '"', src++;
		else
			*dest++ = *src++;
	}
	*dest++ = 0;
}

/*
 * Print a very brief version of the date in question.
 */
char *
briefdate(datestr)
char *datestr;
{
	long dt, now;
	char *tmstr;
	char *wkday, *monthdate, *timeofday;
	static char rbuf[20];

	dt = cgtdate(datestr);
	tmstr = ctime(&dt);

	wkday = tmstr; tmstr[3] = '\0';
	monthdate = tmstr+4; tmstr[10] = '\0';
	timeofday = tmstr+11; tmstr[16] = '\0';

	time(&now);
	if (now - dt < 7 * DAYS)
		strcpy(rbuf, wkday);
	else
		strcpy(rbuf, monthdate);
	strcat(rbuf, " ");
	strcat(rbuf, timeofday);
	return rbuf;
}

/*
 * Return TRUE iff stdout is /dev/null.
 */
ignoring()
{
	struct stat ss, ns;

	fstat(1, &ss);
	stat("/dev/null", &ns);
	if (ss.st_dev == ns.st_dev && ss.st_rdev == ns.st_rdev)
		return TRUE;
	return FALSE;
}