rick@seismo.UUCP (Rick Adams) (09/05/84)
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 * diff
rick@seismo.UUCP (Rick Adams) (09/08/84)
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@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