|
|
1.1 ! root 1: #ident "@(#)collect.c 1.7 'attmail mail(1) command'" ! 2: #ident "@(#)mailx:collect.c 1.18.1.1" ! 3: /* Copyright (c) 1984 AT&T */ ! 4: /* All Rights Reserved */ ! 5: ! 6: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ ! 7: /* The copyright notice above does not evidence any */ ! 8: /* actual or intended publication of such source code. */ ! 9: ! 10: #ident "@(#)mailx:collect.c 1.16.1.1" ! 11: ! 12: /* ! 13: * mailx -- a modified version of a University of California at Berkeley ! 14: * mail program ! 15: * ! 16: * Collect input from standard input, handling ! 17: * ~ escapes. ! 18: */ ! 19: ! 20: #include "rcv.h" ! 21: ! 22: #ifdef SIGCONT ! 23: static void collcont(); ! 24: #endif ! 25: static void collrub(); ! 26: static void cpout(); ! 27: static int exwrite(); ! 28: static int forward(); ! 29: static void intack(); ! 30: static FILE *mesedit(); ! 31: static FILE *mespipe(); ! 32: static void resetsigs(); ! 33: static int stripnulls(); ! 34: static long transmit(); ! 35: static void xhalt(); ! 36: static char **Xaddone(); ! 37: ! 38: /* ! 39: * Read a message from standard output and return a read file to it ! 40: * or NULL on error. ! 41: */ ! 42: ! 43: /* ! 44: * The following hokiness with global variables is so that on ! 45: * receipt of an interrupt signal, the partial message can be salted ! 46: * away on dead.letter. The output file must be available to flush, ! 47: * and the input to read. Several open files could be saved all through ! 48: * mailx if stdio allowed simultaneous read/write access. ! 49: */ ! 50: ! 51: static void (*savesig)(); /* Previous SIGINT value */ ! 52: static void (*savehup)(); /* Previous SIGHUP value */ ! 53: #ifdef SIGCONT ! 54: static void (*savecont)(); /* Previous SIGCONT value */ ! 55: #endif ! 56: static FILE *newi; /* File for saving away */ ! 57: static FILE *newo; /* Output side of same */ ! 58: static int hf; /* Ignore interrups */ ! 59: static int hadintr; /* Have seen one SIGINT so far */ ! 60: static struct header *savehp; ! 61: static jmp_buf coljmp; /* To get back to work */ ! 62: ! 63: FILE * ! 64: collect(hp) ! 65: struct header *hp; ! 66: { ! 67: FILE *ibuf, *fbuf, *obuf; ! 68: int escape, eof; ! 69: long lc, cc; ! 70: register int c, t; ! 71: char linebuf[LINESIZE+1], *cp; ! 72: char *iprompt; ! 73: void (*sigpipe)(), (*sigint)(); ! 74: ! 75: noreset++; ! 76: ibuf = obuf = NULL; ! 77: newi = newo = NULL; ! 78: if ((obuf = fopen(tempMail, "w")) == NULL) { ! 79: perror(tempMail); ! 80: goto err; ! 81: } ! 82: newo = obuf; ! 83: if ((ibuf = fopen(tempMail, "r")) == NULL) { ! 84: perror(tempMail); ! 85: newo = NULL; ! 86: fclose(obuf); ! 87: goto err; ! 88: } ! 89: newi = ibuf; ! 90: removefile(tempMail); ! 91: ! 92: hf = !!value("ignore"); ! 93: hadintr = 1; ! 94: savehp = hp; ! 95: if ((savesig = sigset(SIGINT, SIG_IGN)) != (void (*)())SIG_IGN) ! 96: sigset(SIGINT, hf ? (void (*)())intack : (void (*)())collrub); ! 97: if ((savehup = sigset(SIGHUP, SIG_IGN)) != (void (*)())SIG_IGN) ! 98: sigset(SIGHUP, collrub); ! 99: #ifdef SIGCONT ! 100: # ifdef preSVr4 ! 101: savecont = sigset(SIGCONT, collcont); ! 102: # else ! 103: { ! 104: struct sigaction nsig, osig; ! 105: nsig.sa_handler = collcont; ! 106: sigemptyset(&nsig.sa_mask); ! 107: nsig.sa_flags = SA_RESTART; ! 108: (void) sigaction(SIGCONT, &nsig, &osig); ! 109: savecont = osig.sa_handler; ! 110: } ! 111: # endif ! 112: #endif ! 113: /* ! 114: * If we are going to prompt for subject/cc/bcc, ! 115: * refrain from printing a newline after ! 116: * the headers (since some people mind). ! 117: */ ! 118: ! 119: if (hp->h_subject == NOSTR) { ! 120: hp->h_subject = sflag; ! 121: sflag = NOSTR; ! 122: } ! 123: t = GMASK; ! 124: c = 0; ! 125: if (intty) { ! 126: if (hp->h_subject == NOSTR && value("asksub")) ! 127: c |= GSUBJECT; ! 128: /* adb: due to popular demand, these were moved to the end of the letter ! 129: * adb: if (hp->h_cc == NOSTR && value("askcc")) ! 130: * adb: c |= GCC; ! 131: * adb: if (hp->h_bcc == NOSTR && value("askbcc")) ! 132: * adb: c |= GBCC; ! 133: * adb */ ! 134: if (c) ! 135: t &= ~GNL; ! 136: } ! 137: if (hp->h_seq != 0) { ! 138: puthead(hp, stdout, t); ! 139: fflush(stdout); ! 140: } ! 141: if (setjmp(coljmp)) ! 142: goto err; ! 143: if (c) ! 144: grabh(hp, c, 1); ! 145: escape = SENDESC; ! 146: if ((cp = value("escape")) != NOSTR) ! 147: escape = *cp; ! 148: eof = 0; ! 149: if ((cp = value("MAILX_HEAD")) != NOSTR) { ! 150: cpout( cp, obuf); ! 151: if (isatty(fileno(stdin))) ! 152: cpout( cp, stdout); ! 153: } ! 154: iprompt = value("iprompt"); ! 155: fflush(obuf); ! 156: hadintr = 0; ! 157: for (;;) { ! 158: int nread, hasnulls; ! 159: setjmp(coljmp); ! 160: sigrelse(SIGINT); ! 161: sigrelse(SIGHUP); ! 162: if (intty && outtty && iprompt) ! 163: fputs(iprompt, stdout); ! 164: flush(); ! 165: if ((nread = getline(linebuf,LINESIZE,stdin,&hasnulls)) == NULL) { ! 166: if (intty && value("ignoreeof") != NOSTR) { ! 167: if (++eof > 35) ! 168: break; ! 169: printf("Use \".\" to terminate letter\n"); ! 170: continue; ! 171: } ! 172: break; ! 173: } ! 174: eof = 0; ! 175: hadintr = 0; ! 176: if (intty && equal(".\n", linebuf) && ! 177: (value("dot") != NOSTR || value("ignoreeof") != NOSTR)) ! 178: break; ! 179: if ((linebuf[0] != escape) || (rflag != NOSTR) || !intty) { ! 180: if (write(fileno(obuf),linebuf,nread) != nread) ! 181: goto err; ! 182: continue; ! 183: } ! 184: /* ! 185: * On double escape, just send the single one. ! 186: */ ! 187: if ((nread > 1) && (linebuf[1] == escape)) { ! 188: if (write(fileno(obuf),linebuf+1,nread-1) != (nread-1)) ! 189: goto err; ! 190: continue; ! 191: } ! 192: if (hasnulls) ! 193: nread = stripnulls(linebuf, nread); ! 194: c = linebuf[1]; ! 195: linebuf[nread - 1] = '\0'; ! 196: switch (c) { ! 197: default: ! 198: /* ! 199: * Otherwise, it's an error. ! 200: */ ! 201: printf("Unknown tilde escape.\n"); ! 202: break; ! 203: ! 204: case 'a': ! 205: case 'A': ! 206: /* ! 207: * autograph; sign the letter. ! 208: */ ! 209: ! 210: if (cp = value(c=='a' ? "sign":"Sign")) { ! 211: cpout( cp, obuf); ! 212: if (isatty(fileno(stdin))) ! 213: cpout( cp, stdout); ! 214: } ! 215: ! 216: break; ! 217: ! 218: case 'i': ! 219: /* ! 220: * insert string ! 221: */ ! 222: for (cp = &linebuf[2]; any(*cp, " \t"); cp++) ! 223: ; ! 224: if (*cp) ! 225: cp = value(cp); ! 226: if (cp != NOSTR) { ! 227: cpout(cp, obuf); ! 228: if (isatty(fileno(stdout))) ! 229: cpout(cp, stdout); ! 230: } ! 231: break; ! 232: ! 233: case '!': ! 234: /* ! 235: * Shell escape, send the balance of the ! 236: * line to sh -c. ! 237: */ ! 238: ! 239: shell(&linebuf[2]); ! 240: break; ! 241: ! 242: case ':': ! 243: case '_': ! 244: /* ! 245: * Escape to command mode, but be nice! ! 246: */ ! 247: ! 248: execute(&linebuf[2], 1); ! 249: iprompt = value("iprompt"); ! 250: if (cp = value("escape")) ! 251: escape = *cp; ! 252: printf("(continue)\n"); ! 253: break; ! 254: ! 255: case '.': ! 256: /* ! 257: * Simulate end of file on input. ! 258: */ ! 259: goto eofl; ! 260: ! 261: case 'q': ! 262: case 'Q': ! 263: /* ! 264: * Force a quit of sending mail. ! 265: * Act like an interrupt happened. ! 266: */ ! 267: ! 268: hadintr++; ! 269: collrub(SIGINT); ! 270: exit(1); ! 271: /* NOTREACHED */ ! 272: ! 273: case 'x': ! 274: xhalt(); ! 275: break; /* not reached */ ! 276: ! 277: case 'h': ! 278: /* ! 279: * Grab a bunch of headers. ! 280: */ ! 281: if (!intty || !outtty) { ! 282: printf("~h: no can do!?\n"); ! 283: break; ! 284: } ! 285: grabh(hp, GMASK, 0); ! 286: printf("(continue)\n"); ! 287: break; ! 288: ! 289: case 't': ! 290: /* ! 291: * Add to the To list. ! 292: */ ! 293: ! 294: hp->h_to = addto(hp->h_to, &linebuf[2]); ! 295: hp->h_seq++; ! 296: break; ! 297: ! 298: case 's': ! 299: /* ! 300: * Set the Subject list. ! 301: */ ! 302: ! 303: cp = &linebuf[2]; ! 304: while (any(*cp, " \t")) ! 305: cp++; ! 306: hp->h_subject = savestr(cp); ! 307: hp->h_seq++; ! 308: break; ! 309: ! 310: case 'c': ! 311: /* ! 312: * Add to the CC list. ! 313: */ ! 314: ! 315: hp->h_cc = addto(hp->h_cc, &linebuf[2]); ! 316: hp->h_seq++; ! 317: break; ! 318: ! 319: case 'b': ! 320: /* ! 321: * Add stuff to blind carbon copies list. ! 322: */ ! 323: hp->h_bcc = addto(hp->h_bcc, &linebuf[2]); ! 324: hp->h_seq++; ! 325: break; ! 326: ! 327: case 'R': ! 328: hp->h_defopt = addone(hp->h_defopt, "/receipt"); ! 329: hp->h_seq++; ! 330: fprintf(stderr, "Return receipt marked.\n"); ! 331: break; ! 332: ! 333: case 'd': ! 334: copy(Getf("DEAD"), &linebuf[2]); ! 335: /* FALLTHROUGH */ ! 336: ! 337: case '<': ! 338: case 'r': { ! 339: int ispip; ! 340: /* ! 341: * Invoke a file: ! 342: * Search for the file name, ! 343: * then open it and copy the contents to obuf. ! 344: * ! 345: * if name begins with '!', read from a command ! 346: */ ! 347: ! 348: cp = &linebuf[2]; ! 349: while (any(*cp, " \t")) ! 350: cp++; ! 351: if (*cp == '\0') { ! 352: printf("Interpolate what file?\n"); ! 353: break; ! 354: } ! 355: if (*cp=='!') { ! 356: /* take input from a command */ ! 357: ispip = 1; ! 358: if ((fbuf = npopen(++cp, "r"))==NULL) { ! 359: perror(""); ! 360: break; ! 361: } ! 362: sigint = sigset(SIGINT, SIG_IGN); ! 363: } else { ! 364: ispip = 0; ! 365: cp = expand(cp); ! 366: if (cp == NOSTR) ! 367: break; ! 368: if (isdir(cp)) { ! 369: printf("%s: directory\n",cp); ! 370: break; ! 371: } ! 372: if ((fbuf = fopen(cp, "r")) == NULL) { ! 373: perror(cp); ! 374: break; ! 375: } ! 376: } ! 377: printf("\"%s\" ", cp); ! 378: flush(); ! 379: lc = cc = 0; ! 380: while ((t = getc(fbuf)) != EOF) { ! 381: if (t == '\n') ! 382: lc++; ! 383: if (putc(t, obuf) == EOF) { ! 384: if (ispip) { ! 385: npclose(fbuf); ! 386: sigset(SIGINT, sigint); ! 387: } else ! 388: fclose(fbuf); ! 389: goto err; ! 390: } ! 391: cc++; ! 392: } ! 393: if (ispip) { ! 394: npclose(fbuf); ! 395: sigset(SIGINT, sigint); ! 396: } else ! 397: fclose(fbuf); ! 398: printf("%ld/%ld\n", lc, cc); ! 399: fflush(obuf); ! 400: break; ! 401: } ! 402: ! 403: case 'w': ! 404: /* ! 405: * Write the message on a file. ! 406: */ ! 407: ! 408: cp = &linebuf[2]; ! 409: while (any(*cp, " \t")) ! 410: cp++; ! 411: if (*cp == '\0') { ! 412: fprintf(stderr, "Write what file!?\n"); ! 413: break; ! 414: } ! 415: if ((cp = expand(cp)) == NOSTR) ! 416: break; ! 417: fflush(obuf); ! 418: rewind(ibuf); ! 419: exwrite(cp, ibuf); ! 420: break; ! 421: ! 422: case 'm': ! 423: case 'f': ! 424: /* ! 425: * Interpolate the named messages, if we ! 426: * are in receiving mail mode. Does the ! 427: * standard list processing garbage. ! 428: * If ~f is given, we don't shift over. ! 429: */ ! 430: ! 431: if (!rcvmode) { ! 432: printf("No messages to send from!?!\n"); ! 433: break; ! 434: } ! 435: cp = &linebuf[2]; ! 436: while (any(*cp, " \t")) ! 437: cp++; ! 438: if (forward(cp, obuf, c) < 0) ! 439: goto err; ! 440: fflush(obuf); ! 441: printf("(continue)\n"); ! 442: break; ! 443: ! 444: case '?': ! 445: if ((fbuf = fopen(THELPFILE, "r")) == NULL) { ! 446: printf("No help just now.\n"); ! 447: break; ! 448: } ! 449: t = getc(fbuf); ! 450: while (t != -1) { ! 451: putchar(t); ! 452: t = getc(fbuf); ! 453: } ! 454: fclose(fbuf); ! 455: break; ! 456: ! 457: case 'p': ! 458: /* ! 459: * Print out the current state of the ! 460: * message without altering anything. ! 461: */ ! 462: ! 463: fflush(obuf); ! 464: rewind(ibuf); ! 465: if (value("crt")) { ! 466: char *pg = PG; ! 467: if (!*pg) ! 468: pg = "cat"; ! 469: if (fbuf = npopen(pg, "w")) { /* adb */ ! 470: sigint = sigset(SIGINT, SIG_IGN); ! 471: sigpipe = sigset(SIGPIPE, SIG_IGN); ! 472: } else ! 473: fbuf = stdout; ! 474: } else ! 475: fbuf = stdout; ! 476: fprintf(fbuf, "-------\nMessage contains:\n"); ! 477: puthead(hp, fbuf, GMASK); ! 478: while ((t = getc(ibuf))!=EOF) ! 479: putc(t, fbuf); ! 480: if (fbuf != stdout) { ! 481: npclose(fbuf); ! 482: sigset(SIGPIPE, sigpipe); ! 483: sigset(SIGINT, sigint); ! 484: } ! 485: printf("(continue)\n"); ! 486: break; ! 487: ! 488: case '^': ! 489: case '|': ! 490: /* ! 491: * Pipe message through command. ! 492: * Collect output as new message. ! 493: */ ! 494: ! 495: obuf = mespipe(ibuf, obuf, &linebuf[2]); ! 496: newo = obuf; ! 497: ibuf = newi; ! 498: newi = ibuf; ! 499: printf("(continue)\n"); ! 500: break; ! 501: ! 502: case 'v': ! 503: case 'e': ! 504: /* ! 505: * Edit the current message. ! 506: * 'e' means to use EDITOR ! 507: * 'v' means to use VISUAL ! 508: */ ! 509: ! 510: if ((obuf = mesedit(ibuf, obuf, c, hp)) == NULL) ! 511: goto err; ! 512: newo = obuf; ! 513: ibuf = newi; ! 514: printf("(continue)\n"); ! 515: break; ! 516: } ! 517: fflush(obuf); ! 518: } ! 519: eofl: ! 520: c = 0; /* adb */ ! 521: if (intty) { /* adb */ ! 522: if (hp->h_cc == NOSTR && value("askcc")) /* adb */ ! 523: c |= GCC; /* adb */ ! 524: if (hp->h_bcc == NOSTR && value("askbcc")) /* adb */ ! 525: c |= GBCC; /* adb */ ! 526: } /* adb */ ! 527: if (c) /* adb */ ! 528: grabh(hp, c, 1); /* adb */ ! 529: fflush(obuf); ! 530: if ((cp = value("MAILX_TAIL")) != NOSTR) { ! 531: cpout( cp, obuf); ! 532: if (isatty(fileno(stdin))) ! 533: cpout( cp, stdout); ! 534: } ! 535: fclose(obuf); ! 536: rewind(ibuf); ! 537: resetsigs(0); ! 538: noreset = 0; ! 539: return(ibuf); ! 540: ! 541: err: ! 542: if (ibuf != NULL) ! 543: fclose(ibuf); ! 544: if (obuf != NULL) ! 545: fclose(obuf); ! 546: resetsigs(0); ! 547: noreset = 0; ! 548: return(NULL); ! 549: } ! 550: ! 551: static void resetsigs(resethup) ! 552: int resethup; ! 553: { ! 554: (void) sigset(SIGINT, savesig); ! 555: if (resethup) ! 556: (void) sigset(SIGHUP, savehup); ! 557: #ifdef SIGCONT ! 558: # ifdef preSVr4 ! 559: (void) sigset(SIGCONT, savecont); ! 560: # else ! 561: { ! 562: struct sigaction nsig; ! 563: nsig.sa_handler = savecont; ! 564: sigemptyset(&nsig.sa_mask); ! 565: nsig.sa_flags = SA_RESTART; ! 566: (void) sigaction(SIGCONT, &nsig, (struct sigaction*)0); ! 567: } ! 568: # endif ! 569: #endif ! 570: } ! 571: ! 572: /* ! 573: * Write a file ex-like. ! 574: */ ! 575: ! 576: static int ! 577: exwrite(name, ibuf) ! 578: char name[]; ! 579: FILE *ibuf; ! 580: { ! 581: register FILE *of; ! 582: struct stat junk; ! 583: void (*sigint)(), (*sigpipe)(); ! 584: int pi = (*name == '!'); ! 585: ! 586: if (!pi && stat(name, &junk) >= 0 ! 587: && (junk.st_mode & S_IFMT) == S_IFREG) { ! 588: fprintf(stderr, "%s: File exists\n", name); ! 589: return(-1); ! 590: } ! 591: if ((of = pi ? npopen(++name, "w") : fopen(name, "w")) == NULL) { ! 592: perror(name); ! 593: return(-1); ! 594: } ! 595: if (pi) { ! 596: sigint = sigset(SIGINT, SIG_IGN); ! 597: sigpipe = sigset(SIGPIPE, SIG_IGN); ! 598: } ! 599: lcwrite(name, ibuf, of); ! 600: pi ? npclose(of) : fclose(of); ! 601: if (pi) { ! 602: sigset(SIGPIPE, sigpipe); ! 603: sigset(SIGINT, sigint); ! 604: } ! 605: return(0); ! 606: } ! 607: ! 608: void ! 609: lcwrite(fn, fi, fo) ! 610: char *fn; ! 611: FILE *fi, *fo; ! 612: { ! 613: register int c; ! 614: long lc, cc; ! 615: ! 616: printf("\"%s\" ", fn); ! 617: fflush(stdout); ! 618: lc = cc = 0; ! 619: while ((c = getc(fi)) != EOF) { ! 620: cc++; ! 621: if (putc(c, fo) == '\n') ! 622: lc++; ! 623: if (ferror(fo)) { ! 624: perror(""); ! 625: return; ! 626: } ! 627: } ! 628: printf("%ld/%ld\n", lc, cc); ! 629: fflush(stdout); ! 630: } ! 631: ! 632: /* ! 633: * Edit the message being collected on ibuf and obuf. ! 634: * Write the message out onto some poorly-named temp file ! 635: * and point an editor at it. ! 636: * ! 637: * On return, make the edit file the new temp file. ! 638: */ ! 639: ! 640: static FILE * ! 641: mesedit(ibuf, obuf, c, hp) ! 642: FILE *ibuf, *obuf; ! 643: struct header *hp; ! 644: { ! 645: pid_t pid; ! 646: FILE *fbuf; ! 647: register int t; ! 648: void (*sigint)(); ! 649: struct stat sbuf; ! 650: register char *edit; ! 651: char hdr[LINESIZE]; ! 652: ! 653: if (stat(tempEdit, &sbuf) >= 0) { ! 654: printf("%s: file exists\n", tempEdit); ! 655: goto out; ! 656: } ! 657: close(creat(tempEdit, TEMPPERM)); ! 658: if ((fbuf = fopen(tempEdit, "w")) == NULL) { ! 659: perror(tempEdit); ! 660: goto out; ! 661: } ! 662: fflush(obuf); ! 663: rewind(ibuf); ! 664: puthead(hp, fbuf, GMASK); ! 665: while ((t = getc(ibuf)) != EOF) ! 666: putc(t, fbuf); ! 667: fflush(fbuf); ! 668: if (ferror(fbuf)) { ! 669: perror(tempEdit); ! 670: removefile(tempEdit); ! 671: goto out; ! 672: } ! 673: fclose(fbuf); ! 674: if ((edit = value(c == 'e' ? "EDITOR" : "VISUAL")) == NOSTR) ! 675: edit = c == 'e' ? EDITOR : VISUAL; ! 676: edit = expand(edit); ! 677: ! 678: /* ! 679: * Fork/execlp the editor on the edit file ! 680: */ ! 681: ! 682: pid = fork(); ! 683: if ( pid == (pid_t)-1 ) { ! 684: perror("fork"); ! 685: removefile(tempEdit); ! 686: goto out; ! 687: } ! 688: if ( pid == 0 ) { ! 689: sigchild(); ! 690: execlp(edit, edit, tempEdit, (char *)0); ! 691: perror(edit); ! 692: _exit(1); ! 693: } ! 694: sigint = sigset(SIGINT, SIG_IGN); ! 695: while (wait((int *)0) != pid) ! 696: ; ! 697: sigset(SIGINT, sigint); ! 698: /* ! 699: * Now switch to new file. ! 700: */ ! 701: ! 702: if ((fbuf = fopen(tempEdit, "r")) == NULL) { ! 703: perror(tempEdit); ! 704: removefile(tempEdit); ! 705: goto out; ! 706: } ! 707: removefile(tempEdit); ! 708: hp->h_to = hp->h_subject = hp->h_cc = hp->h_bcc = hp->h_defopt = NOSTR; ! 709: hp->h_others = NOSTRPTR; ! 710: hp->h_seq = 0; ! 711: while (gethfield(fbuf, hdr, 9999L) > 0) { ! 712: if (ishfield(hdr, "to")) ! 713: hp->h_to = addto(hp->h_to, hcontents(hdr)); ! 714: else if (ishfield(hdr, "subject")) ! 715: hp->h_subject = addone(hp->h_subject, hcontents(hdr)); ! 716: else if (ishfield(hdr, "cc")) ! 717: hp->h_cc = addto(hp->h_cc, hcontents(hdr)); ! 718: else if (ishfield(hdr, "bcc")) ! 719: hp->h_bcc = addto(hp->h_bcc, hcontents(hdr)); ! 720: else if (ishfield(hdr, "default-options")) ! 721: hp->h_defopt = addone(hp->h_defopt, hcontents(hdr)); ! 722: else ! 723: hp->h_others = Xaddone(hp->h_others, hdr); ! 724: hp->h_seq++; ! 725: } ! 726: if ((obuf = fopen(tempMail, "w")) == NULL) { ! 727: perror(tempMail); ! 728: fclose(fbuf); ! 729: goto out; ! 730: } ! 731: if ((ibuf = fopen(tempMail, "r")) == NULL) { ! 732: perror(tempMail); ! 733: removefile(tempMail); ! 734: fclose(fbuf); ! 735: fclose(obuf); ! 736: goto out; ! 737: } ! 738: removefile(tempMail); ! 739: if (strlen(hdr) > 0) { ! 740: fputs(hdr, obuf); ! 741: putc('\n', obuf); ! 742: } ! 743: while ((t = getc(fbuf)) != EOF) ! 744: putc(t, obuf); ! 745: fclose(fbuf); ! 746: fclose(newo); ! 747: fclose(newi); ! 748: newo = obuf; ! 749: newi = ibuf; ! 750: out: ! 751: return(newo); ! 752: } ! 753: ! 754: /* ! 755: * Pipe the message through the command. ! 756: * Old message is on stdin of command; ! 757: * New message collected from stdout. ! 758: * Sh -c must return 0 to accept the new message. ! 759: */ ! 760: ! 761: static FILE * ! 762: mespipe(ibuf, obuf, cmd) ! 763: FILE *ibuf, *obuf; ! 764: char cmd[]; ! 765: { ! 766: register FILE *ni, *no; ! 767: pid_t pid; ! 768: int s; ! 769: void (*sigint)(); ! 770: char *Shell; ! 771: ! 772: newi = ibuf; ! 773: if ((no = fopen(tempEdit, "w")) == NULL) { ! 774: perror(tempEdit); ! 775: return(obuf); ! 776: } ! 777: if ((ni = fopen(tempEdit, "r")) == NULL) { ! 778: perror(tempEdit); ! 779: fclose(no); ! 780: removefile(tempEdit); ! 781: return(obuf); ! 782: } ! 783: removefile(tempEdit); ! 784: fflush(obuf); ! 785: rewind(ibuf); ! 786: if ((Shell = value("SHELL")) == NULL || *Shell=='\0') ! 787: Shell = SHELL; ! 788: if ((pid = fork()) == (pid_t)-1) { ! 789: perror("fork"); ! 790: goto err; ! 791: } ! 792: if (pid == 0) { ! 793: /* ! 794: * stdin = current message. ! 795: * stdout = new message. ! 796: */ ! 797: ! 798: sigchild(); ! 799: close(0); ! 800: dup(fileno(ibuf)); ! 801: close(1); ! 802: dup(fileno(no)); ! 803: for (s = 4; s < 15; s++) ! 804: close(s); ! 805: execlp(Shell, Shell, "-c", cmd, (char *)0); ! 806: perror(Shell); ! 807: _exit(1); ! 808: } ! 809: sigint = sigset(SIGINT, SIG_IGN); ! 810: while (wait(&s) != pid) ! 811: ; ! 812: sigset(SIGINT, sigint); ! 813: if (s != 0 || pid == (pid_t)-1) { ! 814: fprintf(stderr, "\"%s\" failed!?\n", cmd); ! 815: goto err; ! 816: } ! 817: if (fsize(ni) == 0) { ! 818: fprintf(stderr, "No bytes from \"%s\" !?\n", cmd); ! 819: goto err; ! 820: } ! 821: ! 822: /* ! 823: * Take new files. ! 824: */ ! 825: ! 826: newi = ni; ! 827: fclose(ibuf); ! 828: fclose(obuf); ! 829: return(no); ! 830: ! 831: err: ! 832: fclose(no); ! 833: fclose(ni); ! 834: return(obuf); ! 835: } ! 836: ! 837: /* ! 838: * Interpolate the named messages into the current ! 839: * message, preceding each line with a tab. ! 840: * Return a count of the number of characters now in ! 841: * the message, or -1 if an error is encountered writing ! 842: * the message temporary. The flag argument is 'm' if we ! 843: * should shift over and 'f' if not. ! 844: */ ! 845: static int ! 846: forward(ms, obuf, f) ! 847: char ms[]; ! 848: FILE *obuf; ! 849: { ! 850: register int *msgvec, *ip; ! 851: ! 852: msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec); ! 853: if (msgvec == NOINTPTR) ! 854: return(0); ! 855: if (getmsglist(ms, msgvec, 0) < 0) ! 856: return(0); ! 857: if (*msgvec == NULL) { ! 858: *msgvec = first(0, MMNORM); ! 859: if (*msgvec == NULL) { ! 860: printf("No appropriate messages\n"); ! 861: return(0); ! 862: } ! 863: msgvec[1] = NULL; ! 864: } ! 865: printf("Interpolating:"); ! 866: for (ip = msgvec; *ip != NULL; ip++) { ! 867: touch(*ip); ! 868: printf(" %d", *ip); ! 869: if (f == 'm') { ! 870: if (transmit(&message[*ip-1], obuf) < 0L) { ! 871: perror(tempMail); ! 872: return(-1); ! 873: } ! 874: } else ! 875: if (send(&message[*ip-1], obuf, 0) < 0) { ! 876: perror(tempMail); ! 877: return(-1); ! 878: } ! 879: } ! 880: printf("\n"); ! 881: return(0); ! 882: } ! 883: ! 884: /* ! 885: * Send message described by the passed pointer to the ! 886: * passed output buffer. Insert a tab in front of each ! 887: * line. Return a count of the characters sent, or -1 ! 888: * on error. ! 889: */ ! 890: ! 891: static long ! 892: transmit(mailp, obuf) ! 893: struct message *mailp; ! 894: FILE *obuf; ! 895: { ! 896: register struct message *mp; ! 897: register int ch; ! 898: register long c, n; ! 899: int bol; ! 900: FILE *ibuf; ! 901: char *mprefix = value("mprefix"); ! 902: ! 903: if (!mprefix) ! 904: mprefix = "\t"; ! 905: mp = mailp; ! 906: ibuf = setinput(mp); ! 907: c = mp->m_size; ! 908: n = c; ! 909: bol = 1; ! 910: while (c-- > 0L) { ! 911: if (bol) { ! 912: bol = 0; ! 913: fputs(mprefix, obuf); ! 914: n++; ! 915: if (ferror(obuf)) { ! 916: perror("/tmp"); ! 917: return(-1L); ! 918: } ! 919: } ! 920: ch = getc(ibuf); ! 921: if (ch == '\n') ! 922: bol++; ! 923: putc(ch, obuf); ! 924: if (ferror(obuf)) { ! 925: perror("/tmp"); ! 926: return(-1L); ! 927: } ! 928: } ! 929: return(n); ! 930: } ! 931: ! 932: /* ! 933: * Print (continue) when continued after ^Z. ! 934: */ ! 935: #ifdef SIGCONT ! 936: /*ARGSUSED*/ ! 937: static void ! 938: collcont(s) ! 939: { ! 940: printf("(continue)\n",s); /* reference s to suppress warning -- adb */ ! 941: fflush(stdout); ! 942: } ! 943: #endif /* SIGCONT */ ! 944: ! 945: /* ! 946: * On interrupt, go here to save the partial ! 947: * message on ~/dead.letter. ! 948: * Then restore signals and execute the normal ! 949: * signal routine. We only come here if signals ! 950: * were previously set anyway. ! 951: */ ! 952: static void ! 953: collrub(s) ! 954: { ! 955: register FILE *dbuf; ! 956: register int c; ! 957: register char *deadletter = Getf("DEAD"); ! 958: long cc, lc; ! 959: ! 960: if (s == SIGHUP) ! 961: sigignore(SIGHUP); ! 962: if (s == SIGINT && hadintr == 0) { ! 963: hadintr++; ! 964: clrbuf(stdout); ! 965: printf("\n(Interrupt -- one more to kill letter)\n"); ! 966: sigrelse(s); ! 967: longjmp(coljmp, 1); ! 968: } ! 969: fclose(newo); ! 970: rewind(newi); ! 971: if (s == SIGINT && value("save")==NOSTR || fsize(newi) == 0) ! 972: goto done; ! 973: if ((dbuf = fopen(deadletter, "w")) == NULL) { /* old behavior -- adb */ ! 974: perror(deadletter); ! 975: goto done; ! 976: } ! 977: chmod(deadletter, DEADPERM); ! 978: printf("\"%s\" ", deadletter); ! 979: fflush(stdout); ! 980: puthead(savehp, dbuf, GMASK); ! 981: for (cc = lc = 0; (c = getc(newi)) != EOF; cc++) ! 982: if (putc(c, dbuf) == '\n') ! 983: lc++; ! 984: fclose(dbuf); ! 985: printf("%ld/%ld\n", lc, cc); ! 986: done: ! 987: fclose(newi); ! 988: resetsigs(1); ! 989: if (rcvmode) { ! 990: if (s == SIGHUP) ! 991: hangup(); ! 992: else ! 993: stop(s); ! 994: } ! 995: else ! 996: exit(1); ! 997: } ! 998: ! 999: /* ! 1000: * Acknowledge an interrupt signal from the tty by typing an @ ! 1001: */ ! 1002: static void ! 1003: intack(s) ! 1004: { ! 1005: (void) s; ! 1006: puts("@"); ! 1007: fflush(stdout); ! 1008: clearerr(stdin); ! 1009: longjmp(coljmp,1); ! 1010: } ! 1011: ! 1012: /* Read line from stdin, noting any NULL characters. ! 1013: Return the number of characters read. Note that the buffer ! 1014: passed must be 1 larger than "size" for the trailing NUL byte. ! 1015: */ ! 1016: int ! 1017: getline(line,size,f,hasnulls) ! 1018: char *line; ! 1019: int size; ! 1020: FILE *f; ! 1021: int *hasnulls; ! 1022: { ! 1023: register int i, ch; ! 1024: for (i = 0; (i < size) && ((ch=getc(f)) != EOF); ) { ! 1025: if ( ch == '\0' ) ! 1026: *hasnulls = 1; ! 1027: if ((line[i++] = ch) == '\n') break; ! 1028: } ! 1029: line[i] = '\0'; ! 1030: return(i); ! 1031: } ! 1032: ! 1033: void ! 1034: savedead(s) ! 1035: { ! 1036: (void) s; ! 1037: collrub(SIGINT); ! 1038: exit(1); ! 1039: /* NOTREACHED */ ! 1040: } ! 1041: ! 1042: /* ! 1043: * Add a list of addresses to the end of a header entry field. ! 1044: */ ! 1045: char * ! 1046: addto(hf, news) ! 1047: char hf[], news[]; ! 1048: { ! 1049: char name[LINESIZE]; ! 1050: int comma = docomma(news); ! 1051: ! 1052: while (news = yankword(news, name, comma)) { ! 1053: strcat(name, ", "); ! 1054: hf = addone(hf, name); ! 1055: } ! 1056: return hf; ! 1057: } ! 1058: ! 1059: /* ! 1060: * Add a string to the end of a header entry field. ! 1061: */ ! 1062: char * ! 1063: addone(hf, news) ! 1064: char hf[], news[]; ! 1065: { ! 1066: register char *cp, *cp2, *linebuf; ! 1067: ! 1068: if (hf == NOSTR) ! 1069: hf = ""; ! 1070: if (*news == '\0') ! 1071: return(hf); ! 1072: linebuf = salloc((unsigned)(strlen(hf) + strlen(news) + 2)); ! 1073: for (cp = hf; any(*cp, " \t"); cp++) ! 1074: ; ! 1075: for (cp2 = linebuf; *cp;) ! 1076: *cp2++ = *cp++; ! 1077: if (cp2 > linebuf && cp2[-1] != ' ') ! 1078: *cp2++ = ' '; ! 1079: for (cp = news; any(*cp, " \t"); cp++) ! 1080: ; ! 1081: while (*cp != '\0') ! 1082: *cp2++ = *cp++; ! 1083: *cp2 = '\0'; ! 1084: return(linebuf); ! 1085: } ! 1086: ! 1087: static int nptrs(hf) ! 1088: char **hf; ! 1089: { ! 1090: register int i; ! 1091: if (!hf) ! 1092: return 0; ! 1093: for (i = 0; *hf; hf++) ! 1094: i++; ! 1095: return i; ! 1096: } ! 1097: ! 1098: /* ! 1099: * Add a non-standard header to the end of the non-standard headers. ! 1100: */ ! 1101: static char ** ! 1102: Xaddone(hf, news) ! 1103: char **hf, news[]; ! 1104: { ! 1105: register char *linebuf; ! 1106: char **ohf = hf; ! 1107: int nhf = nptrs(hf); ! 1108: ! 1109: if (hf == NOSTRPTR) ! 1110: hf = (char**)salloc(sizeof(char*) * 2); ! 1111: else ! 1112: hf = (char**)srealloc(hf, sizeof(char*) * (nhf + 2)); ! 1113: if (hf == NOSTRPTR) { ! 1114: fprintf(stderr, "No room, header lost: %s\n", news); ! 1115: return(ohf); ! 1116: } ! 1117: linebuf = salloc((unsigned)(strlen(news) + 1)); ! 1118: strcpy(linebuf, news); ! 1119: hf[nhf++] = linebuf; ! 1120: hf[nhf] = NOSTR; ! 1121: return(hf); ! 1122: } ! 1123: ! 1124: static void ! 1125: cpout( str, ofd ) ! 1126: char *str; ! 1127: FILE *ofd; ! 1128: { ! 1129: register char *cp = str; ! 1130: ! 1131: while ( *cp ) { ! 1132: if ( *cp == '\\' ) { ! 1133: switch ( *(cp+1) ) { ! 1134: case 'n': ! 1135: putc('\n',ofd); ! 1136: cp++; ! 1137: break; ! 1138: case 't': ! 1139: putc('\t',ofd); ! 1140: cp++; ! 1141: break; ! 1142: default: ! 1143: putc('\\',ofd); ! 1144: } ! 1145: } ! 1146: else { ! 1147: putc(*cp,ofd); ! 1148: } ! 1149: cp++; ! 1150: } ! 1151: putc('\n',ofd); ! 1152: fflush(ofd); ! 1153: } ! 1154: ! 1155: static void ! 1156: xhalt() ! 1157: { ! 1158: fclose(newo); ! 1159: fclose(newi); ! 1160: sigset(SIGINT, savesig); ! 1161: sigset(SIGHUP, savehup); ! 1162: if (rcvmode) ! 1163: stop(0); ! 1164: exit(1); ! 1165: /* NOTREACHED */ ! 1166: } ! 1167: ! 1168: /* ! 1169: Strip the nulls from a buffer of length n ! 1170: */ ! 1171: static int ! 1172: stripnulls(linebuf, nread) ! 1173: register char *linebuf; ! 1174: register int nread; ! 1175: { ! 1176: register int i, j; ! 1177: for (i = 0; i < nread; i++) ! 1178: if (linebuf[i] == '\0') ! 1179: break; ! 1180: for (j = i; j < nread; j++) ! 1181: if (linebuf[j] != '\0') ! 1182: linebuf[i++] = linebuf[j]; ! 1183: linebuf[i] = '\0'; ! 1184: return i; ! 1185: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.