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