news 2.10.2 src part 5 (reposting)
Rick Adams
rick at seismo.UUCP
Sat Sep 8 10:29:27 AEST 1984
cat <<'E_O_F'
This was received truncated at a lot of places
E_O_F
if test ! -d src
then
mkdir src
echo mkdir src
fi
echo x - src/process.c
sed 's/^X//' >src/process.c <<'*-*-END-of-src/process.c-*-*'
X/*
X * process - process options for readnews
X */
X
Xstatic char *SccsId = "@(#)process.c 2.9 4/20/84";
X
X#include "rparams.h"
X
X#define OPTION 0 /* pick up an option string */
X#define STRING 1 /* pick up a string of arguments */
X
Xstruct optable *optpt, options[] = { /*
Xoptlet filchar flag newstate oldmode newmode buf */
X'p', '\0', FALSE, OPTION, UNKNOWN, UNKNOWN,(char *)NULL,
X't', '\0', FALSE, STRING, ANY, UNKNOWN,header.title,
X'a', ' ', FALSE, STRING, ANY, UNKNOWN,datebuf,
X'n', NGDELIM, FALSE, STRING, ANY, UNKNOWN,header.nbuf,
X'c', ' ', FALSE, STRING, UNKNOWN, UNKNOWN,coptbuf,
X'l', ' ', FALSE, OPTION, UNKNOWN, UNKNOWN,(char *)NULL,
X'r', '\0', FALSE, OPTION, ANY, UNKNOWN,(char *)NULL,
X's', NGDELIM, FALSE, STRING, ANY, UNKNOWN,header.nbuf,
X'x', '\0', FALSE, OPTION, ANY, UNKNOWN,(char *)NULL,
X'h', '\0', FALSE, OPTION, ANY, UNKNOWN,(char *)NULL,
X'M', '\0', FALSE, OPTION, UNKNOWN, MAIL, (char *)NULL,
X'f', '\0', FALSE, OPTION, ANY, UNKNOWN,(char *)NULL,
X'u', '\0', FALSE, OPTION, ANY, UNKNOWN,(char *)NULL,
X'e', '\0', FALSE, OPTION, ANY, UNKNOWN,(char *)NULL,
X'\0', '\0', 0, 0, 0, 0, (char *)NULL
X};
X
Xprocess(argc,argv)
Xregister int argc;
Xregister char **argv;
X{
X register int state = OPTION;
X register char *ptr;
X char filchar;
X int len, tlen;
X
X /* loop once per arg. */
X
X while (--argc) {
X if (state == OPTION) {
X if (**argv != '-') {
X sprintf(bfr, "Bad option string \"%s\"", *argv);
X xerror(bfr);
X }
X while (*++*argv != '\0') {
X for (optpt = options; optpt->optlet != '\0'; ++optpt) {
X if (optpt->optlet == **argv)
X goto found;
X }
X /* unknown option letter */
X fprintf(stderr, "Usage: readnews [ -a [ date ]] [ -n newsgroups ] [ -t titles ] [ -lprxhfuM ]\n");
X fprintf(stderr, "\t[ -c [ ``mailer'' ]]\n\n");
X fprintf(stderr, " readnews -s\n");
X exit(1);
X
X found:;
X if (mode != UNKNOWN && (mode&optpt->oldmode) == 0) {
X sprintf(bfr, "Bad %c option", **argv);
X xerror(bfr);
X }
X if (mode == UNKNOWN)
X mode = optpt->newmode;
X filchar = optpt->filchar;
X optpt->flag = TRUE;
X state = optpt->newstate;
X ptr = optpt->buf;
X len = LBUFLEN;
X }
X
X argv++; /* done with this option arg. */
X
X } else {
X
X /*
X * Pick up a piece of a string and put it into
X * the appropriate buffer.
X */
X if (**argv == '-') {
X state = OPTION;
X argc++; /* uncount this arg. */
X continue;
X }
X
X if ((tlen = strlen(*argv)) >= len)
X xerror("Argument string too long");
X strcpy(ptr, *argv++);
X ptr += tlen;
X if (*(ptr-1) != filchar)
X *ptr++ = filchar;
X len -= tlen + 1;
X *ptr = '\0';
X }
X }
X return;
X}
*-*-END-of-src/process.c-*-*
echo x - src/readnews.c
sed 's/^X//' >src/readnews.c <<'*-*-END-of-src/readnews.c-*-*'
X/*
X * readnews - read news articles.
X */
X
X#ifndef lint
Xstatic char *SccsId = "@(#)readnews.c 2.19 8/28/84";
X#endif !lint
X
X#include "rparams.h"
X
X/*
X * readnews - article reading program
X */
X
X#ifndef SYSBUF
Xchar SYSBUF[BUFSIZ]; /* to buffer std out */
X#endif
X
X#define OPTION 0 /* pick up an option string */
X#define STRING 1 /* pick up a string of arguments */
X
Xint onsig();
X
X/*
X * Authors:
X * Matt Glickman ucbvax!glickman
X * Mark Horton cbosg!mark
X * Stephen Daniels duke!swd
X * Tom Truscott duke!trt
X */
X
Xmain(argc, argv)
Xint argc;
Xregister char **argv;
X{
X register char *ptr; /* pointer to rest of buffer */
X char *user, *home;
X int optflag = FALSE, space = FALSE;
X struct utsname ubuf;
X char *myrc;
X
X /* set up defaults and initialize. */
X pathinit();
X mode = UNKNOWN;
X header.title[0] = header.nbuf[0] = '\0';
X titlebuf[0] = coptbuf[0] = datebuf[0] = '\0';
X uname(&ubuf);
X strcpy(FULLSYSNAME, ubuf.nodename);
X
X savmask = umask(N_UMASK); /* set up mask */
X uid = getuid();
X gid = getgid();
X duid = 0;
X dgid = 0;
X
X#ifndef V6
X#ifndef SHELL
X if ((SHELL = getenv("SHELL")) == NULL)
X SHELL = "/bin/sh";
X#endif
X#ifndef IHCC
X /*
X * IHCC does not allow use of $LOGNAME to prevent forgery.
X * Note that this shouldn't matter in readnews, since inews
X * does all the actual posting of news.
X */
X if ((user = getenv("USER")) == NULL)
X user = getenv("LOGNAME");
X if ((home = getenv("HOME")) == NULL)
X home = getenv("LOGDIR");
X#endif
X if (user == NULL || home == NULL)
X getuser();
X else {
X username = AllocCpy(user);
X strcpy(header.path, username);
X userhome = AllocCpy(home);
X }
X
X getuser();
X if (!(MAILER = getenv("MAILER")))
X MAILER = "mail"; /* was /bin/mail */
X
X#ifdef PAGE
X if (myrc = getenv("PAGER"))
X strcpy(PAGER, myrc);
X else
X# ifdef IHCC
X sprintf(PAGER,"%s/bin/%s",logdir(HOME),PAGE);
X# else
X strcpy(PAGER, PAGE);
X# endif
X#else
X strcpy(PAGER, "");
X#endif
X
X if (ptr = getenv("NEWSOPTS"))
X strcpy(rcbuf, ptr);
X else
X *rcbuf = '\0';
X if (*rcbuf) {
X strcat(rcbuf, " \1");
X ptr = rcbuf;
X while (*++ptr)
X if (isspace(*ptr))
X *ptr = '\0';
X for (ptr = rcbuf; ; ptr++) {
X if (!*ptr)
X continue;
X if (*ptr == '\1')
X break;
X if (++line > LINES)
X xerror("Too many options.");
X if ((rcline[line] = malloc((unsigned)(strlen(ptr) + 1))) == NULL)
X xerror("Not enough memory.");
X argvrc[line] = rcline[line];
X strcpy(rcline[line], ptr);
X while (*ptr)
X ptr++;
X }
X }
X#else
X getuser();
X#endif
X myrc = getenv("NEWSRC");
X if (myrc == NULL) {
X myrc = NEWSRC;
X sprintf(newsrc, "%s/%s", userhome, myrc);
X } else {
X strcpy(newsrc, myrc);
X }
X if (access(newsrc, 0))
X newrc(newsrc);
X if ((rcfp = fopen(newsrc, "r")) != NULL) {
X rcreadok = FALSE;
X while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
X if (!(space = isspace(*rcbuf)))
X optflag = FALSE;
X if (!strncmp(rcbuf, "options ", 8))
X optflag = TRUE;
X if (optflag) {
X strcat(rcbuf, "\1");
X if (space)
X ptr = rcbuf - 1;
X else
X ptr = &rcbuf[7];
X while (*++ptr)
X if (isspace(*ptr))
X *ptr = '\0';
X if (space)
X ptr = rcbuf;
X else
X ptr = &rcbuf[8];
X for (; ; ptr++) {
X if (!*ptr)
X continue;
X if (*ptr == '\1')
X break;
X if (++line > LINES)
X xerror("Too many options.");
X if ((rcline[line] = malloc((unsigned)(strlen(ptr) + 1))) == NULL)
X xerror("Not enough memory.");
X argvrc[line] = rcline[line];
X strcpy(rcline[line], ptr);
X while (*ptr)
X ptr++;
X }
X }
X }
X fclose(rcfp);
X rcreadok = TRUE;
X }
X if (line != -1) {
X#ifdef DEBUG
X for (i = 0; i <= line; i++)
X fprintf(stderr, "options: %s\n", rcline[i]);
X#endif
X process(line + 2, argvrc);
X do {
X#ifdef DEBUG
X fprintf(stderr, "Freeing %d\n", line);
X#endif
X free(rcline[line]);
X } while (line--);
X }
X
X argv++;
X strcat(header.nbuf, ADMSUB);
X ngcat(header.nbuf);
X process(argc, argv);
X if (!nflag) {
X strcpy(header.nbuf, DFLTSUB);
X ngcat(header.nbuf);
X strcat(header.nbuf, ADMSUB);
X ngcat(header.nbuf);
X }
X if (*header.nbuf)
X lcase(header.nbuf);
X makehimask(header.nbuf, "junk");
X makehimask(header.nbuf, "control");
X makehimask(header.nbuf, "test");
X
X setbuf(stdout, SYSBUF);
X sigtrap = FALSE; /* true if a signal has been caught */
X if (!pflag && !lflag && !eflag) {
X signal(SIGQUIT, SIG_IGN);
X signal(SIGHUP, onsig);
X signal(SIGINT, onsig);
X signal(SIGPIPE, onsig);
X }
X
X /*
X * ALL of the command line has now been processed. (!)
X */
X
X if (!*header.nbuf)
X ngcat(strcpy(header.nbuf, DFLTSUB));
X if (sflag) {
X ngdel(header.nbuf);
X printf("Subscription list: %s\n", header.nbuf);
X xxit(0);
X }
X if (xflag)
X line = -1;
X rcfp = xfopen(newsrc, "r");
X while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
X if (!nstrip(rcbuf))
X xerror(".newsrc line too long");
X if (++line >= LINES)
X xerror("Too many .newsrc lines");
X if ((rcline[line] = malloc((unsigned)(strlen(rcbuf) + 1))) == NULL)
X xerror("Not enough memory");
X strcpy(rcline[line], rcbuf);
X }
X fclose(rcfp);
X
X if (sigtrap) {
X if (sigtrap == SIGHUP || !rcreadok)
X xxit(0);
X fprintf(stdout, "Abort (n)? ");
X fflush(stdout);
X if (gets(bfr) == NULL || *bfr == 'y' || *bfr == 'Y')
X xxit(0);
X sigtrap = FALSE;
X }
X#ifdef SORTACTIVE
X sortactive();
X#endif
X actfp = xfopen(ACTIVE, "r");
X
X#ifdef DEBUG
X fprintf(stderr, "header.nbuf = %s\n", header.nbuf);
X#endif
X switch (mode) {
X case UNKNOWN:
X readr();
X break;
X#ifdef TMAIL
X case MAIL:
X Mail();
X break;
X#endif
X }
X fflush(stdout);
X if (xflag || lflag || tflag)
X xxit(0);
X if (*groupdir && mode != MAIL)
X updaterc();
X writeoutrc();
X xxit(0);
X
X /* Camel, R.O.H. */
X}
X
X/*
X * Write out the .newsrc file. We sort it into "active" file order,
X * for speed in future invocations, and to get rid of junk.
X */
Xwriteoutrc()
X{
X FILE *wrcfp, *afp;
X char aline[BUFLEN];
X register int i, c;
X register char *p;
X
X if (!rcreadok)
X return;
X#ifdef VMS
X unlink(newsrc);
X#endif
X
X wrcfp = xfopen(newsrc, "w");
X afp = xfopen(ACTIVE, "r");
X
X /* Write out options line, continuations, and comments. */
X for (i=0;rcline[i];i++) {
X c = rcline[i][0];
X if (c != 'o' && c != '#' && c != ' ' && c != '\t')
X break;
X if (c == 'o' && strncmp(rcline[i], "options", 7) != 0)
X break;
X fprintf(wrcfp, "%s\n", rcline[i]);
X }
X
X /* For each newsgroup in active, find that newsrc line and write it out. */
X while (fgets(aline, sizeof aline, afp)) {
X p = index(aline, ' ');
X if (p)
X *p = 0;
X i = findrcline(aline);
X if (i >= 0)
X fprintf(wrcfp, "%s\n", rcline[i]);
X }
X fclose(wrcfp);
X fclose(afp);
X}
X
X/*
X * Forbid newsgroup ng, unless he asked for it in nbuf.
X */
Xmakehimask(nbuf, ng)
Xchar *nbuf, *ng;
X{
X if (!findex(nbuf, ng)) {
X ngcat(nbuf);
X strcat(nbuf, "!");
X strcat(nbuf, ng);
X ngcat(nbuf);
X }
X}
X
X/*
X * Return true if the string searchfor is in string, but not if preceeded by !.
X */
Xfindex(string, searchfor)
Xchar *string, *searchfor;
X{
X register char first;
X register char *p;
X
X first = *searchfor;
X for (p=index(string, first); p; p = index(p+1, first)) {
X if (((p==string) || (p[-1]!='!')) && strncmp(p, searchfor, strlen(searchfor)) == 0)
X return TRUE;
X }
X return FALSE;
X}
*-*-END-of-src/readnews.c-*-*
echo x - src/readr.c
sed 's/^X//' >src/readr.c <<'*-*-END-of-src/readr.c-*-*'
X/*
X * readr - /bin/mail and msgs interface and associated functions.
X */
X
X#ifndef lint
Xstatic char *SccsId = "@(#)readr.c 2.45 9/3/84";
X#endif !lint
X
X#include "rparams.h"
X#if defined(BSD4_2) || defined(BSD4_1C)
X#include <sys/dir.h>
X#else
X#include "ndir.h"
X#endif !BSD4_2 && !BSD4_1C
X#include <setjmp.h>
X#include <errno.h>
X
Xextern int errno;
X
Xchar *Progname = "readnews"; /* used by xerror to identify failing program */
X
Xstatic char lbuf[BUFLEN*2];
Xlong atol();
X
X#define saveart oobit = bit;strcpy(ofilename1, filename);strcpy(ogroupdir, groupdir);hptr = h;h = hold;hold = hptr;ongsize = pngsize
X#define NLINES(h, fp) (h->numlines[0] ? h->intnumlines : (h->intnumlines=linecnt(fp),sprintf(h->numlines, "%d", h->intnumlines), h->intnumlines))
X
Xchar *tft = "/tmp/folXXXXXX";
X
X/*
X * These were made static for u370 with its buggy cc.
X * I judged it better to have one copy with no ifdefs than
X * to conditionally compile them as automatic variables
X * in readr (which they originally were). Performance
X * considerations might warrent moving some of the simple
X * things into register variables, but I don't know what
X * breaks the u370 cc.
X */
Xstatic char goodone[BUFLEN]; /* last decent article */
Xstatic char ogroupdir[BUFLEN]; /* last groupdir */
Xstatic char address[PATHLEN]; /* for reply copy */
Xstatic char edcmdbuf[128];
Xstatic int rfq = 0; /* for last article */
Xstatic long ongsize; /* Previous ngsize */
Xstatic long pngsize; /* Printing ngsize */
Xstatic char *bptr; /* temp pointer. */
Xstatic struct srec srec; /* srec for sys file entries */
Xstatic char *tfilename; /* temporary file name */
Xstatic char ofilename1[BUFLEN]; /* previous file name */
Xstatic struct hbuf hbuf1, hbuf2, /* for minusing */
X *h = &hbuf1, /* current header */
X *hold = &hbuf2, /* previous header */
X *hptr; /* temporary */
Xstatic char *ptr1, *ptr2, *ptr3; /* for reply manipulation */
Xstatic int news = 0;
Xstatic int abs = FALSE; /* TRUE if we asked absolutely */
Xstatic char tf[100];
Xstatic long oobit; /* last bit, really */
Xstatic int dgest = 0;
Xstatic FILE *ofp; /* Current output file to terminal*/
Xstatic FILE *fp; /* current article to be printed*/
Xstatic int holdup; /* 1 iff should stop before hdr */
Xstatic int ignorenews; /* 1 iff readnews -p > /dev/null*/
Xstatic time_t timelastsaved; /* time newsrc last written out */
Xstatic jmp_buf sigjmpbuf; /* for signal processing */
Xstatic int canlongjmp; /* TRUE if setjmp on sigjmp valid */
X
Xint catchcont();
X
Xreadr()
X{
X
X#ifdef DEBUG
X fprintf(stderr, "readr()\n");
X#endif
X if (aflag) {
X if (*datebuf) {
X if ((atime = cgtdate(datebuf)) == -1)
X xerror("Cannot parse date string");
X } else
X atime = 0;
X }
X
X if (pflag && ignoring())
X ignorenews = TRUE;
X
X if (xflag)
X uflag = 0;
X if (uflag)
X (void) time(&timelastsaved);
X
X ofp = stdout;
X if (cflag && coptbuf[0] != '\0') {
X umask(022);
X mktemp(outfile); /* get "unique" file name */
X close(creat(outfile,0666));
X ofp = xfopen(outfile, "w");
X umask(N_UMASK);
X cflag = FALSE;
X pflag = TRUE;
X }
X
X /* loop reading articles. */
X fp = NULL;
X obit = -1;
X nextng();
X for ( ;; ) {
X if (getnextart(FALSE))
X break;
X#ifdef DEBUG
X fprintf(stderr,"after getnextart, fp %x, pos %ld, bit %ld, group '%s', filename '%s'\n",
X fp, ftell(fp), bit, groupdir, filename);
X#endif
X strcpy(goodone, filename);
X if (pflag || lflag || eflag) {
X /* This code should be gotten rid of */
X if (sigtrap) {
X qfflush(ofp);
X fprintf(ofp, "\n");
X cdump(ofp);
X xxit(0); /* kludge! drop when qfflush works */
X return;
X }
X clear(bit);
X nextbit();
X FCLOSE(fp);
X continue;
X }
X for ( ;; ) {
X char *pp;
X int nlines;
X int (*ointr)();
X#ifdef SIGCONT
X int (*ocont)();
X#endif
X setjmp(sigjmpbuf);
X canlongjmp = TRUE;
X
X sigtrap = FALSE;
X if (!cflag) {
X if (rfq)
X sprintf(bfr, "Last article. [qfr] ");
X else {
X nlines = NLINES(h, fp);
X if (nlines <= 0) {
X sprintf(bfr, "(0 lines) Next? [nqfr] ");
X FCLOSE(fp);
X } else {
X sprintf(bfr, "(%d lines) More? [ynq] ", nlines);
X }
X }
X } else
X sprintf(bfr, "? ");
X fprintf(ofp, "%s", bfr);
X fflush(ofp);
X bptr = lbuf;
X ointr = signal(SIGINT, catchcont);
X#ifdef SIGCONT
X ocont = signal(SIGCONT, catchcont);
X#endif
X pp = fgets(bptr, BUFLEN, stdin);
X canlongjmp = FALSE;
X signal(SIGINT, ointr);
X#ifdef SIGCONT
X signal(SIGCONT, ocont);
X#endif
X if (pp != NULL)
X break;
X if (!sigtrap)
X return;
X#ifdef SIGCONT
X if (sigtrap != SIGCONT)
X#endif
X fprintf(ofp, "\n");
X }
X nstrip(bptr);
X while (*bptr == ' ' || *bptr == '\t')
X bptr++;
X if (command())
X break;
X }
X
X if (!news)
X fprintf(stderr, "No news.\n");
X cout(ofp);
X}
X
X
X#define EOL() if (*bptr != '\0') { fprintf(ofp, "? for commands.\n"); return FALSE; }
X/*
X * Process one command, which has already been typed in.
X */
Xcommand()
X{
X char *findhist();
X long i;
X
X switch (*bptr++) {
X
X /* No. Go on to next article. */
X case 'n':
X EOL();
X readmode = NEXT;
X if (!cflag)
X FCLOSE(fp);
X fprintf(ofp, "\n");
X clear(bit);
X saveart;
X nextbit();
X break;
X
X /* Undigestify the article. */
X case 'd':
X dgest = 1;
X /* fall through */
X
X /* yes: print this article, go on. */
X case 'y':
X EOL();
X /* fall through. */
X
X /* The user hit return. Default is 'y' unless rfq, then it's 'q'. */
X case '\0':
X if (!bptr[-1] && rfq)
X return TRUE;
X readmode = NEXT;
X showtail(fp);
X clear(bit);
X saveart;
X nextbit();
X break;
X
X /*
X * Unsubscribe to the newsgroup and go on to next group
X */
X case 'u':
X fprintf(ofp, "To unsubscribe, use 'U'\n");
X break;
X
X case 'U':
X fprintf(ofp, "Unsubscribing to newsgroup: %s\n", groupdir);
X obit = -1;
X FCLOSE(fp);
X if (cflag)
X clear(bit);
X else
X putc('\n', ofp);
X rfq = 0;
X zapng = TRUE;
X saveart;
X if (nextng()) {
X if (actdirect == BACKWARD)
X fprintf(ofp, "Can't back up.\n");
X else
X return TRUE;
X }
X break;
X
X /* Print the current version of news */
X case 'v':
X fprintf(ofp, "News version: %s\n", news_version);
X break;
X
X /* reprint the article */
X case 'p':
X EOL();
X if (!cflag)
X goto minus;
X readmode = NEXT;
X if (!cflag) {
X FCLOSE(fp);
X bit = last;
X putc('\n', ofp);
X }
X obit = -1;
X break;
X
X /* decrypt joke */
X case 'D':
X caesar_command();
X readmode = NEXT;
X clear(bit);
X saveart;
X nextbit();
X break;
X
X /* write out the article someplace */
X case 's':
X case 'w':
X {
X char *grn = groupdir;
X tfilename = filename;
X if (*bptr == '-') {
X bptr++;
X grn = ogroupdir;
X if (*ofilename1)
X tfilename = ofilename1;
X }
X if (*bptr != '\0' && *bptr != ' ') {
X fprintf(ofp, "Bad file name.\n");
X break;
X }
X while (*bptr == ' ')
X bptr++;
X if (*bptr != '|' && *bptr != '/') {
X char hetyped[BUFLEN];
X char *boxptr;
X strcpy(hetyped, bptr);
X if (boxptr = getenv("NEWSBOX"))
X if (index(boxptr, '%'))
X sprintf(bptr, boxptr, grn);
X else
X strcpy(bptr, boxptr);
X else if (hetyped[0] == '~' && hetyped[1] == '/') {
X strcpy(hetyped, bptr+2);
X strcpy(bptr, userhome);
X } else
X strcpy(bptr, ".");
X strcat(bptr, "/");
X if (hetyped[0] != '\0')
X strcat(bptr, hetyped);
X else
X strcat(bptr, "Articles");
X }
X fwait(fsubr(save, tfilename, bptr));
X }
X break;
X
X /* back up */
X case '-':
Xminus:
X rfq = 0;
X abs = TRUE;
X if (!*ofilename1) {
X fprintf(ofp, "Can't back up.\n");
X break;
X }
X if (cflag)
X clear(bit);
X else {
X FCLOSE(fp);
X putc('\n', ofp);
X }
X hptr = h;
X h = hold;
X hold = hptr;
X strcpy(bfr, filename);
X strcpy(filename, ofilename1);
X strcpy(ofilename1, bfr);
X obit = bit;
X if (strcmp(groupdir, ogroupdir)) {
X strcpy(bfr, groupdir);
X selectng(ogroupdir, TRUE);
X strcpy(groupdir, ogroupdir);
X strcpy(ogroupdir, bfr);
X ngrp = 1;
X back();
X }
X bit = oobit;
X oobit = obit;
X obit = -1;
X (void) getnextart(TRUE);
X return FALSE;
X
X /* skip forwards */
X case '+':
Xcaseplus:
X if (*bptr == '\0')
X strcat(bptr, "1");
X rfq = 0;
X if (cflag)
X clear(bit);
X saveart;
X last = bit;
X for (i = 0; i < atol(bptr); i++) {
X nextbit();
X if ((bit > pngsize) || (rflag && bit < 1))
X break;
X }
X if (!cflag) {
X putc('\n', ofp);
X FCLOSE(fp);
X }
X obit = -1;
X break;
X
X /* exit - time updated to that of most recently read article */
X case 'q':
X EOL();
X return TRUE;
X
X /* exit - no time update. */
X case 'x':
X EOL();
X xxit(0);
X
X /* cancel the article. */
X case 'c':
X (void) cancel_command();
X break;
X
X /* escape to shell */
X case '!':
X fwait(fsubr(ushell, bptr, (char *)NULL));
X fprintf(ofp, "\n");
X hdr();
X break;
X
X /* mail reply */
X case 'r':
X (void) reply_command();
X break;
X
X /* send to some system */
X case 'X':
X xmit_command();
X break;
X /* mark the rest of the articles in this group as read */
X case 'K':
X saveart;
X while (bit <= pngsize && bit >= minartno) {
X clear(bit);
X nextbit();
X }
X FCLOSE(fp);
X break;
X
X /* next newsgroup */
X case 'P':
X *bptr = '-';
X case 'N':
X FCLOSE(fp);
X if (next_ng_command())
X return TRUE;
X break;
X
X case 'b': /* back up 1 article */
X i = bit - 1;
X goto tryartnum;
X case '0': /* specific no. */
X case '1':
X case '2':
X case '3':
X case '4':
X case '5':
X case '6':
X case '7':
X case '8':
X case '9':
X sscanf(--bptr, "%ld", &i);
X if (i == 0) {
X fprintf(ofp, "Bad article no.\n");
X break;
X }
X if (i > pngsize) {
X fprintf(ofp, "Not that many articles.\n");
X break;
X }
Xtryartnum:
X readmode = SPEC;
X abs = TRUE;
X bit = i;
X obit = -1;
X if (!cflag) {
X putc('\n', ofp);
X FCLOSE(fp);
X }
X rfq = 0;
X break;
X
X /* specific message ID. */
X case '<':
X ptr1 = findhist(--bptr);
X if (ptr1 == NULL) {
X fprintf(ofp, "No such article: %s.\n", bptr);
X break;
X }
X ptr2 = index(ptr1, '\t');
X ptr3 = index(++ptr2, '\t');
X ptr2 = index(++ptr3, ' ');
X if (ptr2)
X *ptr2 = '\0';
X ptr2 = index(ptr3, '/');
X *ptr2++ = '\0';
X abs = TRUE;
X if (cflag)
X clear(bit);
X else {
X FCLOSE(fp);
X putc('\n', ofp);
X }
X saveart;
X strcpy(ogroupdir, ptr3);
X if (strcmp(groupdir, ogroupdir)) {
X strcpy(bfr, groupdir);
X selectng(ogroupdir, TRUE);
X strcpy(groupdir, ogroupdir);
X strcpy(ogroupdir, bfr);
X back();
X }
X sscanf(ptr2, "%ld", &bit);
X oobit = obit;
X obit = -1;
X (void) getnextart(TRUE);
X rfq = 0;
X break;
X
X /* follow-up article */
X case 'f':
X if (*bptr == '-')
X tfilename = ofilename1;
X else
X tfilename = filename;
X sprintf(bfr,"%s/%s %s", BIN, "postnews", tfilename);
X system(bfr);
X break;
X
X /* erase - pretend we haven't seen this article. */
X case 'e':
X if (rfq || *bptr == '-') {
X if (strcmp(groupdir, ogroupdir)) {
X i = bit;
X strcpy(bfr, groupdir);
X selectng(ogroupdir, FALSE);
X set(oobit);
X fprintf(ofp,"Holding article %ld newsgroup %s\n", oobit, ogroupdir),
X strcpy(groupdir, ogroupdir);
X selectng(bfr, FALSE);
X bit = i;
X } else {
X fprintf(ofp,"Holding article %ld\n", oobit);
X set(oobit);
X }
X } else {
X fprintf(ofp,"Holding article %ld\n", bit);
X set(bit);
X goto caseplus; /* skip this article for now */
X }
X break;
X
X case 'H':
X case 'h':
X if (!hflag)
X dash(8, ofp);
X if (*bptr == '-') {
X if (oobit > 0)
X fprintf(ofp, "Article %ld:\n", oobit);
X hprint(hold, ofp, 1 + (bptr[-1]=='H'));
X } else {
X fprintf(ofp, "Article %ld of %ld: %s\n",
X rfq ? oobit : bit, pngsize, h->ident);
X hprint(h, ofp, 1 + (bptr[-1]=='H'));
X }
X if (!hflag)
X dash(8, ofp);
X break;
X
X case '#':
X fprintf(ofp, "Article %ld of %ld: newsgroup %s\n",
X rfq ? oobit : bit, pngsize, rfq ? ogroupdir : groupdir);
X break;
X
X /* error */
X case '?':
X help(ofp);
X break;
X default:
X fprintf(ofp, "? for commands.\n");
X break;
X }
X
X return FALSE;
X}
X
Xcancel_command()
X{
X tfilename = filename;
X hptr = h;
X if (*bptr == '-') {
X if (*ofilename1) {
X tfilename = ofilename1;
X hptr = hold;
X }
X bptr++;
X }
X EOL();
X readmode = SPEC;
X strcpy(rcbuf, hptr->path);
X ptr1 = index(rcbuf, ' ');
X if (ptr1)
X *ptr1 = 0;
X if (uid != ROOTID && strcmp(username, rcbuf)) {
X fprintf(ofp, "Can't cancel what you didn't write.\n");
X return FALSE;
X }
X if (!cancel(ofp, hptr, 0) && hptr == h) {
X clear(bit);
X saveart;
X nextbit();
X obit = -1;
X if (!cflag)
X putc('\n', ofp);
X FCLOSE(fp);
X }
X return TRUE;
X}
X
Xreply_command()
X{
X register char *pathptr;
X int edit = 1;
X char *ed;
X FILE *tfp;
X char curberk[BUFLEN];
X char *replyname();
X char subj[BUFLEN];
X char folbuf[BUFLEN];
X extern char MAILPARSER[];
X struct stat statb;
X long creatm;
X
X hptr = h;
X while (*bptr && index("d-", *bptr)) {
X switch (*bptr) {
X /* Followup the previous article. */
X case '-':
X hptr = hold;
X break;
X
X /* Don't edit the headers */
X case 'd':
X edit = 0;
X break;
X }
X bptr++;
X }
X EOL();
X if (edit && access(MAILPARSER, 1)) {
X#ifdef IHCC
X fprintf(stderr, "Can't edit headers, 'recmail' missing.\n");
X#else
X fprintf(stderr, "Can't edit headers without %s\n", MAILPARSER);
X#endif
X edit = 0;
X }
X
X *rcbuf = '\0';
X *curberk = '\0';
X pathptr = replyname(hptr);;
X for (ptr1 = address, ptr2 = pathptr; *ptr2; ptr1++, ptr2++) {
X if (index("\"\\$", *ptr2))
X *ptr1++ = '\\';
X *ptr1 = *ptr2;
X }
X *ptr1 = '\0';
X
X folbuf[0] = '\0'; /* References */
X if (hptr->followid[0]) {
X strcpy(folbuf, hptr->followid);
X strcat(folbuf, ", ");
X }
X strcat(folbuf, hptr->ident);
X
X strcpy(subj, hptr->title); /* Subject */
X while (isspace(*bptr))
X bptr++;
X if (*bptr != '\0')
X strcpy(subj, bptr);
X if (!prefix(subj, "Re:")){
X strcpy(bfr, subj);
X sprintf(subj, "Re: %s", bfr);
X }
X if (!edit) {
X fprintf(ofp, "To: %s\n", pathptr);
X ed = index(MAILER, '%');
X if (ed && ed[1] == 's')
X fprintf(ofp, "Subject: %s\n", subj);
X fflush(ofp);
X }
X
X /* Put the user in the editor to create the body of the followup. */
X if (edit) {
X strcpy(tf, tft);
X mktemp(tf);
X
X ed = getenv("EDITOR");
X if (ed == NULL)
X ed = DFTEDITOR;
X
X if ((tfp = fopen(tf, "w")) == NULL) {
X perror(tf);
X creatm = 0L;
X } else {
X fprintf(tfp, "To: %s\n", pathptr);
X fprintf(tfp, "Subject: %s\n", subj);
X fprintf(tfp, "References: %s\n\n", folbuf);
X fstat(fileno(tfp), &statb);
X creatm = statb.st_mtime;
X fclose(tfp);
X }
X
X sprintf(edcmdbuf, "%s %s", ed, tf);
X system(edcmdbuf);
X strcpy(rcbuf, MAILPARSER);
X strcat(rcbuf, " -t");
X strcat(rcbuf, " < ");
X strcat(rcbuf, tf);
X if (access(tf, 4) || stat(tf, &statb)) {
X fprintf(stderr, "Reply not sent: no input file.\n");
X return FALSE;
X }
X if (statb.st_mtime == creatm) {
X fprintf(stderr, "Reply not sent: cancelled.\n");
X unlink(tf);
X return FALSE;
X }
X fprintf(ofp,"Sending reply.\n");
X fflush(stdout);
X if (fork() == 0) {
X system(rcbuf);
X unlink(tf);
X _exit(0);
X }
X } else {
X sprintf(rcbuf, MAILER, hptr->title);
X sprintf(bfr, "%s %s", rcbuf, address);
X system(bfr);
X }
X hdr();
X return TRUE;
X}
X
Xxmit_command()
X{
X tfilename = filename;
X if (*bptr == '-') {
X if (*ofilename1)
X tfilename = ofilename1;
X bptr++;
X }
X if (*bptr != '\0' && *bptr != ' ') {
X fprintf(ofp, "Bad system name.\n");
X return;
X }
X while (*bptr == ' ')
X bptr++;
X if (*bptr == '\0') {
X fprintf(ofp, "Missing system name.\n");
X return;
X }
X if (s_find(&srec, bptr) == NULL) {
X fprintf(ofp, "%s not in SYSFILE\n", bptr);
X return;
X }
X transmit(&srec, tfilename);
X}
X
Xnext_ng_command()
X{
X obit = -1;
X if (!*bptr || *bptr == '-') {
X if (cflag)
X clear(bit);
X else
X putc('\n', ofp);
X if (*bptr)
X actdirect = BACKWARD;
X rfq = 0;
X saveart;
X if (nextng()) {
X if (actdirect == BACKWARD)
X fprintf(ofp, "Can't back up.\n");
X else
X return TRUE;
X }
X return FALSE;
X }
X while (isspace(*bptr))
X bptr++;
X if (!validng(bptr)) {
X fprintf(ofp, "No such group.\n");
X return FALSE;
X }
X if (cflag)
X clear(bit);
X else
X putc('\n', ofp);
X readmode = SPEC;
X rfq = 0;
X saveart;
X back();
X selectng(bptr, TRUE);
X return FALSE;
X}
X
Xcaesar_command()
X{
X char temp[BUFLEN];
X FILE *pfp, *popen();
X
X fprintf(stderr, "Caesar decoding:\n");
X sprintf(temp, "%s/%s", LIB, "caesar");
X if (*bptr) {
X strcat(temp, " ");
X strcat(temp, bptr);
X }
X if (NLINES(h, fp) > LNCNT && *PAGER) {
X strcat(temp, " | ");
X strcat(temp, PAGER);
X }
X pfp = popen(temp, "w");
X tprint(fp, pfp, FALSE);
X FCLOSE(fp);
X pclose(pfp);
X}
X
X/*
X * Show the user the tail, if any, of the message on file
X * descriptor fd, and close fd. The digester is considered,
X * and the pager is used if appropriate.
X */
Xshowtail(fd)
XFILE *fd;
X{
X if (fd == NULL)
X return;
X
X if (dgest) {
X digest(fd, ofp, h);
X } else if (!lflag && !pflag && !eflag) {
X pprint(fd);
X }
X fclose(fd);
X}
X
X/*
X * Print out the rest of the article through the pager.
X */
Xpprint(fd)
XFILE *fd;
X{
X#ifdef PAGE
X /* Filter the tail of long messages through PAGER. */
X if (NLINES(h, fd) > LNCNT && *PAGER) {
X if (!index(PAGER, FMETA)) {
X FILE *pfp, *popen();
X
X pfp = popen(PAGER, "w");
X if (pfp == NULL)
X pfp = ofp;
X /*
X * What follows is an attempt to prevent the
X * next message from scrolling part of this
X * message off the top of the screen before
X * the poor luser can read it.
X */
X tprint(fd, pfp, FALSE);
X pclose(pfp);
X }
X else
X pout(ofp);
X holdup = TRUE;
X }
X else
X#endif
X tprint(fd, ofp, FALSE);
X}
X
X/*
X * Find the next article we want to consider, if we're done with
X * the last one, and show the header.
X */
Xgetnextart(minus)
Xint minus;
X{
X int noaccess;
X register DIR *dirp;
X register struct direct *dir;
X long nextnum, tnum;
X
X noaccess = 0;
X
X if (minus)
X goto nextart2; /* Kludge for "-" command. */
X
X if (bit == obit) /* Return if still on same article as last time */
X return 0;
X
X sigtrap = FALSE;
X
Xnextart:
X#ifdef DEBUG
X fprintf(stderr,"nextart:\n");
X#endif DEBUG
X dgest = 0;
X
X if (bit < minartno && !rflag)
X bit = minartno;
X
X /* If done with this newsgroup, find the next one. */
X while (ngsize <= 0 || ((long) bit > ngsize) || (rflag && bit < minartno)) {
X if (nextng()) {
X if (actdirect == BACKWARD) {
X fprintf(ofp, "Can't back up.\n");
X actdirect = FORWARD;
X continue;
X } else
X if (rfq++ || pflag || cflag)
X return 1;
X }
X if (rflag)
X bit = ngsize + 1;
X else
X bit = minartno - 1;
X if (uflag) {
X time_t now;
X (void) time(&now);
X if (now - timelastsaved > 5*60 /* 5 minutes */) {
X fprintf(stderr,"[Saving .newsrc]\n");
X writeoutrc();
X timelastsaved = now;
X }
X }
X }
X
Xnextart2:
X#ifdef DEBUG
X fprintf(stderr, "article: %s/%ld\n", groupdir, bit);
X#endif
X if (rcreadok)
X rcreadok = 2; /* have seen >= 1 article */
X sprintf(filename, "%s/%ld", dirname(groupdir), bit);
X if (rfq && goodone[0])
X strcpy(filename, goodone);
X if (sigtrap) {
X if (sigtrap == SIGHUP)
X return 1;
X if (!rcreadok)
X xxit(0);
X fprintf(ofp, "Abort (n)? ");
X fflush(ofp);
X gets(bfr);
X if (*bfr == 'y' || *bfr == 'Y')
X xxit(0);
X sigtrap = FALSE;
X }
X#ifdef DEBUG
X fprintf(stderr, "filename = '%s'\n", filename);
X#endif
X /* Decide if we want to show this article. */
X if ((fp = fopen(filename, "r")) == NULL) {
X /* since there can be holes in legal article numbers, */
X /* we wait till we hit 5 consecutive bad articles */
X /* before we haul off and scan the directory */
X if (++noaccess < 5)
X goto badart;
X noaccess = 0;
X dirp = opendir(dirname(groupdir));
X if (dirp == NULL) {
X if (errno != EACCES)
X fprintf(stderr,"Can't open %s", dirname(groupdir));
X goto badart;
X }
X nextnum = rflag ? minartno - 1 : ngsize + 1;
X while ((dir = readdir(dirp)) != NULL) {
X tnum = atol(dir->d_name);
X if (tnum <= 0)
X continue;
X if (rflag ? (tnum > nextnum && tnum < bit)
X : (tnum < nextnum && tnum > bit))
X nextnum = tnum;
X }
X closedir(dirp);
X if (rflag ? (nextnum >= bit) : (nextnum <= bit))
X goto badart;
X#ifdef DEBUG
X fprintf(stderr,"nextnum = %ld\n",nextnum);
X#endif DEBUG
X do {
X clear(bit);
X nextbit();
X } while (rflag ? (nextnum < bit) : (nextnum > bit));
X obit = -1;
X abs = FALSE;
X goto nextart;
X } else
X noaccess = 0;
X
X if (ignorenews || hread(h, fp, TRUE) == NULL
X || (!rfq && !aselect(h, abs))) {
X badart:
X#ifdef DEBUG
X fprintf(stderr, "Bad article '%s'\n", filename);
X#endif
X FCLOSE(fp);
X clear(bit);
X obit = -1;
X nextbit();
X abs = FALSE;
X goto nextart;
X }
X abs = FALSE;
X actdirect = FORWARD;
X news = TRUE;
X hdr();
X if (pflag)
X tprint(fp, ofp, FALSE);
X else if (cflag && !lflag && !eflag) {
X fflush(ofp);
X pprint(fp);
X }
X if (cflag || lflag || eflag || pflag) {
X sigtrap = FALSE;
X FCLOSE(fp);
X }
X obit = bit;
X return 0;
X}
X
X/*
X * Print out whatever the appropriate header is
X */
Xhdr()
X{
X char *briefdate();
X
X if (rfq)
X return;
X
X if (lflag || eflag) {
X hprint(h, ofp, 0);
X return;
X }
X
X /* Print out a header */
X if (ngrp) {
X pngsize = ngsize;
X ngrp--;
X nghprint(groupdir);
X }
X if (!hflag)
X fprintf(ofp, "Article %ld of %ld, %s.\n",
X bit, pngsize, briefdate(h->subdate));
X hprint(h, ofp, pflag ? 1 : 0);
X}
X
Xnghprint(title)
Xchar *title;
X{
X char *tstr = "Newsgroup ";
X int l = strlen(title) + strlen(tstr);
X
X fprintf(ofp, "\n");
X if (!hflag) {
X dash(l, ofp);
X fprintf(ofp, "%s%s\n", tstr, title);
X dash(l, ofp);
X } else {
X fprintf(ofp, "%s%s, ", tstr, title);
X if (bit == pngsize)
X fprintf(ofp, "%ld\n", pngsize);
X else
X fprintf(ofp, "%ld-%ld\n", bit, pngsize);
X }
X fprintf(ofp, "\n");
X}
X
X/*
X * Routine to catch a continue signal.
X */
Xcatchcont(sig)
Xint sig;
X{
X signal(sig, catchcont);
X sigtrap = sig;
X fflush(ofp);
X#ifdef SIGCONT
X if (fp && sig == SIGCONT)
X hdr();
X if (sig != SIGCONT)
X#endif SIGCONT
X putc('\n', ofp);
X if (canlongjmp)
X longjmp(sigjmpbuf,1);
X}
*-*-END-of-src/readr.c-*-*
echo x - src/recmail.c
sed 's/^X//' >src/recmail.c <<'*-*-END-of-src/recmail.c-*-*'
X/*
X * recmail: read a mail message on stdin, grab all addresses in To and Cc
X * lines, and pass the full message to all addressees. This is useful to
X * send the output of a recently edited mail message (with headers edited too).
X * It is similar to sendmail -t, but only assumes /bin/mail.
X * To use your own mailer, e. g. nmail, compile with -DMAILER=my_mailer.
X */
X
X#ifndef lint
Xstatic char *SccsId = "@(#)recmail.c 1.8 8/14/84";
X#endif !lint
X
X#include <stdio.h>
X#include <ctype.h>
X#include <pwd.h>
X#ifdef USG
Xstruct passwd *getpwent(), *getpwuid(), *getpwnam();
X#endif USG
X
X#ifndef MAILER
X#define MAILER "/bin/mail"
X#endif
Xchar mailer[] = MAILER;
X
X#define MAXRECIPS 100
Xchar *recips[MAXRECIPS];
Xint nrecips = 0;
X
Xmain()
X{
X FILE *fd;
X char *tmpf;
X FILE *errfd;
X char *errf;
X char linebuf[1024];
X int i, pid, wpid;
X int exstat;
X char *mypath;
X int goodcnt, badcnt;
X char *mktemp(), *getenv();
X
X tmpf = mktemp("/tmp/rmXXXXXX");
X close(creat(tmpf,0666));
X fd = fopen(tmpf, "w");
X errf = mktemp("/tmp/rmXXXXXX");
X close(creat(errf,0666));
X errfd = fopen(errf, "w");
X fprintf(errfd, "Subject: Returned mail\n");
X fprintf(errfd, "\n ----- Transcript of session follows -----\n");
X fflush(errfd);
X goodcnt = badcnt = 0;
X
X while (fgets(linebuf, sizeof linebuf, stdin) != NULL) {
X if (fputs(linebuf, fd) == EOF)
X goto werror;
X if (linebuf[0] == '\n')
X break;
X if (strncmp(linebuf, "To: ", 4) == 0 ||
X strncmp(linebuf, "to: ", 4) == 0 ||
X strncmp(linebuf, "TO: ", 4) == 0 ||
X strncmp(linebuf, "Cc: ", 4) == 0 ||
X strncmp(linebuf, "cc: ", 4) == 0 ||
X strncmp(linebuf, "CC: ", 4) == 0)
X addrecips(linebuf+4);
X }
X if (!feof(stdin)) {
X while (fgets(linebuf, sizeof linebuf, stdin) != NULL) {
X if (fputs(linebuf, fd) == EOF) {
Xwerror:
X printf("write error on temp file\n");
X exit(2);
X }
X }
X }
X fclose(fd);
X
X /*
X * Force the path to only consider /bin and /usr/bin, since
X * that's the version of mail we want (not /usr/ucb/mail)
X * This code will probably cause a core dump some day.
X */
X mypath = getenv("PATH");
X if (mypath)
X strcpy(mypath, "/bin:/usr/bin");
X
X /*
X * We send the copies out separately, because of a bug in
X * USG's /bin/mail which will generate ANOTHER To: line,
X * even though we already have one, if there are at least
X * two recipients.
X */
X for (i=0; i<nrecips; i++) {
X /*
X * mail recips[i] < tmpf
X */
X pid = mailto(tmpf, errfd, recips[i]);
X exstat = -1;
X while ((wpid = wait(&exstat)) >= 0 && wpid != pid)
X ;
X if (exstat == 0)
X goodcnt++;
X else
X badcnt++;
X }
X if (badcnt) {
X mailback(errfd, tmpf, errf);
X unlink(tmpf);
X unlink(errf);
X exit(1);
X } else if (goodcnt == 0) {
X fprintf(errfd, "recmail: no 'To:' line\n");
X mailback(errfd, tmpf, errf);
X unlink(tmpf);
X unlink(errf);
X exit (1);
X }
X unlink(tmpf);
X unlink(errf);
X exit (0);
X}
X
X#define isok(c) (isprint(c) && (c) != ' ' && c != ',')
Xaddrecips(line)
Xchar *line;
X{
X char *front, *back, *tail;
X char *malloc();
X
X tail = line + strlen(line);
X for (front=line; front < tail; ) {
X while (!isok(*front) && front < tail)
X front++;
X for (back=front; isok(*back); back++)
X ;
X *back=0;
X if (nrecips >= MAXRECIPS) {
X printf("Too many destinations\n");
X exit(2);
X }
X if ((recips[nrecips] = malloc(strlen(front) + 1)) == NULL) {
X printf("Out of space\n");
X exit(2);
X }
X strcpy(recips[nrecips], front);
X nrecips++;
X front = back+1;
X }
X}
X
Xint
Xmailto(tmpf, errfd, recip)
Xchar *tmpf;
XFILE *errfd;
Xchar *recip;
X{
X register int pid;
X
X /*
X * mail recips < tmpf
X */
X while ((pid = fork()) == -1) {
X fprintf(stderr, "fork failed, waiting...\r\n");
X sleep(60);
X }
X if (pid == 0) {
X close(0);
X open(tmpf, 0);
X if (errfd != NULL) {
X close(1);
X dup(fileno(errfd));
X fclose(errfd);
X close(2);
X dup(1);
X }
X execlp(mailer, mailer, recip, (char *)0);
X perror(mailer);
X exit(1);
X }
X return(pid);
X}
X
Xmailback(errfd, tmpf, errf)
Xregister FILE *errfd;
Xchar *tmpf;
Xchar *errf;
X{
X register FILE *fd;
X register int c;
X int exstat;
X register int pid, wpid;
X char *logn;
X char *getlogin(), *getenv();
X register struct passwd *pwd;
X
X if ((fd = fopen(tmpf, "r")) != NULL) {
X fprintf(errfd, "\n ----- Unsent message follows -----\n");
X while ((c = getc(fd)) != EOF)
X putc(c, errfd);
X fclose(fd);
X }
X fclose(errfd);
X if ((logn = getlogin()) == NULL && (logn = getenv("USER")) == NULL) {
X if ((pwd = getpwent(getuid())) == NULL)
X return;
X logn = pwd->pw_name;
X }
X pid = mailto(errf, (FILE *)NULL, logn);
X while ((wpid = wait(&exstat)) >= 0 && wpid != pid)
X ;
X}
*-*-END-of-src/recmail.c-*-*
echo x - src/recnews.c
sed 's/^X//' >src/recnews.c <<'*-*-END-of-src/recnews.c-*-*'
X/*
X * recnews [to newsgroup] [from user]
X *
X * Process a news article which has been mailed to some group like msgs.
X * Such articles are in normal mail format and have never seen the insides
X * of netnews. If the "to newsgroup" is included, the article is posted
X * to this newsgroup instead of trying to intuit it from the headers.
X * If the "from user" is included, the return address is forged to look
X * like that user instead of what getuid or a from line says.
X *
X * It is recommended that you always include the to newsgroup, since the
X * intution code is flakey and out of date. The from user is probably
X * appropriate for arpanet mailing lists being funnelled at ucbvax but
X * not otherwise. Sample lines in /usr/lib/aliases (if you run delivermail):
X * worldnews: "|/usr/lib/news/recnews net.general"
X * Allows you to mail to worldnews rather than using inews.
X * Intended for humans to mail to.
X * post-unix-wizards: "|/usr/lib/news/recnews fa.unix-wizards unix-wizards"
X * Causes mail to post-unix-wizards to be fed into fa.unix-wizards
X * and the return address forged as unix-wizards on the local
X * machine. post-unix-wizards (on the local machine) should
X * be part of the master mailing list somewhere (on a different
X * machine.)
X *
X * Recnews is primarily useful in remote places on the usenet which collect
X * mail from mailing lists and funnel them into the network. It is also
X * useful if you like to send mail to some user instead of invoking
X * inews -t .. -n .. when you want to submit an article. (Many mailers give
X * you nice facilities like editing the message.) It is not, however,
X * essential to use recnews to be able to join usenet.
X *
X * WARNING: recnews disables the "recording" check - it has to because
X * by the time inews is run, it's in the background and too late to
X * ask permission. If you depend heavily on recordings you probably
X * should not allow recnews (and thus the mail interface) to be used.
X */
X
X#ifndef lint
Xstatic char *SccsId = "@(#)recnews.c 2.9 9/3/84";
X#endif !lint
X
X#include "defs.h"
X
X#include <stdio.h>
X#include <ctype.h>
X
X/*
X * Note: we assume there are 2 kinds of hosts using recnews:
X * Those that have delivermail (and hence this program will never
X * have to deal with more than one message at a time) and those on the arpanet
X * that do not (and hence all messages end with a sentenel). It is
X * supposed that regular v7 type systems without delivermail or some
X * other automatic forwarding device will just use rnews. We do
X * not attempt to tell where a message ends on all systems due to the
X * different conventions in effect. (This COULD be fixed, I suppose.)
X */
X
X/*
X * Kinds of lines in a message.
X */
X#define FROM 001 /* From line */
X#define SUBJ 002 /* Subject */
X#define TO 003 /* To (newgroup based on this) */
X#define BLANK 004 /* blank line */
X#define EOM 005 /* End of message (4 ctrl A's) */
X#define HEADER 006 /* any unrecognized header */
X#define TEXT 007 /* anything unrecognized */
X#define INCLUSIVE 010 /* newsgroup is already in header */
X
X/*
X * Possible states program can be in.
X */
X#define SKIPPING 0100 /* In header of message */
X#define READING 0200 /* In body of message */
X
X#define BFSZ 250
X
X#define EOT '\004'
X
Xchar from[BFSZ]; /* mailing address for replies */
Xchar sender[BFSZ]; /* mailing address of author, if different */
Xchar to[BFSZ]; /* Destination of mail (msgs, etc) */
Xchar subject[BFSZ]; /* subject of message */
Xchar newsgroup[BFSZ]; /* newsgroups of message */
Xchar cmdbuf[BFSZ]; /* command to popen */
X
Xextern char *strcat(), *strcpy();
Xextern FILE *popen();
Xchar *any();
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X char buf[BFSZ], inews[BFSZ];
X register char *p, *q;
X register FILE *pipe = NULL;
X register int state;
X
X /* build inews command */
X#ifdef IHCC
X sprintf(inews, "%s/%s/%s", logdir(HOME), LIBDIR, "inews");
X#else
X sprintf(inews, "%s/%s", LIBDIR, "inews");
X#endif
X
X if (argc > 1)
X strcpy(to, argv[1]);
X if (argc > 2)
X strcpy(from, argv[2]);
X#ifdef debug
X printf("argv[0] is <%s>, argv[1] is <%s>, argv[2] is <%s>\n",
X argv[0], argv[1], argv[2]);
X#endif
X state = SKIPPING;
X while (fgets(buf, BFSZ, stdin) != NULL) {
X if (state == READING) {
X fputs(buf,pipe);
X continue;
X }
X switch (type(buf)) {
X
X case FROM:
X frombreak(buf, from);
X break;
X
X case SUBJ:
X p = any(buf, " \t");
X if (p == NULL)
X p = buf + 8;
X q = subject;
X while (*++p) {
X if (*p == '"')
X *q++ = '\\';
X *q++ = *p;
X }
X q[-1] = '\0';
X break;
X
X case TO:
X if (to[0])
X break; /* already have one */
X p = any(buf, " \t");
X if (p == NULL)
X p = buf + 3;
X q = to;
X while (*++p) {
X if (*p == '"')
X *q++ = '\\';
X *q++ = *p;
X }
X q[-1] = '\0';
X break;
X
X case INCLUSIVE:
X sprintf(cmdbuf,"exec %s -p", inews);
X pipe = popen(cmdbuf,"w");
X if (pipe == NULL){
X perror("recnews: open failed");
X exit(1);
X }
X state = READING;
X fputs(buf,pipe);
X break;
X
X /*
X * Kludge to compensate for messages without real headers
X */
X case HEADER:
X break;
X
X case BLANK:
X state = READING;
X findgroup(to, newsgroup);
X sprintf(cmdbuf, "exec %s -t \"%s\" -n \"%s\" -f \"%s\"",
X inews, subject, newsgroup, from);
X#ifdef debug
X pipe = stdout;
X printf("BLANK: %s\n", cmdbuf);
X#else
X pipe = popen(cmdbuf, "w");
X if (pipe == NULL) {
X perror("recnews: popen failed");
X exit(1);
X }
X#endif
X if (sender[0]) {
X fputs(sender, pipe);
X putc('\n', pipe);
X }
X break;
X
X case TEXT:
X findgroup(to, newsgroup);
X state = READING;
X if (subject[0] == 0) {
X strcpy(subject, buf);
X if (subject[strlen(subject)-1] == '\n')
X subject[strlen(subject)-1] = '\0';
X }
X sprintf(cmdbuf, "exec \"%s\" -t \"%s\" -n \"%s\" -f \"%s\"",
X inews, subject, newsgroup, from);
X#ifdef debug
X pipe = stdout;
X printf("TEXT: %s\n", cmdbuf);
X#else
X pipe = popen(cmdbuf, "w");
X if (pipe == NULL) {
X perror("pipe failed");
X exit(1);
X }
X#endif
X if (sender[0]){
X fputs(sender, pipe);
X putc('\n',pipe);
X }
X break;
X }
X }
X exit(0);
X}
X
Xtype(p)
Xregister char *p;
X{
X char *firstbl;
X static char lasthdr; /* prev line was a header */
X
X lasthdr = 1;
X if ((*p == ' ' || *p == '\t') && lasthdr)
X return HEADER; /* continuation line */
X firstbl = any(p, " \t");
X while (*p == ' ' || *p == '?' || *p == '\t')
X ++p;
X
X if (*p == '\n' || *p == 0)
X return BLANK;
X if (strncmp(p, ">From", 5) == 0 || strncmp(p, "From", 4) == 0)
X return FROM;
X if (strncmp(p, "Subj", 4)==0 || strncmp(p, "Re:", 3)==0 ||
X strncmp(p, "re:", 3)==0)
X return SUBJ;
X if (strncmp(p, "To", 2)==0)
X return TO;
X if (strncmp(p, "\1\1\1\1", 4)==0)
X return EOM;
X if (firstbl && firstbl[-1] == ':' && isalpha(*p))
X return HEADER;
X lasthdr = 0;
X return TEXT;
X}
X
X/*
X * Figure out who a message is from.
X */
Xfrombreak(buf, fbuf)
Xregister char *buf, *fbuf;
X{
X char wordfrom[BFSZ], uname[BFSZ], at[BFSZ], site[BFSZ];
X
X if (fbuf[0]) { /* we already know who it's from */
X if (sender[0] == 0 || buf[4] == ':') {
X#ifdef debug
X printf("sender set to: %s", buf);
X#endif
X strcpy(sender, buf);
X }
X return;
X }
X /* break the line into tokens. */
X sscanf(buf, "%s %s %s %s", wordfrom, uname, at, site);
X if (isat(at))
X /*
X * Some arpanet mail comes from "joe at mit-dms"
X * instead of "joe at mit-dms", so handle it here.
X */
X sprintf(fbuf, "%s@%s", uname, site);
X else
X strcpy(fbuf, uname);
X}
X
Xisat(str)
Xchar *str;
X{
X if (strcmp(str, "@")==0) return TRUE;
X if (strcmp(str, "at")==0) return TRUE;
X if (strcmp(str, "AT")==0) return TRUE;
X return FALSE;
X}
X
Xfindgroup(dest, group)
Xchar *dest ;
Xchar *group;
X{
X#ifdef debug
X printf("findgroup(%s)\n", dest);
X#endif
X#ifdef fussy
X /*
X * Default unknown "to" fields to "general". This gives you
X * tight control over which newsgroups exist.
X */
X if (strcmp(dest, "msgs")==0)
X strcpy(group, "msgs");
X else if (strcmp(dest, "allmsgs")==0)
X strcpy(group, "NET.allmsgs");
X else if (strcmp(dest, "csmsgs")==0)
X strcpy(group, "NET.csmsgs");
X else
X strcpy(group, "general");
X#else
X /*
X * Allow any newsgroup. This way you don't have to recompile
X * recnews everytime you add a newsgroup.
X */
X strcpy(group, dest);
X#endif
X}
X
X/*
X * Return the ptr in sp at which a character in sq appears;
X * NULL if not found
X *
X */
X
Xchar *
Xany(sp, sq)
Xchar *sp, *sq;
X{
X register c1, c2;
X register char *q;
X
X while (c1 = *sp++) {
X q = sq;
X while (c2 = *q++)
X if (c1 == c2)
X return(--sp);
X }
X return(NULL);
X}
*-*-END-of-src/recnews.c-*-*
echo x - src/rextern.c
sed 's/^X//' >src/rextern.c <<'*-*-END-of-src/rextern.c-*-*'
X/*
X * rextern - external definitions for readnews
X */
X
X#ifndef lint
Xstatic char *SccsId = "@(#)rextern.c 2.12 8/28/84";
X#endif !lint
X
X#include "rparams.h"
X
Xint uid, gid; /* real user/group I.D. */
Xint duid, dgid; /* effective user/group I.D. */
Xint sigtrap; /* set if signal trapped */
Xint savmask; /* old umask */
Xint mode; /* mode of news program */
Xstruct hbuf header; /* general-use header structure */
Xchar bfr[LBUFLEN]; /* general-use scratch area */
X
X#ifndef ROOTID
Xint ROOTID; /* special users id # */
X#endif
X
Xchar *outfile = "/tmp/M1XXXXXX"; /* output file for -M and -c */
Xchar *infile = "/tmp/M2XXXXXX"; /* -T output from Mail */
Xint ngrp, line = -1;
X
Xchar filename[BUFLEN], coptbuf[BUFLEN], datebuf[BUFLEN];
Xchar titlebuf[BUFLEN];
Xchar afline[BUFLEN];
XFILE *rcfp, *actfp;
Xtime_t atime;
Xchar newsrc[BUFLEN], groupdir[BUFLEN], *rcline[LINES], rcbuf[LBUFLEN];
Xchar bitmap[BITMAPSIZE/8], *argvrc[LINES];
Xlong bit, obit, last;
Xint readmode = NEXT;
Xint actdirect = FORWARD; /* read direction in ACTIVE file */
Xint rcreadok = FALSE; /* NEWSRC has been read OK */
Xint zapng = FALSE; /* ! out this newsgroup on next updaterc */
Xlong ngsize; /* max article # in this newsgroup */
Xlong minartno; /* min article # in this newsgroup */
X
X#ifndef SHELL
Xchar *SHELL;
X#endif
X
X#ifndef MAILER
Xchar *MAILER;
X#endif
X
Xchar PAGER[BUFLEN];
*-*-END-of-src/rextern.c-*-*
exit
More information about the Comp.sources.unix
mailing list