smk@linus.UUCP (Steven M. Kramer) (06/06/83)
I have modified this fix to readr.c to work with the -ldir stuff. You have to compile readnews with the -ldir flag in the Makefile and have to enable the -DMITRE stuff. Also in readr.c are all the current fixes to now, so I'll post the whole thing. If you don't enable -DMITRE, you get the original source. Remember, the -ldir lib that has been posted a few times must be used or opendir and readdir will be undefined. readr.c: -------------------------- /* * readr - /bin/mail and msgs interface and associated functions. */ static char *SccsId = "@(#)readr.c 2.26 5/3/83"; #include "rparams.h" #ifdef MITRE #include <ndir.h> #endif static char lbuf[BUFLEN*2]; #define saveart oobit = bit;strcpy(ofilename1, filename);strcpy(ogroupdir, groupdir);hbufcp(&hbuf1, &h);ongsize = pngsize #define NLINES(h, fp) (h.numlines[0] ? h.intnumlines : (h.intnumlines=linecnt(fp),sprintf(h.numlines, "%d", h.intnumlines), h.intnumlines)) #ifdef MITRE /* Some systems don't have a /usr/tmp because it is a nuisance to have two publically writable directories to clear out periodically and /tmp is a file system of adequate size. */ char *tft = "/tmp/folXXXXXX"; #else char *tft = "/usr/tmp/folXXXXXX"; #endif static int hascaught = 0; static catchintr() { hascaught = 1; printf("\n"); fflush(stdout); } /* * These were made static for u370 with its buggy cc. * I judged it better to have one copy with no ifdefs than * to conditionally compile them as automatic variables * in readr (which they originally were). Performance * considerations might warrent moving some of the simple * things into register variables, but I don't know what * breaks the u370 cc. */ static char goodone[BUFLEN]; /* last decent article */ static char ogroupdir[BUFLEN]; /* last groupdir */ static char address[PATHLEN]; /* for reply copy */ static char edcmdbuf[128]; static char folbuf[160]; static int rfq = 0; /* for last article */ static long ongsize; /* Previous ngsize */ static long pngsize; /* Printing ngsize */ static char *bptr; /* temp pointer. */ static struct srec srec; /* srec for sys file entries */ static char *tfilename; /* temporary file name */ static char ofilename1[BUFLEN]; /* previous file name */ static struct hbuf hbuf1, hbuf2, *hptr; /* for minusing */ static char *ptr1, *ptr2, *ptr3; /* for reply manipulation */ static int news = 0; static int abs = FALSE; /* TRUE if we asked absolutely */ static char *ed, tf[100]; static struct hbuf h; /* ditto. */ static int i; static int oobit; /* last bit, really */ static char *oldsig; static int dgest = 0; static FILE *ofp; /* Current output file to terminal*/ static FILE *fp; /* current article to be printed*/ static int holdup; /* 1 iff should stop before hdr */ static int ignorenews; /* 1 iff readnews -p > /dev/null*/ static long timelastsaved; /* time newsrc last written out */ int catchcont(); readr() { #ifdef DEBUG fprintf(stderr, "readr()\n"); #endif if (aflag) { if (*datebuf) { if ((atime = cgtdate(datebuf)) == -1) xerror("Cannot parse date string"); } else atime = 0L; } if (pflag && ignoring()) ignorenews = TRUE; if (uflag) time(&timelastsaved); ofp = stdout; if (cflag && coptbuf[0] != '\0') { umask(022); mktemp(outfile); /* get "unique" file name */ ofp = xfopen(outfile, "w"); umask(N_UMASK); cflag = FALSE; pflag = TRUE; } /* loop reading articles. */ fp = NULL; obit = -1; nextng(); for ( ;; ) { if (getnextart(FALSE)) break; #ifdef DEBUG printf("after getnextart, fp %x, pos %d, bit %d, group '%s', filename '%s'\n", fp, ftell(fp), bit, groupdir, filename); #endif strcpy(goodone, filename); if (pflag || lflag || eflag) { /* This code should be gotten rid of */ if (sigtrap) { qfflush(ofp); fprintf(ofp, "\n"); cdump(ofp); _exit(0); /* kludge! drop when qfflush works */ return; } clear(bit); nextbit(); if (fp) { fclose(fp); fp = NULL; } continue; } for ( ;; ) { char *pp; #ifdef SIGCONT int (*ocont)(); #endif sigtrap = FALSE; if (!cflag) { if (rfq) fprintf(ofp, "Last article. [qfr] "); else fprintf(ofp, "(%d lines) More? [ynq] ", NLINES(h, fp)); } else fprintf(ofp, "? "); fflush(ofp); bptr = lbuf; #ifdef SIGCONT ocont = signal(SIGCONT, catchcont); #endif pp = fgets(bptr, BUFLEN, stdin); #ifdef SIGCONT signal(SIGCONT, ocont); #endif if (pp != NULL) break; if (!sigtrap) return; #ifdef SIGCONT if (sigtrap != SIGCONT) #endif fprintf(ofp, "\n"); } nstrip(bptr); while (*bptr == ' ' || *bptr == '\t') bptr++; i = command(); if (i) break; } if (!news) fprintf(stderr, "No news.\n"); cout(ofp); } #define EOL() if (*bptr != '\0') { fprintf(ofp, "? for commands.\n"); return FALSE; } /* * Process one command, which has already been typed in. */ command() { char *findhist(); switch (i = *bptr++) { /* No. Go on to next article. */ case 'n': EOL(); itsbeenseen(h.ident); readmode = NEXT; if (!cflag) { fclose(fp); fp = NULL; } fprintf(ofp, "\n"); clear(bit); saveart; nextbit(); break; /* Undigestify the article. */ case 'd': dgest = 1; /* fall through */ /* yes: print this article, go on. */ case 'y': EOL(); /* fall through. */ /* The user hit return. Default is 'y' unless rfq, then it's 'q'. */ case '\0': if (!bptr[-1] && rfq) return; readmode = NEXT; showtail(fp); clear(bit); saveart; nextbit(); break; /* * Unsubscribe to the newsgroup and go on to next group */ case 'u': fprintf(ofp, "To unsubscribe, use 'U'\n"); break; case 'U': fprintf(ofp, "Unsubscribing to newsgroup: %s\n", groupdir); obit = -1; if (fp != NULL) { fclose(fp); fp = NULL; } if (cflag) clear(bit); else putc('\n', ofp); rfq = 0; zapng = TRUE; saveart; if (nextng()) { if (actdirect == BACKWARD) fprintf(ofp, "Can't back up.\n"); else return TRUE; } break; /* Print the current version of news */ case 'v': fprintf(ofp, "News version: %s\n", news_version); break; /* reprint the article */ case 'p': EOL(); if (!cflag) goto minus; readmode = NEXT; if (!cflag) { fclose(fp); fp = NULL; bit = last; putc('\n', ofp); } obit = -1; break; /* decrypt joke */ case 'D': caesar_command(); readmode = NEXT; clear(bit); saveart; nextbit(); break; /* write out the article someplace */ case 's': case 'w': { char *grn = groupdir; tfilename = filename; if (*bptr == '-') { bptr++; grn = ogroupdir; if (*ofilename1) tfilename = ofilename1; } if (*bptr != '\0' && *bptr != ' ') { fprintf(ofp, "Bad file name.\n"); break; } while (*bptr == ' ') bptr++; if (*bptr != '|' && *bptr != '/') { char hetyped[BUFLEN]; char *boxptr; strcpy(hetyped, bptr); if (boxptr = getenv("NEWSBOX")) if (index(boxptr, '%')) sprintf(bptr, boxptr, grn); else strcpy(bptr, boxptr); else if (hetyped[0] == '~' && hetyped[1] == '/') { strcpy(hetyped, bptr+2); strcpy(bptr, userhome); } else strcpy(bptr, "."); strcat(bptr, "/"); if (hetyped[0] != '\0') strcat(bptr, hetyped); else strcat(bptr, "Articles"); } fwait(fsubr(save, tfilename, bptr)); } break; /* back up */ case '-': minus: rfq = 0; abs = TRUE; if (!*ofilename1) { fprintf(ofp, "Can't back up.\n"); break; } if (cflag) clear(bit); else { fclose(fp); fp = NULL; putc('\n', ofp); } hbufcp(&hbuf2, &h); hbufcp(&h, &hbuf1); hbufcp(&hbuf1, &hbuf2); strcpy(bfr, filename); strcpy(filename, ofilename1); strcpy(ofilename1, bfr); obit = bit; if (strcmp(groupdir, ogroupdir)) { strcpy(bfr, groupdir); selectng(ogroupdir); strcpy(groupdir, ogroupdir); strcpy(ogroupdir, bfr); ngrp = 1; back(); } bit = oobit; oobit = obit; obit = -1; getnextart(TRUE); return FALSE; /* skip forwards */ case '+': caseplus: if (*bptr == '\0') strcat(bptr, "1"); rfq = 0; if (cflag) clear(bit); saveart; last = bit; for (i = 0; i < atoi(bptr); i++) { nextbit(); if ((bit > pngsize) || (rflag && bit < 1)) break; } if (!cflag) { putc('\n', ofp); fclose(fp); fp = NULL; } obit = -1; break; /* exit - time updated to that of most recently read article */ case 'q': EOL(); return TRUE; /* exit - no time update. */ case 'x': EOL(); xxit(0); /* cancel the article. */ case 'c': cancel_command(); break; /* escape to shell */ case '!': fwait(fsubr(ushell, bptr, (char *)NULL)); fprintf(ofp, "\n"); hdr(); break; /* mail reply */ case 'r': reply_command(); break; /* send to some system */ case 'X': xmit_command(); break; /* next newsgroup */ case 'P': *bptr = '-'; case 'N': if (fp != NULL) { fclose(fp); fp = NULL; } if (next_ng_command()) return TRUE; break; /* specific no. */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': sscanf(--bptr, "%d", &i); if (i == 0) { fprintf(ofp, "Bad article no.\n"); break; } if (i > pngsize) { fprintf(ofp, "Not that many articles.\n"); break; } readmode = SPEC; abs = TRUE; bit = i; obit = -1; if (!cflag) { putc('\n', ofp); fclose(fp); fp = NULL; } rfq = 0; break; /* specific message ID. */ case '<': ptr1 = findhist(--bptr); if (ptr1 == NULL) { fprintf(ofp, "No such article: %s.\n", bptr); break; } ptr2 = index(ptr1, '\t'); ptr3 = index(++ptr2, '\t'); ptr2 = index(++ptr3, ' '); if (ptr2) *ptr2 = '\0'; ptr2 = index(ptr3, '/'); *ptr2++ = '\0'; abs = TRUE; if (cflag) clear(bit); else { fclose(fp); fp = NULL; putc('\n', ofp); } hbufcp(&hbuf1, &h); saveart; strcpy(ogroupdir, ptr3); if (strcmp(groupdir, ogroupdir)) { strcpy(bfr, groupdir); selectng(ogroupdir); strcpy(groupdir, ogroupdir); strcpy(ogroupdir, bfr); back(); } sscanf(ptr2, "%d", &bit); oobit = obit; obit = -1; getnextart(TRUE); rfq = 0; break; /* follow-up article */ case 'f': followup_command(); break; /* erase - pretend we haven't seen this article. */ case 'e': if (rfq || *bptr == '-') { if (strcmp(groupdir, ogroupdir)) { i = bit; strcpy(bfr, groupdir); selectng(ogroupdir); set(oobit); printf("Holding article %d newsgroup %s\n", oobit, ogroupdir), strcpy(groupdir, ogroupdir); selectng(bfr); bit = i; } else { printf("Holding article %d\n", oobit), set(oobit); } } else { printf("Holding article %d\n", bit), set(bit); goto caseplus; /* skip this article for now */ } break; case 'H': case 'h': if (!hflag) dash(8, ofp); if (*bptr == '-') { if (oobit > 0) fprintf(ofp, "Article %d:\n", oobit); hprint(&hbuf1, ofp, 1 + (i=='H')); } else { fprintf(ofp, "Article %d of %ld: %s\n", rfq ? oobit : bit, pngsize, h.ident); hprint(&h, ofp, 1 + (i=='H')); } if (!hflag) dash(8, ofp); break; case '#': fprintf(ofp, "Article %d of %ld: newsgroup %s\n", rfq ? oobit : bit, pngsize, rfq ? ogroupdir : groupdir); break; /* error */ case '?': help(ofp); break; default: fprintf(ofp, "? for commands.\n"); break; } return FALSE; } cancel_command() { tfilename = filename; hptr = &h; if (*bptr == '-') { if (*ofilename1) { tfilename = ofilename1; hptr = &hbuf1; } bptr++; } EOL(); readmode = SPEC; strcpy(rcbuf, hptr->path); ptr1 = index(rcbuf, ' '); if (ptr1) *ptr1 = 0; if (uid == ROOTID) i = 0; /* root gets to cancel */ else i = strcmp(username, rcbuf); if (i != 0) { fprintf(ofp, "Can't cancel what you didn't write.\n"); return; } if (!cancel(ofp, hptr, i) && hptr == &h) { clear(bit); saveart; nextbit(); obit = -1; fp = NULL; if (!cflag) putc('\n', ofp); } if (fp != NULL) fclose(fp); fp = NULL; } reply_command() { register char *pathptr, *ptr; int edit = 1; char *ed; FILE *tfp; char curberk[BUFLEN]; char *replyname(); char subj[100]; char folbuf[100]; extern char MAILPARSER[]; hptr = &h; while (*bptr && index("d-", *bptr)) { switch (*bptr) { /* Followup the previous article. */ case '-': hptr = &hbuf1; break; /* Don't edit the headers */ case 'd': edit = 0; break; } bptr++; } EOL(); if (edit && access(MAILPARSER, 1)) { #ifdef IHCC fprintf(stderr, "Can't edit headers, 'recmail' missing.\n"); #else fprintf(stderr, "Can't edit headers without %s\n", MAILPARSER); #endif edit = 0; } *rcbuf = '\0'; *curberk = '\0'; pathptr = replyname(hptr);; ptr = pathptr - 1; i = 0; for (ptr1 = address, ptr2 = pathptr; *ptr2; ptr1++, ptr2++) { if (index("\"\\$", *ptr2)) *ptr1++ = '\\'; *ptr1 = *ptr2; } *ptr1 = '\0'; folbuf[0] = 0; /* References */ if (hptr->followid[0]) { strcpy(folbuf, hptr->followid); #ifdef MITRE /* The usenet standards document (doc/standard in the 2.10 distribution) specifies that followups should use blanks to separate the references in the header. */ strcat(folbuf, " "); #else strcat(folbuf, ", "); #endif } strcat(folbuf, hptr->ident); strcpy(subj, hptr->title); /* Subject */ while (isspace(*bptr)) bptr++; if (*bptr != '\0') strcpy(subj, bptr); if (!prefix(subj, "Re:") && !prefix(subj, "re:")) { strcpy(bfr, subj); sprintf(subj, "Re: %s", bfr); } if (!edit) { fprintf(ofp, "To: %s\n", pathptr); ed = index(MAILER, '%'); if (ed && ed[1] == 's') fprintf(ofp, "Subject: %s\n", subj); fflush(ofp); } /* Put the user in the editor to create the body of the followup. */ if (edit) { strcpy(tf, tft); mktemp(tf); ed = getenv("EDITOR"); if (ed == NULL) ed = DFTEDITOR; #ifdef MITRE /* The original code failed to test the value returned by fopen when using the template tft. This is a bad practice, since fopen for a file could fail due to kernel table exhaustion or an existing file of the same name with no permission, etc. */ if ((tfp = fopen(tf, "w")) == NULL) perror(tf); else { fprintf(tfp, "To: %s\n", pathptr); fprintf(tfp, "Subject: %s\n", subj); fprintf(tfp, "References: %s\n\n", folbuf); fclose(tfp); } #else tfp = fopen(tf, "w"); fprintf(tfp, "To: %s\n", pathptr); fprintf(tfp, "Subject: %s\n", subj); fprintf(tfp, "References: %s\n\n", folbuf); fclose(tfp); #endif sprintf(edcmdbuf, "%s %s", ed, tf); system(edcmdbuf); strcpy(rcbuf, MAILPARSER); strcat(rcbuf, " -t"); strcat(rcbuf, " < "); strcat(rcbuf, tf); if (access(tf, 4)) { fprintf(stderr, "Reply not sent: no input file.\n"); return; } printf("Sending reply.\n"); fflush(stdout); if (fork() == 0) { system(rcbuf); unlink(tf); _exit(0); } } else { sprintf(rcbuf, MAILER, hptr->title); sprintf(bfr, "%s %s", rcbuf, address); system(bfr); } hdr(); } xmit_command() { tfilename = filename; if (*bptr == '-') { if (*ofilename1) tfilename = ofilename1; bptr++; } if (*bptr != '\0' && *bptr != ' ') { fprintf(ofp, "Bad system name.\n"); return; } while (*bptr == ' ') bptr++; if (*bptr == '\0') { fprintf(ofp, "Missing system name.\n"); return; } if (s_find(&srec, bptr) == NULL) { fprintf(ofp, "%s not in SYSFILE\n", bptr); return; } transmit(&srec, tfilename); } next_ng_command() { if (!*bptr || *bptr == '-') { obit = -1; if (cflag) clear(bit); else putc('\n', ofp); if (*bptr) actdirect = BACKWARD; rfq = 0; saveart; if (nextng()) { if (actdirect == BACKWARD) fprintf(ofp, "Can't back up.\n"); else return TRUE; } return FALSE; } while (isspace(*bptr)) bptr++; if (!validng(bptr)) { fprintf(ofp, "No such group.\n"); return FALSE; } obit = -1; if (cflag) clear(bit); else putc('\n', ofp); readmode = SPEC; rfq = 0; saveart; back(); selectng(bptr); return FALSE; } followup_command() { int edit = 1; char subj[100]; char folbuf[100]; char *ng; FILE *tfp; hptr = &h; while (*bptr && index("d-", *bptr)) { switch (*bptr) { /* Followup the previous article. */ case '-': hptr = &hbuf1; break; /* Don't edit the headers */ case 'd': edit = 0; break; } bptr++; } /* Figure out the subject, newsgroups, and references for the followup. */ ng = hptr->nbuf; /* Newsgroups */ if (hptr->followto[0]) ng = hptr->followto; launder(ng); folbuf[0] = 0; /* References */ if (hptr->followid[0]) { strcpy(folbuf, hptr->followid); #ifdef MITRE /* The usenet standards document (doc/standard in the 2.10 distribution) specifies that followups should use blanks to separate the references in the header. */ strcat(folbuf, " "); #else strcat(folbuf, ", "); #endif } strcat(folbuf, hptr->ident); strcpy(subj, hptr->title); /* Subject */ while (isspace(*bptr)) bptr++; if (*bptr != '\0') strcpy(subj, bptr); if (!prefix(subj, "Re:") && !prefix(subj, "re:")) { strcpy(bfr, subj); sprintf(subj, "Re: %s", bfr); } /* Determine the command line for the shell. */ if (edit) { sprintf(bfr, "%s -h -D", FOLLOWUP); } else { sprintf(bfr, "%s -D -F '%s' -n %s -t \'", FOLLOWUP, folbuf, ng); strqcat(bfr, subj); strcat(bfr, "\'"); } /* backslash special characters */ for (ptr1 = rcbuf, ptr2 = bfr; *ptr2; ptr1++, ptr2++) { if (index("\\", *ptr2)) *ptr1++ = '\\'; *ptr1 = *ptr2; } *ptr1 = '\0'; /* Let the user know what's going on. */ fprintf(ofp, "Posting followup article to network. Please use\n"); fprintf(ofp, "reply ('r') instead unless your article is of general\n"); fprintf(ofp, "interest. (To abort press BREAK.)\n"); fprintf(ofp, "Subject: %s\n", subj); fprintf(ofp, "Newsgroups: %s\n", ng); fprintf(ofp, "Hit <return> to continue, BREAK to abort: "); fflush(ofp); /* Give the user a chance to hit BREAK and back out. */ hascaught = 0; oldsig = (char *) signal(SIGINT, catchintr); gets(edcmdbuf); signal(SIGINT, oldsig); if (hascaught) return; /* Play obnoxious warnings, if necessary. */ if (recording(hptr->nbuf, 0)) return; /* Put the user in the editor to create the body of the followup. */ ed = getenv("EDITOR"); if (ed == NULL || *ed == '\0') ed = DFTEDITOR; if (ed) { strcpy(tf, tft); mktemp(tf); #ifdef MITRE /* The original code failed to test the value returned by fopen when using the template tft. This is a bad practice, since fopen for a file could fail due to kernel table exhaustion or an existing file of the same name with no permission, etc. */ if ((tfp = fopen(tf, "w")) == NULL) perror(tf); else { if (edit) { fprintf(tfp, "Newsgroups: %s\n", ng); fprintf(tfp, "Subject: %s\n", subj); fprintf(tfp, "References: %s\n", folbuf); if (hptr->keywords[0]) fprintf(tfp, "Keywords: %s\n", hptr->keywords); fprintf(tfp, "\n"); } fclose(tfp); } #else tfp = fopen(tf, "w"); if (edit) { fprintf(tfp, "Newsgroups: %s\n", ng); fprintf(tfp, "Subject: %s\n", subj); fprintf(tfp, "References: %s\n", folbuf); if (hptr->keywords[0]) fprintf(tfp, "Keywords: %s\n", hptr->keywords); fprintf(tfp, "\n"); } fclose(tfp); #endif sprintf(edcmdbuf, "%s %s", ed, tf); system(edcmdbuf); strcat(rcbuf, "< "); strcat(rcbuf, tf); if (access(tf, 4)) { fprintf(stderr, "Article not posted: no input file.\n"); return; } printf("Posting article.\n"); fflush(stdout); if (fork() == 0) { system(rcbuf); unlink(tf); _exit(0); } } else { printf("%s\n", rcbuf); system(rcbuf); } hdr(); } caesar_command() { char temp[100]; char *pp = bptr; FILE *pfp, *popen(); fprintf(stderr, "Caesar decoding:\n"); strcpy(temp, CAESAR); if (*bptr) { strcat(temp, " "); strcat(temp, bptr); } if (NLINES(h, fp) > LNCNT && *PAGER) { strcat(temp, " | "); strcat(temp, PAGER); } pfp = popen(temp, "w"); tprint(fp, pfp, FALSE); itsbeenseen(h.ident); fclose(fp); fp = NULL; pclose(pfp); } /* * Show the user the tail, if any, of the message on file * descriptor fd, and close fd. The digester is considered, * and the pager is used if appropriate. */ showtail(fd) FILE *fd; { if (fd == NULL) return; if (dgest) { digest(fd, ofp, &h); } else if (!lflag && !pflag && !eflag) { #ifdef PAGE /* Filter the tail of long messages through PAGER. */ if (NLINES(h, fd) > LNCNT && *PAGER) { if (!index(PAGER, FMETA)) { FILE *pfp, *popen(); int cnt; pfp = popen(PAGER, "w"); if (pfp == NULL) pfp = ofp; /* * What follows is an attempt to prevent the * next message from scrolling part of this * message off the top of the screen before * the poor luser can read it. */ tprint(fd, pfp, FALSE); itsbeenseen(h.ident); pclose(pfp); } else pout(ofp); holdup = TRUE; #ifndef MITRE fprintf(ofp, ":"); fflush(ofp); #endif } else #endif tprint(fd, ofp, FALSE), itsbeenseen(h.ident); } fclose(fd); } /* * Find the next article we want to consider, if we're done with * the last one, and show the header. */ getnextart(minus) int minus; { #ifdef MITRE int noaccess = 0; DIR *dfp; struct direct *entry; long nextnum, tnum; long atol(); #endif if (minus) goto nextart2; /* Kludge for "-" command. */ if (bit == obit) /* Return if still on same article as last time */ return 0; sigtrap = FALSE; nextart: dgest = 0; if (bit < 1 && !rflag) bit = 1; /* If done with this newsgroup, find the next one. */ while (((long) bit > ngsize) || (rflag && bit < 1)) { int i; if (i=nextng()) { if (actdirect == BACKWARD) { fprintf(ofp, "Can't back up.\n"); actdirect = FORWARD; continue; } else if (rfq++ || pflag || cflag) return 1; } if (rflag) bit = ngsize + 1L; else bit = -1; if (uflag) { long now; time(&now); if (now - timelastsaved > 5*60 /* 5 minutes */) { printf("[Saving .newsrc]\n"); fflush(stdout); writeoutrc(); timelastsaved = now; } } } nextart2: #ifdef DEBUG fprintf(stderr, "article: %s/%d\n", groupdir, bit); #endif if (rcreadok) rcreadok = 2; /* have seen >= 1 article */ sprintf(filename, "%s/%d", dirname(groupdir), bit); if (rfq && goodone[0]) strcpy(filename, goodone); if (sigtrap) { if (sigtrap == SIGHUP) return 1; if (!rcreadok) xxit(0); fprintf(ofp, "Abort (n)? "); fflush(ofp); gets(bfr); if (*bfr == 'y' || *bfr == 'Y') xxit(0); sigtrap = FALSE; } #ifdef DEBUG fprintf(stderr, "filename = '%s'\n", filename); #endif /* Decide if we want to show this article. */ #ifdef MITRE /* This modification is to speed up readnews when you first start reading a group for the first time. On sites that expire articles, you eventually get lots of articles that don't exist. You start reading news for the first time, and you get to a popular group with current articles in the 1000's, and readnews says "Oh, an new group! Let's see, is article 1 there? nope. Is article 2 there? nope. Is article 3 there? nope..." and so on and so on, so it does over 1000 calls to access(2), which is really a waste. This modification solves this. When readnews finds 5 consecutive articles that don't exist, it hauls off and opens up the directory, and reads it in and finds the next article to show. */ if (access(filename, 4)) { /* since there can be holes in legal article numbers, */ /* we wait till we hit 5 consecutive bad articles */ /* before we haul off and scan the directory */ if (++noaccess < 5) goto badart; dfp = opendir(dirname(groupdir)); if (dfp == (DIR *) NULL) { #ifdef DEBUG fprintf(stderr, "can't open groupdir (%s)\n", dirname(groupdir)); #endif noaccess = 0; goto badart; } nextnum = rflag ? 0 : ngsize; while ((entry = readdir (dfp)) != NULL) { tnum = atol(entry->d_name); #ifdef DEBUG fprintf(stderr, "art %s (%ld) next %ld\n", entry->d_name, tnum, nextnum); #endif DEBUG if (tnum <= 0) continue; if (rflag ? (tnum > nextnum && tnum < bit) : (tnum < nextnum && tnum > bit)) nextnum = tnum; } closedir(dfp); if (rflag ? (nextnum >= bit) : (nextnum <= bit)) goto badart; do { clear(bit); nextbit(); } while (rflag ? (nextnum < bit) : (nextnum > bit)); obit = -1; abs = FALSE; goto nextart; #ifdef DEBUG fprintf(stderr, "bit %d nextnum %ld\n", bit, nextnum); #endif DEBUG } else noaccess = 0; #endif if (ignorenews #ifndef MITRE || access(filename, 4) #endif || ((fp = fopen(filename, "r")) == NULL) || (hread(&h, fp, TRUE) == NULL) || (!rfq && !select(&h, abs))) { #ifdef MITRE badart: #endif #ifdef DEBUG fprintf(stderr, "Bad article '%s'\n", filename); #endif if (fp != NULL) { fclose(fp); fp = NULL; } clear(bit); obit = -1; nextbit(); abs = FALSE; goto nextart; } abs = FALSE; actdirect = FORWARD; news = TRUE; hdr(); if ((cflag && !lflag && !eflag) || pflag) tprint(fp, ofp, FALSE); #ifdef MITRE /* Readnews with the -c, -l, and -e options will list each article posted to multiple news groups once for each group, rather than just once for the session. */ if (cflag || lflag || eflag || pflag) { #else if (cflag && lflag && eflag || pflag) { #endif itsbeenseen(h.ident); sigtrap = FALSE; fclose(fp); fp = NULL; } obit = bit; return 0; } /* * Print out whatever the appropriate header is */ hdr() { if (rfq) return; /* Wait for user to read previous article. */ if (holdup) { holdup = FALSE; #ifdef MITRE /* If the last article is piped through the pager, it prints a ':', but does not wait for any input. */ fprintf(ofp, ":"); fflush(ofp); #endif gets(bfr); if (bfr[0]) explaincolon(); } if (lflag || eflag) { hprint(&h, ofp, 0); return; } /* Print out a header */ if (ngrp) { pngsize = ngsize; ngrp--; nghprint(groupdir); } if (!hflag) #ifdef MITRE /* Trivial fix to allow header line to show the current newsgroup (which can be forgotten in long newsgroups). */ fprintf(ofp, "Article %d of %ld, %s; %s.\n", bit, pngsize, groupdir, briefdate(h.subdate)); #else fprintf(ofp, "Article %d of %ld, %s.\n", bit, pngsize, briefdate(h.subdate)); #endif hprint(&h, ofp, pflag ? 1 : 0); } explaincolon() { fprintf(ofp, "\n'%s' ignored.\n", bfr); fprintf(ofp, "The colon is to give you a chance to finish reading the\n"); fprintf(ofp, "previous article before the next header scrolls it off\n"); fprintf(ofp, "the top of the screen. You should hit `return' or `newline'\n"); fprintf(ofp, "when you are ready to go on to the next article.\n\n"); fflush(ofp); } nghprint(title) char *title; { char *tstr = "Newsgroup "; int l = strlen(title) + strlen(tstr); fprintf(ofp, "\n"); if (!hflag) { dash(l, ofp); fprintf(ofp, "%s%s\n", tstr, title); dash(l, ofp); } else { fprintf(ofp, "%s%s, ", tstr, title); if (bit == pngsize) #ifdef MITRE /* The variable pngsize is long, yet this prints it via %d instead of %ld. */ fprintf(ofp, "%ld\n", pngsize); #else fprintf(ofp, "%d\n", pngsize); #endif else #ifdef MITRE /* The variable pngsize is long, yet this prints it via %d instead of %ld. */ fprintf(ofp, "%d-%ld\n", bit, pngsize); #else fprintf(ofp, "%d-%d\n", bit, pngsize); #endif } fprintf(ofp, "\n"); } /* * Routine to catch a continue signal. */ catchcont() { #ifdef SIGCONT signal(SIGCONT, catchcont); sigtrap = SIGCONT; #endif hdr(); }