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: }

Defined functions

caesar_command defined in line 877; used 1 times
cancel_command defined in line 632; used 1 times
catchcont defined in line 1168; used 4 times
command defined in line 218; used 1 times
getnextart defined in line 957; used 3 times
hdr defined in line 1120; used 4 times
next_ng_command defined in line 839; used 1 times
nghprint defined in line 1144; used 1 times
pprint defined in line 920; used 2 times
readr defined in line 81; never used
reply_command defined in line 667; used 2 times
showtail defined in line 903; used 1 times
xmit_command defined in line 814; used 1 times
xxit defined in line 1184; used 4 times

Defined variables

Progname defined in line 33; never used
SccsId defined in line 19; never used
abs defined in line 68; used 7 times
address defined in line 54; used 2 times
bptr defined in line 59; used 74 times
canlongjmp defined in line 78; used 3 times
dgest defined in line 71; used 3 times
edcmdbuf defined in line 55; used 2 times
goodone defined in line 52; used 3 times
h defined in line 64; used 26 times
hbuf1 defined in line 63; used 1 times
  • in line 64
hbuf2 defined in line 63; used 1 times
  • in line 65
holdup defined in line 74; used 1 times
ignorenews defined in line 75; used 3 times
lbuf defined in line 35; used 3 times
ofilename1 defined in line 62; used 11 times
ogroupdir defined in line 53; used 16 times
ongsize defined in line 57; used 1 times
  • in line 38
oobit defined in line 70; used 12 times
pngsize defined in line 58; used 11 times
ptr1 defined in line 67; used 17 times
ptr2 defined in line 67; used 14 times
ptr3 defined in line 67; used 8 times
rfq defined in line 56; used 17 times
sigjmpbuf defined in line 77; used 2 times
srec defined in line 60; used 2 times
tf defined in line 69; used 10 times
tfilename defined in line 61; used 11 times
tft defined in line 41; used 1 times

Defined macros

EOL defined in line 214; used 7 times
NLINES defined in line 39; used 3 times
saveart defined in line 38; used 10 times
Last modified: 1986-01-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4300
Valid CSS Valid XHTML 1.0 Strict