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