|
|
1.1 root 1: /*
2: * This software is Copyright (c) 1986 by Rick Adams.
3: *
4: * Permission is hereby granted to copy, reproduce, redistribute or
5: * otherwise use this software as long as: there is no monetary
6: * profit gained specifically from the use or reproduction or this
7: * software, it is not sold, rented, traded or otherwise marketed, and
8: * this copyright notice is included prominently in any copy
9: * made.
10: *
11: * The author make no claims as to the fitness or correctness of
12: * this software for any use whatsoever, and it is provided as is.
13: * Any use of this software is at the user's own risk.
14: *
15: * readr - /bin/mail and msgs interface and associated functions.
16: */
17:
18: #ifdef SCCSID
19: static char *SccsId = "@(#)readr.c 2.55 1/17/86";
20: #endif /* SCCSID */
21:
22: #include "rparams.h"
23: #if defined(BSD4_2) || defined(BSD4_1C)
24: #include <sys/dir.h>
25: #else
26: #include "ndir.h"
27: #endif /* !BSD4_2 && !BSD4_1C */
28: #include <setjmp.h>
29: #include <errno.h>
30:
31: extern int errno;
32:
33: char *Progname = "readnews"; /* used by xerror to identify failing program */
34:
35: static char lbuf[BUFLEN*2];
36: long atol();
37:
38: #define saveart oobit = bit;strcpy(ofilename1, filename);strcpy(ogroupdir, groupdir);hptr = h;h = hold;hold = hptr;ongsize = pngsize
39: #define NLINES(h, fp) (h->numlines[0] ? h->intnumlines : (h->intnumlines=linecnt(fp),sprintf(h->numlines, "%d", h->intnumlines), h->intnumlines))
40:
41: char *tft = "/tmp/folXXXXXX";
42:
43: /*
44: * These were made static for u370 with its buggy cc.
45: * I judged it better to have one copy with no ifdefs than
46: * to conditionally compile them as automatic variables
47: * in readr (which they originally were). Performance
48: * considerations might warrant moving some of the simple
49: * things into register variables, but I don't know what
50: * breaks the u370 cc.
51: */
52: static char goodone[BUFLEN]; /* last decent article */
53: static char ogroupdir[BUFLEN]; /* last groupdir */
54: static char address[PATHLEN]; /* for reply copy */
55: static char edcmdbuf[128];
56: static int rfq = 0; /* for last article */
57: static long ongsize; /* Previous ngsize */
58: static long pngsize; /* Printing ngsize */
59: static char *bptr; /* temp pointer. */
60: static struct srec srec; /* srec for sys file entries */
61: static char *tfilename; /* temporary file name */
62: static char ofilename1[BUFLEN]; /* previous file name */
63: static struct hbuf hbuf1, hbuf2, /* for minusing */
64: *h = &hbuf1, /* current header */
65: *hold = &hbuf2, /* previous header */
66: *hptr; /* temporary */
67: static char *ptr1, *ptr2, *ptr3; /* for reply manipulation */
68: static int abs = FALSE; /* TRUE if we asked absolutely */
69: static char tf[100];
70: static long oobit; /* last bit, really */
71: static int dgest = 0;
72: static FILE *ofp; /* Current output file to terminal*/
73: static FILE *fp; /* current article to be printed*/
74: static int holdup; /* 1 iff should stop before hdr */
75: static int ignorenews; /* 1 iff readnews -p > /dev/null*/
76: static time_t timelastsaved; /* time newsrc last written out */
77: static jmp_buf sigjmpbuf; /* for signal processing */
78: static int canlongjmp; /* TRUE if setjmp on sigjmp valid */
79:
80: int catchcont();
81: readr()
82: {
83: register char *m = getenv("MORE");
84: register char *m2, cc;
85:
86: /*
87: * Turn of more's 'l' option, so \f kludge will work.
88: * This is really revolting!
89: */
90: if (m2 = m) {
91: while (cc = *m++)
92: if (cc != 'l')
93: *m2++ = cc;
94: *m2 = '\0';
95: }
96:
97: #ifdef DEBUG
98: fprintf(stderr, "readr()\n");
99: #endif
100: if (aflag) {
101: if (*datebuf) {
102: if ((atime = cgtdate(datebuf)) == -1)
103: xerror("Cannot parse date string");
104: } else
105: atime = 0;
106: }
107:
108: if (pflag && ignoring())
109: ignorenews = TRUE;
110:
111: if (xflag)
112: uflag = 0;
113: if (uflag)
114: (void) time(&timelastsaved);
115:
116: ofp = stdout;
117: if (cflag && coptbuf[0] != '\0') {
118: (void) umask(022);
119: (void) mktemp(outfile); /* get "unique" file name */
120: (void) close(creat(outfile,0666));
121: ofp = xfopen(outfile, "w");
122: (void) umask(N_UMASK);
123: cflag = FALSE;
124: pflag = TRUE;
125: }
126:
127: /* loop reading articles. */
128: fp = NULL;
129: obit = -1;
130: nextng();
131: for ( ;; ) {
132: if (getnextart(FALSE))
133: break;
134: #ifdef DEBUG
135: fprintf(stderr,"after getnextart, fp %x, pos %ld, bit %ld, group '%s', filename '%s'\n",
136: fp, ftell(fp), bit, groupdir, filename);
137: #endif
138: (void) strcpy(goodone, filename);
139: if (pflag || lflag || eflag) {
140: /* This code should be gotten rid of */
141: if (SigTrap) {
142: qfflush(ofp);
143: fprintf(ofp, "\n");
144: cdump(ofp);
145: xxit(0); /* kludge! drop when qfflush works */
146: return;
147: }
148: clear(bit);
149: nextbit();
150: FCLOSE(fp);
151: continue;
152: }
153: for ( ;; ) {
154: char *pp;
155: int nlines;
156: int (*ointr)();
157: #ifdef SIGCONT
158: int (*ocont)();
159: #endif
160: (void) setjmp(sigjmpbuf);
161: canlongjmp = TRUE;
162:
163: SigTrap = FALSE;
164: if (!cflag) {
165: if (rfq)
166: (void) sprintf(bfr, "Last article. [qfr] ");
167: else {
168: nlines = NLINES(h, fp);
169: if (nlines <= 0) {
170: (void) sprintf(bfr, "(0 lines) Next? [nqfr] ");
171: FCLOSE(fp);
172: } else {
173: (void) sprintf(bfr, "(%d lines) More? [ynq] ", nlines);
174: }
175: }
176: } else
177: (void) sprintf(bfr, "? ");
178: fprintf(ofp, "%s", bfr);
179: (void) fflush(ofp);
180: bptr = lbuf;
181: ointr = signal(SIGINT, catchcont);
182: #ifdef SIGCONT
183: ocont = signal(SIGCONT, catchcont);
184: #endif
185: pp = fgets(bptr, BUFLEN, stdin);
186: canlongjmp = FALSE;
187: (void) signal(SIGINT, ointr);
188: #ifdef SIGCONT
189: (void) signal(SIGCONT, ocont);
190: #endif
191: if (pp != NULL)
192: break;
193: if (!SigTrap)
194: return;
195: #ifdef SIGCONT
196: if (SigTrap != SIGCONT)
197: #endif
198: fprintf(ofp, "\n");
199: }
200: (void) nstrip(bptr);
201: while (*bptr == ' ' || *bptr == '\t')
202: bptr++;
203: if (command())
204: break;
205: }
206:
207: if (!pflag && !news) {
208: if (!checkngs(header.nbuf, actfp))
209: fprintf(stderr, "No news.\n");
210: }
211: cout(ofp);
212: }
213:
214: #define EOL() if (*bptr != '\0') { fprintf(ofp, "? for commands.\n"); return FALSE; }
215: /*
216: * Process one command, which has already been typed in.
217: */
218: command()
219: {
220: char *findhist();
221: long i;
222:
223: switch (*bptr++) {
224:
225: /* No. Go on to next article. */
226: case 'n':
227: EOL();
228: readmode = NEXT;
229: if (!cflag)
230: FCLOSE(fp);
231: fprintf(ofp, "\n");
232: clear(bit);
233: saveart;
234: nextbit();
235: break;
236:
237: /* Undigestify the article. */
238: case 'd':
239: dgest = 1;
240: /* fall through */
241:
242: /* yes: print this article, go on. */
243: case 'y':
244: EOL();
245: /* fall through. */
246:
247: /* The user hit return. Default is 'y' unless rfq, then it's 'q'. */
248: case '\0':
249: if (!bptr[-1] && rfq)
250: return TRUE;
251: readmode = NEXT;
252: showtail(fp);
253: clear(bit);
254: saveart;
255: nextbit();
256: break;
257:
258: /*
259: * Unsubscribe to the newsgroup and go on to next group
260: */
261: case 'u':
262: fprintf(ofp, "To unsubscribe, use 'U'\n");
263: break;
264:
265: case 'U':
266: fprintf(ofp, "Unsubscribing to newsgroup: %s\n", groupdir);
267: obit = -1;
268: FCLOSE(fp);
269: if (cflag)
270: clear(bit);
271: else
272: putc('\n', ofp);
273: rfq = 0;
274: zapng = TRUE;
275: saveart;
276: if (nextng()) {
277: if (actdirect == BACKWARD)
278: fprintf(ofp, "Can't back up.\n");
279: else
280: return TRUE;
281: }
282: break;
283:
284: /* Print the current version of news */
285: case 'v':
286: fprintf(ofp, "News version: %s\n", news_version);
287: break;
288:
289: /* reprint the article */
290: case 'p':
291: EOL();
292: if (!cflag)
293: goto minus;
294: readmode = NEXT;
295: if (!cflag) {
296: FCLOSE(fp);
297: bit = last;
298: putc('\n', ofp);
299: }
300: obit = -1;
301: break;
302:
303: /* decrypt joke */
304: case 'D':
305: caesar_command();
306: readmode = NEXT;
307: clear(bit);
308: saveart;
309: nextbit();
310: break;
311:
312: /* write out the article someplace */
313: case 's':
314: case 'w':
315: {
316: char *grn = groupdir;
317: tfilename = filename;
318: if (*bptr == '-') {
319: bptr++;
320: grn = ogroupdir;
321: if (*ofilename1)
322: tfilename = ofilename1;
323: }
324: if (*bptr != '\0' && *bptr != ' ') {
325: fprintf(ofp, "Bad file name.\n");
326: break;
327: }
328: while (*bptr == ' ')
329: bptr++;
330: if (*bptr != '|' && *bptr != '/') {
331: char hetyped[BUFLEN];
332: char *boxptr;
333: struct stat stbf;
334: (void) strcpy(hetyped, bptr);
335: if (hetyped[0] == '~' && hetyped[1] == '/') {
336: strcpy(hetyped, bptr+2);
337: strcpy(bptr, userhome);
338: } else if (boxptr = getenv("NEWSBOX")) {
339: if (index(boxptr, '%')) {
340: sprintf(bptr, boxptr, grn);
341: if (stat(bptr, &stbf) < 0) {
342: if (mkdir(bptr, 0777) < 0) {
343: fprintf(ofp, "Cannot create directory %s", bptr);
344: break;
345: }
346: } else if ((stbf.st_mode & S_IFMT) != S_IFDIR) {
347: fprintf(ofp, "%s is not a directory", bptr);
348: break;
349: }
350: } else
351: strcpy(bptr, boxptr);
352: } else
353: (void) strcpy(bptr, ".");
354: (void) strcat(bptr, "/");
355: if (hetyped[0] != '\0')
356: (void) strcat(bptr, hetyped);
357: else
358: (void) strcat(bptr, "Articles");
359: }
360: fwait(fsubr(save, tfilename, bptr));
361: }
362: break;
363:
364: /* back up */
365: case '-':
366: minus:
367: rfq = 0;
368: abs = TRUE;
369: if (!*ofilename1) {
370: fprintf(ofp, "Can't back up.\n");
371: break;
372: }
373: if (cflag)
374: clear(bit);
375: else {
376: FCLOSE(fp);
377: putc('\n', ofp);
378: }
379: hptr = h;
380: h = hold;
381: hold = hptr;
382: (void) strcpy(bfr, filename);
383: (void) strcpy(filename, ofilename1);
384: (void) strcpy(ofilename1, bfr);
385: obit = bit;
386: if (strcmp(groupdir, ogroupdir)) {
387: (void) strcpy(bfr, groupdir);
388: selectng(ogroupdir, TRUE, FALSE);
389: (void) strcpy(groupdir, ogroupdir);
390: (void) strcpy(ogroupdir, bfr);
391: ngrp = 1;
392: back();
393: }
394: bit = oobit;
395: oobit = obit;
396: obit = -1;
397: (void) getnextart(TRUE);
398: return FALSE;
399:
400: /* skip forwards */
401: case '+':
402: caseplus:
403: if (*bptr == '\0')
404: (void) strcat(bptr, "1");
405: rfq = 0;
406: if (cflag)
407: clear(bit);
408: saveart;
409: last = bit;
410: for (i = 0; i < atol(bptr); i++) {
411: nextbit();
412: if ((bit > pngsize) || (rflag && bit < 1))
413: break;
414: }
415: if (!cflag) {
416: putc('\n', ofp);
417: FCLOSE(fp);
418: }
419: obit = -1;
420: break;
421:
422: /* exit - time updated to that of most recently read article */
423: case 'q':
424: EOL();
425: return TRUE;
426:
427: /* exit - no time update. */
428: case 'x':
429: EOL();
430: xxit(0);
431:
432: /* cancel the article. */
433: case 'c':
434: (void) cancel_command();
435: break;
436:
437: /* escape to shell */
438: case '!':
439: fwait(fsubr(ushell, bptr, (char *)NULL));
440: fprintf(ofp, "\n");
441: hdr();
442: break;
443:
444: /* mail reply */
445: case 'r':
446: (void) reply_command();
447: break;
448:
449: /* send to some system */
450: case 'X':
451: xmit_command();
452: break;
453: /* mark the rest of the articles in this group as read */
454: case 'K':
455: saveart;
456: while (bit <= pngsize && bit >= minartno) {
457: clear(bit);
458: nextbit();
459: }
460: FCLOSE(fp);
461: break;
462:
463: /* next newsgroup */
464: case 'P':
465: *bptr = '-';
466: case 'N':
467: FCLOSE(fp);
468: if (next_ng_command())
469: return TRUE;
470: break;
471:
472: case 'b': /* back up 1 article */
473: i = bit - 1;
474: goto tryartnum;
475: case '0': /* specific no. */
476: case '1':
477: case '2':
478: case '3':
479: case '4':
480: case '5':
481: case '6':
482: case '7':
483: case '8':
484: case '9':
485: (void) sscanf(--bptr, "%ld", &i);
486: if (i == 0) {
487: fprintf(ofp, "Bad article no.\n");
488: break;
489: }
490: if (i > pngsize) {
491: fprintf(ofp, "Not that many articles.\n");
492: break;
493: }
494: tryartnum:
495: readmode = SPEC;
496: abs = TRUE;
497: bit = i;
498: obit = -1;
499: if (!cflag) {
500: putc('\n', ofp);
501: FCLOSE(fp);
502: }
503: rfq = 0;
504: break;
505:
506: /* specific message ID. */
507: case '<':
508: ptr1 = findhist(--bptr);
509: if (ptr1 == NULL) {
510: fprintf(ofp, "No such article: %s.\n", bptr);
511: break;
512: }
513: ptr2 = index(ptr1, '\t');
514: ptr3 = index(++ptr2, '\t');
515: ptr2 = index(++ptr3, ' ');
516: if (ptr2)
517: *ptr2 = '\0';
518: ptr2 = index(ptr3, '/');
519: if (!ptr2) {
520: *ptr3 = '\0';
521: if (strcmp(++ptr3, "cancelled") == 0) {
522: fprintf(ofp, "Article %s has been cancelled.\n",
523: bptr);
524: break;
525: }
526: fprintf(ofp, "Article %s (dated %s) has expired.\n",
527: bptr, index(ptr1, '\t')+1);
528: break;
529: }
530: *ptr2++ = '\0';
531: abs = TRUE;
532: if (cflag)
533: clear(bit);
534: else {
535: FCLOSE(fp);
536: putc('\n', ofp);
537: }
538: saveart;
539: (void) strcpy(ogroupdir, ptr3);
540: if (strcmp(groupdir, ogroupdir)) {
541: (void) strcpy(bfr, groupdir);
542: selectng(ogroupdir, TRUE, PERHAPS);
543: (void) strcpy(groupdir, ogroupdir);
544: (void) strcpy(ogroupdir, bfr);
545: ngrp = 1;
546: back();
547: }
548: (void) sscanf(ptr2, "%ld", &bit);
549: oobit = obit;
550: obit = -1;
551: i = bit;
552: (void) getnextart(TRUE);
553: if (bit != i || strcmp(groupdir, ptr3) != 0) {
554: (void) fprintf(ofp, "Can't read %s/%ld.\n", ptr3, i);
555: goto minus;
556: }
557: rfq = 0;
558: break;
559:
560: /* follow-up article */
561: case 'f':
562: if (strcmp(h->followto, "poster") == 0) {
563: (void) reply_command();
564: break;
565: }
566:
567: if (*bptr == '-')
568: tfilename = ofilename1;
569: else
570: tfilename = filename;
571: (void) sprintf(bfr,"%s/%s %s", BIN, "postnews", tfilename);
572: (void) system(bfr);
573: break;
574:
575: /* erase - pretend we haven't seen this article. */
576: case 'e':
577: if (rfq || *bptr == '-') {
578: if (strcmp(groupdir, ogroupdir)) {
579: i = bit;
580: (void) strcpy(bfr, groupdir);
581: selectng(ogroupdir, FALSE, PERHAPS);
582: set(oobit);
583: fprintf(ofp,"Holding article %ld newsgroup %s\n", oobit, ogroupdir),
584: (void) strcpy(groupdir, ogroupdir);
585: selectng(bfr, FALSE, FALSE);
586: bit = i;
587: } else {
588: fprintf(ofp,"Holding article %ld\n", oobit);
589: set(oobit);
590: }
591: } else {
592: fprintf(ofp,"Holding article %ld\n", bit);
593: set(bit);
594: goto caseplus; /* skip this article for now */
595: }
596: break;
597:
598: case 'H':
599: case 'h':
600: if (!hflag)
601: dash(8, ofp);
602: if (*bptr == '-') {
603: if (oobit > 0)
604: fprintf(ofp, "Article %ld:\n", oobit);
605: hprint(hold, ofp, 1 + (bptr[-1]=='H'));
606: } else {
607: fprintf(ofp, "Article %ld of %ld: %s\n",
608: rfq ? oobit : bit, pngsize, h->ident);
609: hprint(h, ofp, 1 + (bptr[-1]=='H'));
610: }
611: if (!hflag)
612: dash(8, ofp);
613: break;
614:
615: case '#':
616: fprintf(ofp, "Article %ld of %ld: newsgroup %s\n",
617: rfq ? oobit : bit, pngsize, rfq ? ogroupdir : groupdir);
618: break;
619:
620: /* error */
621: case '?':
622: help(ofp);
623: break;
624: default:
625: fprintf(ofp, "? for commands.\n");
626: break;
627: }
628:
629: return FALSE;
630: }
631:
632: cancel_command()
633: {
634: int notauthor;
635: tfilename = filename;
636: hptr = h;
637: if (*bptr == '-') {
638: if (*ofilename1) {
639: tfilename = ofilename1;
640: hptr = hold;
641: }
642: bptr++;
643: }
644: EOL();
645: readmode = SPEC;
646: (void) strcpy(rcbuf, hptr->path);
647: ptr1 = index(rcbuf, ' ');
648: if (ptr1)
649: *ptr1 = 0;
650: notauthor = strcmp(username, rcbuf);
651: if (uid != ROOTID && uid && notauthor) {
652: fprintf(ofp, "Can't cancel what you didn't write.\n");
653: return FALSE;
654: }
655: if (!cancel(ofp, hptr, notauthor) && hptr == h) {
656: clear(bit);
657: saveart;
658: nextbit();
659: obit = -1;
660: if (!cflag)
661: putc('\n', ofp);
662: FCLOSE(fp);
663: }
664: return TRUE;
665: }
666:
667: reply_command()
668: {
669: register char *pathptr;
670: int edit = 1;
671: char *ed, *fbp;
672: int idlen;
673: FILE *tfp;
674: char *replyname();
675: char subj[BUFLEN];
676: char folbuf[BUFLEN];
677: struct stat statb;
678: long creatm;
679:
680: hptr = h;
681: while (*bptr && index("d-", *bptr)) {
682: switch (*bptr) {
683: /* Followup the previous article. */
684: case '-':
685: hptr = hold;
686: break;
687:
688: /* Don't edit the headers */
689: case 'd':
690: edit = 0;
691: break;
692: }
693: bptr++;
694: }
695: EOL();
696: ptr1 = index(MAILPARSER, ' ');
697: if (ptr1)
698: *ptr1 = '\0';
699: if (edit && access(MAILPARSER, 1)) {
700: #ifdef IHCC
701: fprintf(stderr, "Can't edit headers, 'recmail' missing.\n");
702: #else
703: fprintf(stderr, "Can't edit headers without %s\n", MAILPARSER);
704: #endif
705: edit = 0;
706: }
707: if (ptr1)
708: *ptr1 = ' ';
709:
710: *rcbuf = '\0';
711: pathptr = replyname(hptr);;
712: for (ptr1 = address, ptr2 = pathptr; *ptr2; ptr1++, ptr2++) {
713: if (index("\"\\$", *ptr2))
714: *ptr1++ = '\\';
715: *ptr1 = *ptr2;
716: }
717: *ptr1 = '\0';
718:
719: folbuf[0] = '\0'; /* References */
720: if (hptr->followid[0]) {
721: fbp = hptr->followid;
722: idlen = strlen(hptr->ident);
723:
724: /*
725: * If the references line is too long, truncate it.
726: * The "3" is for the comma, the space, and the '\0' at
727: * the end of the string.
728: */
729: while (fbp && strlen(fbp) + idlen > BUFLEN - 3)
730: fbp = index(fbp + 1, '<');
731: if (fbp != NULL) {
732: (void) strcpy(folbuf, fbp);
733: (void) strcat(folbuf, ", ");
734: }
735: }
736: (void) strcat(folbuf, hptr->ident);
737:
738: (void) strcpy(subj, hptr->title); /* Subject */
739: while (isspace(*bptr))
740: bptr++;
741: if (*bptr != '\0')
742: (void) strcpy(subj, bptr);
743: if (!prefix(subj, "Re:")){
744: (void) strcpy(bfr, subj);
745: (void) sprintf(subj, "Re: %s", bfr);
746: }
747: if (!edit) {
748: fprintf(ofp, "To: %s\n", pathptr);
749: ed = index(MAILER, '%');
750: if (ed && ed[1] == 's')
751: fprintf(ofp, "Subject: %s\n", subj);
752: (void) fflush(ofp);
753: }
754:
755: /* Put the user in the editor to create the body of the followup. */
756: if (edit) {
757: int oumask;
758:
759: (void) strcpy(tf, tft);
760: (void) mktemp(tf);
761:
762: ed = getenv("EDITOR");
763: if (ed == NULL)
764: ed = DFTEDITOR;
765:
766: oumask = umask(077);
767: if ((tfp = fopen(tf, "w")) == NULL) {
768: perror(tf);
769: creatm = 0L;
770: } else {
771: fprintf(tfp, "To: %s\n", pathptr);
772: fprintf(tfp, "Subject: %s\n", subj);
773: #ifdef INTERNET
774: fprintf(tfp, "News-Path: %s\n", hptr->path);
775: #endif /* INTERNET */
776: fprintf(tfp, "References: %s\n\n", folbuf);
777: fstat(fileno(tfp), &statb);
778: creatm = statb.st_mtime;
779: (void) fclose(tfp);
780: }
781: (void) umask(oumask);
782:
783: (void) sprintf(edcmdbuf, "%s %s", ed, tf);
784: (void) system(edcmdbuf);
785: (void) strcpy(rcbuf, MAILPARSER);
786: (void) strcat(rcbuf, " -t");
787: (void) strcat(rcbuf, " < ");
788: (void) strcat(rcbuf, tf);
789: if (access(tf, 4) || stat(tf, &statb)) {
790: fprintf(stderr, "Reply not sent: no input file.\n");
791: return FALSE;
792: }
793: if (statb.st_mtime == creatm) {
794: fprintf(stderr, "Reply not sent: cancelled.\n");
795: (void) unlink(tf);
796: return FALSE;
797: }
798: fprintf(ofp,"Sending reply.\n");
799: (void) fflush(stdout);
800: if (fork() == 0) {
801: (void) system(rcbuf);
802: (void) unlink(tf);
803: _exit(0);
804: }
805: } else {
806: (void) sprintf(rcbuf, MAILER, hptr->title);
807: (void) sprintf(bfr, "%s %s", rcbuf, address);
808: (void) system(bfr);
809: }
810: hdr();
811: return TRUE;
812: }
813:
814: xmit_command()
815: {
816: tfilename = filename;
817: if (*bptr == '-') {
818: if (*ofilename1)
819: tfilename = ofilename1;
820: bptr++;
821: }
822: if (*bptr != '\0' && *bptr != ' ') {
823: fprintf(ofp, "Bad system name.\n");
824: return;
825: }
826: while (*bptr == ' ')
827: bptr++;
828: if (*bptr == '\0') {
829: fprintf(ofp, "Missing system name.\n");
830: return;
831: }
832: if (s_find(&srec, bptr) == NULL) {
833: fprintf(ofp, "%s not in SYSFILE\n", bptr);
834: return;
835: }
836: (void) transmit(&srec, tfilename);
837: }
838:
839: next_ng_command()
840: {
841: obit = -1;
842: if (!*bptr || *bptr == '-') {
843: if (cflag)
844: clear(bit);
845: else
846: putc('\n', ofp);
847: if (*bptr)
848: actdirect = BACKWARD;
849: rfq = 0;
850: saveart;
851: if (nextng()) {
852: if (actdirect == BACKWARD)
853: fprintf(ofp, "Can't back up.\n");
854: else
855: return TRUE;
856: }
857: return FALSE;
858: }
859: while (isspace(*bptr))
860: bptr++;
861: if (!validng(bptr)) {
862: fprintf(ofp, "No such group.\n");
863: return FALSE;
864: }
865: if (cflag)
866: clear(bit);
867: else
868: putc('\n', ofp);
869: readmode = SPEC;
870: rfq = 0;
871: saveart;
872: back();
873: selectng(bptr, TRUE, TRUE);
874: return FALSE;
875: }
876:
877: caesar_command()
878: {
879: char temp[BUFLEN];
880: FILE *pfp, *popen();
881:
882: fprintf(stderr, "Caesar decoding:\n");
883: (void) sprintf(temp, "%s/%s", LIB, "caesar");
884: if (*bptr) {
885: (void) strcat(temp, " ");
886: (void) strcat(temp, bptr);
887: }
888: if (NLINES(h, fp) > LNCNT && *PAGER) {
889: (void) strcat(temp, " | ");
890: (void) strcat(temp, PAGER);
891: }
892: pfp = popen(temp, "w");
893: tprint(fp, pfp, FALSE);
894: FCLOSE(fp);
895: (void) pclose(pfp);
896: }
897:
898: /*
899: * Show the user the tail, if any, of the message on file
900: * descriptor fd, and close fd. The digester is considered,
901: * and the pager is used if appropriate.
902: */
903: showtail(fd)
904: FILE *fd;
905: {
906: if (fd == NULL)
907: return;
908:
909: if (dgest) {
910: digest(fd, ofp, h);
911: } else if (!lflag && !pflag && !eflag) {
912: pprint(fd);
913: }
914: (void) fclose(fd);
915: }
916:
917: /*
918: * Print out the rest of the article through the pager.
919: */
920: pprint(fd)
921: FILE *fd;
922: {
923: #ifdef PAGE
924: /* Filter the tail of long messages through PAGER. */
925: if (NLINES(h, fd) > LNCNT && *PAGER) {
926: if (!index(PAGER, FMETA)) {
927: FILE *pfp, *popen();
928:
929: pfp = popen(PAGER, "w");
930: if (pfp == NULL)
931: pfp = ofp;
932: /*
933: * What follows is an attempt to prevent the
934: * next message from scrolling part of this
935: * message off the top of the screen before
936: * the poor luser can read it.
937: */
938: tprint(fd, pfp, FALSE);
939: putc('\f', pfp);
940: putc('\n', pfp);
941: putc(' ', pfp);
942: (void) pclose(pfp);
943: }
944: else
945: pout(ofp);
946: holdup = TRUE;
947: }
948: else
949: #endif
950: tprint(fd, ofp, FALSE);
951: }
952:
953: /*
954: * Find the next article we want to consider, if we're done with
955: * the last one, and show the header.
956: */
957: getnextart(minus)
958: int minus;
959: {
960: int noaccess;
961: register DIR *dirp;
962: register struct direct *dir;
963: long nextnum, tnum;
964:
965: noaccess = 0;
966:
967: if (minus)
968: goto nextart2; /* Kludge for "-" command. */
969:
970: if (bit == obit) /* Return if still on same article as last time */
971: return 0;
972:
973: SigTrap = FALSE;
974:
975: nextart:
976: #ifdef DEBUG
977: fprintf(stderr,"nextart:\n");
978: #endif /* DEBUG */
979: dgest = 0;
980:
981: if (bit < minartno && !rflag)
982: bit = minartno;
983:
984: /* If done with this newsgroup, find the next one. */
985: while (ngsize <= 0 || (!rflag && ((long) bit > ngsize)) || (rflag && bit < minartno)) {
986: if (nextng()) {
987: if (actdirect == BACKWARD) {
988: fprintf(ofp, "Can't back up.\n");
989: actdirect = FORWARD;
990: continue;
991: } else
992: if (rfq++ || pflag || cflag)
993: return 1;
994: break;
995: }
996: if (rflag)
997: bit = ngsize + 1;
998: else
999: bit = minartno - 1;
1000: if (uflag && !xflag) {
1001: time_t now;
1002: (void) time(&now);
1003: if (now - timelastsaved > 5*60 /* 5 minutes */) {
1004: if (!xflag)
1005: fprintf(stderr,"[Saving .newsrc]\n");
1006: writeoutrc();
1007: timelastsaved = now;
1008: }
1009: }
1010: noaccess = 0;
1011: }
1012:
1013: nextart2:
1014: #ifdef DEBUG
1015: fprintf(stderr, "article: %s/%ld\n", groupdir, bit);
1016: #endif
1017: if (rcreadok)
1018: rcreadok = 2; /* have seen >= 1 article */
1019: (void) sprintf(filename, "%s/%ld", dirname(groupdir), bit);
1020: if (rfq && goodone[0])
1021: strcpy(filename, goodone);
1022: if (SigTrap) {
1023: if (SigTrap == SIGHUP)
1024: return 1;
1025: if (!rcreadok)
1026: xxit(0);
1027: fprintf(ofp, "Abort (n)? ");
1028: (void) fflush(ofp);
1029: (void) gets(bfr);
1030: if (*bfr == 'y' || *bfr == 'Y')
1031: xxit(0);
1032: SigTrap = FALSE;
1033: }
1034: #ifdef DEBUG
1035: fprintf(stderr, "filename = '%s'\n", filename);
1036: #endif
1037: /* Decide if we want to show this article. */
1038: if (bit <= 0 || (fp = fopen(filename, "r")) == NULL) {
1039: /* don't show the header if the article was specifically
1040: * requested and it isn't there
1041: */
1042: if (lbuf[0] == '<') {
1043: lbuf[0] = '\0';
1044: bit = -1;
1045: return 1;
1046: }
1047: /* since there can be holes in legal article numbers, */
1048: /* we wait till we hit 5 consecutive bad articles */
1049: /* before we haul off and scan the directory */
1050: if (++noaccess < 5)
1051: goto badart;
1052: noaccess = 0;
1053: dirp = opendir(dirname(groupdir));
1054: if (dirp == NULL) {
1055: if (errno != EACCES)
1056: fprintf(stderr,"Can't open %s\n", dirname(groupdir));
1057: goto badart;
1058: }
1059: nextnum = rflag ? minartno - 1 : ngsize + 1;
1060: while ((dir = readdir(dirp)) != NULL) {
1061: tnum = atol(dir->d_name);
1062: if (tnum <= 0)
1063: continue;
1064: if (rflag ? (tnum > nextnum && tnum < bit)
1065: : (tnum < nextnum && tnum > bit))
1066: nextnum = tnum;
1067: }
1068: closedir(dirp);
1069: if (rflag ? (nextnum >= bit) : (nextnum <= bit))
1070: goto badart;
1071: #ifdef DEBUG
1072: fprintf(stderr,"nextnum = %ld\n",nextnum);
1073: #endif /* DEBUG */
1074: do {
1075: clear(bit);
1076: nextbit();
1077: } while (rflag ? (nextnum < bit) : (nextnum > bit));
1078: obit = -1;
1079: abs = FALSE;
1080: goto nextart;
1081: } else
1082: noaccess = 0;
1083:
1084: if (ignorenews || hread(h, fp, TRUE) == NULL
1085: || (!rfq && !aselect(h, abs))) {
1086: if (ignorenews)
1087: news = TRUE;
1088: badart:
1089: #ifdef DEBUG
1090: fprintf(stderr, "Bad article '%s'\n", filename);
1091: #endif
1092: FCLOSE(fp);
1093: clear(bit);
1094: obit = -1;
1095: nextbit();
1096: abs = FALSE;
1097: goto nextart;
1098: }
1099: abs = FALSE;
1100: actdirect = FORWARD;
1101: news = TRUE;
1102: hdr();
1103: if (pflag)
1104: tprint(fp, ofp, FALSE);
1105: else if (cflag && !lflag && !eflag) {
1106: (void) fflush(ofp);
1107: pprint(fp);
1108: }
1109: if (cflag || lflag || eflag || pflag) {
1110: SigTrap = FALSE;
1111: FCLOSE(fp);
1112: }
1113: obit = bit;
1114: return 0;
1115: }
1116:
1117: /*
1118: * Print out whatever the appropriate header is
1119: */
1120: hdr()
1121: {
1122: char *briefdate();
1123:
1124: if (rfq)
1125: return;
1126:
1127: if (lflag || eflag) {
1128: hprint(h, ofp, 0);
1129: return;
1130: }
1131:
1132: /* Print out a header */
1133: if (ngrp) {
1134: pngsize = ngsize;
1135: ngrp--;
1136: nghprint(groupdir);
1137: }
1138: if (!hflag)
1139: fprintf(ofp, "Article %ld of %ld, %s.\n",
1140: bit, pngsize, briefdate(h->subdate));
1141: hprint(h, ofp, pflag ? 1 : 0);
1142: }
1143:
1144: nghprint(title)
1145: char *title;
1146: {
1147: char *tstr = "Newsgroup ";
1148: int l = strlen(title) + strlen(tstr);
1149:
1150: fprintf(ofp, "\n");
1151: if (!hflag) {
1152: dash(l, ofp);
1153: fprintf(ofp, "%s%s\n", tstr, title);
1154: dash(l, ofp);
1155: } else {
1156: fprintf(ofp, "%s%s, ", tstr, title);
1157: if (bit == pngsize)
1158: fprintf(ofp, "%ld\n", pngsize);
1159: else
1160: fprintf(ofp, "%ld-%ld\n", bit, pngsize);
1161: }
1162: fprintf(ofp, "\n");
1163: }
1164:
1165: /*
1166: * Routine to catch a continue signal.
1167: */
1168: catchcont(sig)
1169: int sig;
1170: {
1171: (void) signal(sig, catchcont);
1172: SigTrap = sig;
1173: (void) fflush(ofp);
1174: #ifdef SIGCONT
1175: if (fp && sig == SIGCONT)
1176: hdr();
1177: if (sig != SIGCONT)
1178: #endif /* SIGCONT */
1179: putc('\n', ofp);
1180: if (canlongjmp)
1181: longjmp(sigjmpbuf,1);
1182: }
1183:
1184: xxit(status)
1185: int status;
1186: {
1187: (void) unlink(infile);
1188: (void) unlink(outfile);
1189: #ifdef SORTACTIVE
1190: if (strncmp(ACTIVE,"/tmp/", 5) == 0)
1191: (void) unlink(ACTIVE);
1192: #endif /* SORTACTIVE */
1193: exit(status);
1194: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.