|
|
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.