1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: static char *sccsid = "@(#)collect.c	5.2 (Berkeley) 6/21/85";
   9: #endif not lint
  10: 
  11: /*
  12:  * Mail -- a mail program
  13:  *
  14:  * Collect input from standard input, handling
  15:  * ~ escapes.
  16:  */
  17: 
  18: #include "rcv.h"
  19: #include <sys/stat.h>
  20: 
  21: /*
  22:  * Read a message from standard output and return a read file to it
  23:  * or NULL on error.
  24:  */
  25: 
  26: /*
  27:  * The following hokiness with global variables is so that on
  28:  * receipt of an interrupt signal, the partial message can be salted
  29:  * away on dead.letter.  The output file must be available to flush,
  30:  * and the input to read.  Several open files could be saved all through
  31:  * Mail if stdio allowed simultaneous read/write access.
  32:  */
  33: 
  34: static  int (*savesig)();       /* Previous SIGINT value */
  35: static  int (*savehup)();       /* Previous SIGHUP value */
  36: # ifdef VMUNIX
  37: static  int (*savecont)();      /* Previous SIGCONT value */
  38: # endif VMUNIX
  39: static  FILE    *newi;          /* File for saving away */
  40: static  FILE    *newo;          /* Output side of same */
  41: static  int hf;         /* Ignore interrups */
  42: static  int hadintr;        /* Have seen one SIGINT so far */
  43: 
  44: static  jmp_buf coljmp;         /* To get back to work */
  45: 
  46: FILE *
  47: collect(hp)
  48:     struct header *hp;
  49: {
  50:     FILE *ibuf, *fbuf, *obuf;
  51:     int lc, cc, escape, collrub(), intack(), collhup, collcont(), eof;
  52:     register int c, t;
  53:     char linebuf[LINESIZE], *cp;
  54:     extern char tempMail[];
  55:     int notify();
  56:     extern collintsig(), collhupsig();
  57:     char getsub;
  58: 
  59:     noreset++;
  60:     ibuf = obuf = NULL;
  61:     if (value("ignore") != NOSTR)
  62:         hf = 1;
  63:     else
  64:         hf = 0;
  65:     hadintr = 0;
  66: # ifdef VMUNIX
  67:     if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN)
  68:         sigset(SIGINT, hf ? intack : collrub), sigblock(sigmask(SIGINT));
  69:     if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN)
  70:         sigset(SIGHUP, collrub), sigblock(sigmask(SIGHUP));
  71:     savecont = sigset(SIGCONT, collcont);
  72: # else VMUNIX
  73:     savesig = signal(SIGINT, SIG_IGN);
  74:     savehup = signal(SIGHUP, SIG_IGN);
  75: # endif VMUNIX
  76:     newi = NULL;
  77:     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:     remove(tempMail);
  91: 
  92:     /*
  93: 	 * If we are going to prompt for a subject,
  94: 	 * refrain from printing a newline after
  95: 	 * the headers (since some people mind).
  96: 	 */
  97: 
  98:     t = GTO|GSUBJECT|GCC|GNL;
  99:     getsub = 0;
 100:     if (intty && sflag == NOSTR && hp->h_subject == NOSTR && value("ask"))
 101:         t &= ~GNL, getsub++;
 102:     if (hp->h_seq != 0) {
 103:         puthead(hp, stdout, t);
 104:         fflush(stdout);
 105:     }
 106:     escape = ESCAPE;
 107:     if ((cp = value("escape")) != NOSTR)
 108:         escape = *cp;
 109:     eof = 0;
 110:     for (;;) {
 111:         int omask = sigblock(0) &~ (sigmask(SIGINT)|sigmask(SIGHUP));
 112: 
 113:         setjmp(coljmp);
 114: # ifdef VMUNIX
 115:         sigsetmask(omask);
 116: # else VMUNIX
 117:         if (savesig != SIG_IGN)
 118:             signal(SIGINT, hf ? intack : collintsig);
 119:         if (savehup != SIG_IGN)
 120:             signal(SIGHUP, collhupsig);
 121: # endif VMUNIX
 122:         fflush(stdout);
 123:         if (getsub) {
 124:             grabh(hp, GSUBJECT);
 125:             getsub = 0;
 126:             continue;
 127:         }
 128:         if (readline(stdin, linebuf) <= 0) {
 129:             if (intty && value("ignoreeof") != NOSTR) {
 130:                 if (++eof > 35)
 131:                     break;
 132:                 printf("Use \".\" to terminate letter\n",
 133:                     escape);
 134:                 continue;
 135:             }
 136:             break;
 137:         }
 138:         eof = 0;
 139:         hadintr = 0;
 140:         if (intty && equal(".", linebuf) &&
 141:             (value("dot") != NOSTR || value("ignoreeof") != NOSTR))
 142:             break;
 143:         if (linebuf[0] != escape || rflag != NOSTR) {
 144:             if ((t = putline(obuf, linebuf)) < 0)
 145:                 goto err;
 146:             continue;
 147:         }
 148:         c = linebuf[1];
 149:         switch (c) {
 150:         default:
 151:             /*
 152: 			 * On double escape, just send the single one.
 153: 			 * Otherwise, it's an error.
 154: 			 */
 155: 
 156:             if (c == escape) {
 157:                 if (putline(obuf, &linebuf[1]) < 0)
 158:                     goto err;
 159:                 else
 160:                     break;
 161:             }
 162:             printf("Unknown tilde escape.\n");
 163:             break;
 164: 
 165:         case 'C':
 166:             /*
 167: 			 * Dump core.
 168: 			 */
 169: 
 170:             core();
 171:             break;
 172: 
 173:         case '!':
 174:             /*
 175: 			 * Shell escape, send the balance of the
 176: 			 * line to sh -c.
 177: 			 */
 178: 
 179:             shell(&linebuf[2]);
 180:             break;
 181: 
 182:         case ':':
 183:         case '_':
 184:             /*
 185: 			 * Escape to command mode, but be nice!
 186: 			 */
 187: 
 188:             execute(&linebuf[2], 1);
 189:             printf("(continue)\n");
 190:             break;
 191: 
 192:         case '.':
 193:             /*
 194: 			 * Simulate end of file on input.
 195: 			 */
 196:             goto eofl;
 197: 
 198:         case 'q':
 199:         case 'Q':
 200:             /*
 201: 			 * Force a quit of sending mail.
 202: 			 * Act like an interrupt happened.
 203: 			 */
 204: 
 205:             hadintr++;
 206:             collrub(SIGINT);
 207:             exit(1);
 208: 
 209:         case 'h':
 210:             /*
 211: 			 * Grab a bunch of headers.
 212: 			 */
 213:             if (!intty || !outtty) {
 214:                 printf("~h: no can do!?\n");
 215:                 break;
 216:             }
 217:             grabh(hp, GTO|GSUBJECT|GCC|GBCC);
 218:             printf("(continue)\n");
 219:             break;
 220: 
 221:         case 't':
 222:             /*
 223: 			 * Add to the To list.
 224: 			 */
 225: 
 226:             hp->h_to = addto(hp->h_to, &linebuf[2]);
 227:             hp->h_seq++;
 228:             break;
 229: 
 230:         case 's':
 231:             /*
 232: 			 * Set the Subject list.
 233: 			 */
 234: 
 235:             cp = &linebuf[2];
 236:             while (any(*cp, " \t"))
 237:                 cp++;
 238:             hp->h_subject = savestr(cp);
 239:             hp->h_seq++;
 240:             break;
 241: 
 242:         case 'c':
 243:             /*
 244: 			 * Add to the CC list.
 245: 			 */
 246: 
 247:             hp->h_cc = addto(hp->h_cc, &linebuf[2]);
 248:             hp->h_seq++;
 249:             break;
 250: 
 251:         case 'b':
 252:             /*
 253: 			 * Add stuff to blind carbon copies list.
 254: 			 */
 255:             hp->h_bcc = addto(hp->h_bcc, &linebuf[2]);
 256:             hp->h_seq++;
 257:             break;
 258: 
 259:         case 'd':
 260:             copy(deadletter, &linebuf[2]);
 261:             /* fall into . . . */
 262: 
 263:         case 'r':
 264:             /*
 265: 			 * Invoke a file:
 266: 			 * Search for the file name,
 267: 			 * then open it and copy the contents to obuf.
 268: 			 */
 269: 
 270:             cp = &linebuf[2];
 271:             while (any(*cp, " \t"))
 272:                 cp++;
 273:             if (*cp == '\0') {
 274:                 printf("Interpolate what file?\n");
 275:                 break;
 276:             }
 277:             cp = expand(cp);
 278:             if (cp == NOSTR)
 279:                 break;
 280:             if (isdir(cp)) {
 281:                 printf("%s: directory\n");
 282:                 break;
 283:             }
 284:             if ((fbuf = fopen(cp, "r")) == NULL) {
 285:                 perror(cp);
 286:                 break;
 287:             }
 288:             printf("\"%s\" ", cp);
 289:             fflush(stdout);
 290:             lc = 0;
 291:             cc = 0;
 292:             while (readline(fbuf, linebuf) > 0) {
 293:                 lc++;
 294:                 if ((t = putline(obuf, linebuf)) < 0) {
 295:                     fclose(fbuf);
 296:                     goto err;
 297:                 }
 298:                 cc += t;
 299:             }
 300:             fclose(fbuf);
 301:             printf("%d/%d\n", lc, cc);
 302:             break;
 303: 
 304:         case 'w':
 305:             /*
 306: 			 * Write the message on a file.
 307: 			 */
 308: 
 309:             cp = &linebuf[2];
 310:             while (any(*cp, " \t"))
 311:                 cp++;
 312:             if (*cp == '\0') {
 313:                 fprintf(stderr, "Write what file!?\n");
 314:                 break;
 315:             }
 316:             if ((cp = expand(cp)) == NOSTR)
 317:                 break;
 318:             fflush(obuf);
 319:             rewind(ibuf);
 320:             exwrite(cp, ibuf, 1);
 321:             break;
 322: 
 323:         case 'm':
 324:         case 'f':
 325:             /*
 326: 			 * Interpolate the named messages, if we
 327: 			 * are in receiving mail mode.  Does the
 328: 			 * standard list processing garbage.
 329: 			 * If ~f is given, we don't shift over.
 330: 			 */
 331: 
 332:             if (!rcvmode) {
 333:                 printf("No messages to send from!?!\n");
 334:                 break;
 335:             }
 336:             cp = &linebuf[2];
 337:             while (any(*cp, " \t"))
 338:                 cp++;
 339:             if (forward(cp, obuf, c) < 0)
 340:                 goto err;
 341:             printf("(continue)\n");
 342:             break;
 343: 
 344:         case '?':
 345:             if ((fbuf = fopen(THELPFILE, "r")) == NULL) {
 346:                 perror(THELPFILE);
 347:                 break;
 348:             }
 349:             t = getc(fbuf);
 350:             while (t != -1) {
 351:                 putchar(t);
 352:                 t = getc(fbuf);
 353:             }
 354:             fclose(fbuf);
 355:             break;
 356: 
 357:         case 'p':
 358:             /*
 359: 			 * Print out the current state of the
 360: 			 * message without altering anything.
 361: 			 */
 362: 
 363:             fflush(obuf);
 364:             rewind(ibuf);
 365:             printf("-------\nMessage contains:\n");
 366:             puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL);
 367:             t = getc(ibuf);
 368:             while (t != EOF) {
 369:                 putchar(t);
 370:                 t = getc(ibuf);
 371:             }
 372:             printf("(continue)\n");
 373:             break;
 374: 
 375:         case '^':
 376:         case '|':
 377:             /*
 378: 			 * Pipe message through command.
 379: 			 * Collect output as new message.
 380: 			 */
 381: 
 382:             obuf = mespipe(ibuf, obuf, &linebuf[2]);
 383:             newo = obuf;
 384:             ibuf = newi;
 385:             newi = ibuf;
 386:             printf("(continue)\n");
 387:             break;
 388: 
 389:         case 'v':
 390:         case 'e':
 391:             /*
 392: 			 * Edit the current message.
 393: 			 * 'e' means to use EDITOR
 394: 			 * 'v' means to use VISUAL
 395: 			 */
 396: 
 397:             if ((obuf = mesedit(ibuf, obuf, c)) == NULL)
 398:                 goto err;
 399:             newo = obuf;
 400:             ibuf = newi;
 401:             printf("(continue)\n");
 402:             break;
 403:         }
 404:     }
 405: eofl:
 406:     fclose(obuf);
 407:     rewind(ibuf);
 408:     sigset(SIGINT, savesig);
 409:     sigset(SIGHUP, savehup);
 410: # ifdef VMUNIX
 411:     sigset(SIGCONT, savecont);
 412:     sigsetmask(0);
 413: # endif VMUNIX
 414:     noreset = 0;
 415:     return(ibuf);
 416: 
 417: err:
 418:     if (ibuf != NULL)
 419:         fclose(ibuf);
 420:     if (obuf != NULL)
 421:         fclose(obuf);
 422:     sigset(SIGINT, savesig);
 423:     sigset(SIGHUP, savehup);
 424: # ifdef VMUNIX
 425:     sigset(SIGCONT, savecont);
 426:     sigsetmask(0);
 427: # endif VMUNIX
 428:     noreset = 0;
 429:     return(NULL);
 430: }
 431: 
 432: /*
 433:  * Non destructively interrogate the value of the given signal.
 434:  */
 435: 
 436: psig(n)
 437: {
 438:     register (*wassig)();
 439: 
 440:     wassig = sigset(n, SIG_IGN);
 441:     sigset(n, wassig);
 442:     return((int) wassig);
 443: }
 444: 
 445: /*
 446:  * Write a file, ex-like if f set.
 447:  */
 448: 
 449: exwrite(name, ibuf, f)
 450:     char name[];
 451:     FILE *ibuf;
 452: {
 453:     register FILE *of;
 454:     register int c;
 455:     long cc;
 456:     int lc;
 457:     struct stat junk;
 458: 
 459:     if (f) {
 460:         printf("\"%s\" ", name);
 461:         fflush(stdout);
 462:     }
 463:     if (stat(name, &junk) >= 0 && (junk.st_mode & S_IFMT) == S_IFREG) {
 464:         if (!f)
 465:             fprintf(stderr, "%s: ", name);
 466:         fprintf(stderr, "File exists\n", name);
 467:         return(-1);
 468:     }
 469:     if ((of = fopen(name, "w")) == NULL) {
 470:         perror(NOSTR);
 471:         return(-1);
 472:     }
 473:     lc = 0;
 474:     cc = 0;
 475:     while ((c = getc(ibuf)) != EOF) {
 476:         cc++;
 477:         if (c == '\n')
 478:             lc++;
 479:         putc(c, of);
 480:         if (ferror(of)) {
 481:             perror(name);
 482:             fclose(of);
 483:             return(-1);
 484:         }
 485:     }
 486:     fclose(of);
 487:     printf("%d/%ld\n", lc, cc);
 488:     fflush(stdout);
 489:     return(0);
 490: }
 491: 
 492: /*
 493:  * Edit the message being collected on ibuf and obuf.
 494:  * Write the message out onto some poorly-named temp file
 495:  * and point an editor at it.
 496:  *
 497:  * On return, make the edit file the new temp file.
 498:  */
 499: 
 500: FILE *
 501: mesedit(ibuf, obuf, c)
 502:     FILE *ibuf, *obuf;
 503: {
 504:     int pid, s;
 505:     FILE *fbuf;
 506:     register int t;
 507:     int (*sig)(), (*scont)(), signull();
 508:     struct stat sbuf;
 509:     extern char tempMail[], tempEdit[];
 510:     register char *edit;
 511: 
 512:     sig = sigset(SIGINT, SIG_IGN);
 513: # ifdef VMUNIX
 514:     scont = sigset(SIGCONT, signull);
 515: # endif VMUNIX
 516:     if (stat(tempEdit, &sbuf) >= 0) {
 517:         printf("%s: file exists\n", tempEdit);
 518:         goto out;
 519:     }
 520:     close(creat(tempEdit, 0600));
 521:     if ((fbuf = fopen(tempEdit, "w")) == NULL) {
 522:         perror(tempEdit);
 523:         goto out;
 524:     }
 525:     fflush(obuf);
 526:     rewind(ibuf);
 527:     t = getc(ibuf);
 528:     while (t != EOF) {
 529:         putc(t, fbuf);
 530:         t = getc(ibuf);
 531:     }
 532:     fflush(fbuf);
 533:     if (ferror(fbuf)) {
 534:         perror(tempEdit);
 535:         remove(tempEdit);
 536:         goto fix;
 537:     }
 538:     fclose(fbuf);
 539:     if ((edit = value(c == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
 540:         edit = c == 'e' ? EDITOR : VISUAL;
 541:     pid = vfork();
 542:     if (pid == 0) {
 543:         sigchild();
 544:         if (sig != SIG_IGN)
 545:             sigsys(SIGINT, SIG_DFL);
 546:         execl(edit, edit, tempEdit, 0);
 547:         perror(edit);
 548:         _exit(1);
 549:     }
 550:     if (pid == -1) {
 551:         perror("fork");
 552:         remove(tempEdit);
 553:         goto out;
 554:     }
 555:     while (wait(&s) != pid)
 556:         ;
 557:     if ((s & 0377) != 0) {
 558:         printf("Fatal error in \"%s\"\n", edit);
 559:         remove(tempEdit);
 560:         goto out;
 561:     }
 562: 
 563:     /*
 564: 	 * Now switch to new file.
 565: 	 */
 566: 
 567:     if ((fbuf = fopen(tempEdit, "a")) == NULL) {
 568:         perror(tempEdit);
 569:         remove(tempEdit);
 570:         goto out;
 571:     }
 572:     if ((ibuf = fopen(tempEdit, "r")) == NULL) {
 573:         perror(tempEdit);
 574:         fclose(fbuf);
 575:         remove(tempEdit);
 576:         goto out;
 577:     }
 578:     remove(tempEdit);
 579:     fclose(obuf);
 580:     fclose(newi);
 581:     obuf = fbuf;
 582:     goto out;
 583: fix:
 584:     perror(tempEdit);
 585: out:
 586: # ifdef VMUNIX
 587:     sigset(SIGCONT, scont);
 588: # endif VMUNIX
 589:     sigset(SIGINT, sig);
 590:     newi = ibuf;
 591:     return(obuf);
 592: }
 593: 
 594: /*
 595:  * Pipe the message through the command.
 596:  * Old message is on stdin of command;
 597:  * New message collected from stdout.
 598:  * Sh -c must return 0 to accept the new message.
 599:  */
 600: 
 601: FILE *
 602: mespipe(ibuf, obuf, cmd)
 603:     FILE *ibuf, *obuf;
 604:     char cmd[];
 605: {
 606:     register FILE *ni, *no;
 607:     int pid, s;
 608:     int (*savesig)();
 609:     char *Shell;
 610: 
 611:     newi = ibuf;
 612:     if ((no = fopen(tempEdit, "w")) == NULL) {
 613:         perror(tempEdit);
 614:         return(obuf);
 615:     }
 616:     if ((ni = fopen(tempEdit, "r")) == NULL) {
 617:         perror(tempEdit);
 618:         fclose(no);
 619:         remove(tempEdit);
 620:         return(obuf);
 621:     }
 622:     remove(tempEdit);
 623:     savesig = sigset(SIGINT, SIG_IGN);
 624:     fflush(obuf);
 625:     rewind(ibuf);
 626:     if ((Shell = value("SHELL")) == NULL)
 627:         Shell = "/bin/sh";
 628:     if ((pid = vfork()) == -1) {
 629:         perror("fork");
 630:         goto err;
 631:     }
 632:     if (pid == 0) {
 633:         /*
 634: 		 * stdin = current message.
 635: 		 * stdout = new message.
 636: 		 */
 637: 
 638:         sigchild();
 639:         close(0);
 640:         dup(fileno(ibuf));
 641:         close(1);
 642:         dup(fileno(no));
 643:         for (s = 4; s < 15; s++)
 644:             close(s);
 645:         execl(Shell, Shell, "-c", cmd, 0);
 646:         perror(Shell);
 647:         _exit(1);
 648:     }
 649:     while (wait(&s) != pid)
 650:         ;
 651:     if (s != 0 || pid == -1) {
 652:         fprintf(stderr, "\"%s\" failed!?\n", cmd);
 653:         goto err;
 654:     }
 655:     if (fsize(ni) == 0) {
 656:         fprintf(stderr, "No bytes from \"%s\" !?\n", cmd);
 657:         goto err;
 658:     }
 659: 
 660:     /*
 661: 	 * Take new files.
 662: 	 */
 663: 
 664:     newi = ni;
 665:     fclose(ibuf);
 666:     fclose(obuf);
 667:     sigset(SIGINT, savesig);
 668:     return(no);
 669: 
 670: err:
 671:     fclose(no);
 672:     fclose(ni);
 673:     sigset(SIGINT, savesig);
 674:     return(obuf);
 675: }
 676: 
 677: /*
 678:  * Interpolate the named messages into the current
 679:  * message, preceding each line with a tab.
 680:  * Return a count of the number of characters now in
 681:  * the message, or -1 if an error is encountered writing
 682:  * the message temporary.  The flag argument is 'm' if we
 683:  * should shift over and 'f' if not.
 684:  */
 685: forward(ms, obuf, f)
 686:     char ms[];
 687:     FILE *obuf;
 688: {
 689:     register int *msgvec, *ip;
 690:     extern char tempMail[];
 691: 
 692:     msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec);
 693:     if (msgvec == (int *) NOSTR)
 694:         return(0);
 695:     if (getmsglist(ms, msgvec, 0) < 0)
 696:         return(0);
 697:     if (*msgvec == NULL) {
 698:         *msgvec = first(0, MMNORM);
 699:         if (*msgvec == NULL) {
 700:             printf("No appropriate messages\n");
 701:             return(0);
 702:         }
 703:         msgvec[1] = NULL;
 704:     }
 705:     printf("Interpolating:");
 706:     for (ip = msgvec; *ip != NULL; ip++) {
 707:         touch(*ip);
 708:         printf(" %d", *ip);
 709:         if (f == 'm') {
 710:             if (transmit(&message[*ip-1], obuf) < 0L) {
 711:                 perror(tempMail);
 712:                 return(-1);
 713:             }
 714:         } else
 715:             if (send(&message[*ip-1], obuf, 0) < 0) {
 716:                 perror(tempMail);
 717:                 return(-1);
 718:             }
 719:     }
 720:     printf("\n");
 721:     return(0);
 722: }
 723: 
 724: /*
 725:  * Send message described by the passed pointer to the
 726:  * passed output buffer.  Insert a tab in front of each
 727:  * line.  Return a count of the characters sent, or -1
 728:  * on error.
 729:  */
 730: 
 731: long
 732: transmit(mailp, obuf)
 733:     struct message *mailp;
 734:     FILE *obuf;
 735: {
 736:     register struct message *mp;
 737:     register int ch;
 738:     long c, n;
 739:     int bol;
 740:     FILE *ibuf;
 741: 
 742:     mp = mailp;
 743:     ibuf = setinput(mp);
 744:     c = mp->m_size;
 745:     n = c;
 746:     bol = 1;
 747:     while (c-- > 0L) {
 748:         if (bol) {
 749:             bol = 0;
 750:             putc('\t', obuf);
 751:             n++;
 752:             if (ferror(obuf)) {
 753:                 perror("/tmp");
 754:                 return(-1L);
 755:             }
 756:         }
 757:         ch = getc(ibuf);
 758:         if (ch == '\n')
 759:             bol++;
 760:         putc(ch, obuf);
 761:         if (ferror(obuf)) {
 762:             perror("/tmp");
 763:             return(-1L);
 764:         }
 765:     }
 766:     return(n);
 767: }
 768: 
 769: /*
 770:  * Print (continue) when continued after ^Z.
 771:  */
 772: collcont(s)
 773: {
 774: 
 775:     printf("(continue)\n");
 776:     fflush(stdout);
 777: }
 778: 
 779: /*
 780:  * On interrupt, go here to save the partial
 781:  * message on ~/dead.letter.
 782:  * Then restore signals and execute the normal
 783:  * signal routine.  We only come here if signals
 784:  * were previously set anyway.
 785:  */
 786: 
 787: # ifndef VMUNIX
 788: collintsig()
 789: {
 790:     signal(SIGINT, SIG_IGN);
 791:     collrub(SIGINT);
 792: }
 793: 
 794: collhupsig()
 795: {
 796:     signal(SIGHUP, SIG_IGN);
 797:     collrub(SIGHUP);
 798: }
 799: # endif VMUNIX
 800: 
 801: collrub(s)
 802: {
 803:     register FILE *dbuf;
 804:     register int c;
 805: 
 806:     if (s == SIGINT && hadintr == 0) {
 807:         hadintr++;
 808:         fflush(stdout);
 809:         fprintf(stderr, "\n(Interrupt -- one more to kill letter)\n");
 810:         longjmp(coljmp, 1);
 811:     }
 812:     fclose(newo);
 813:     rewind(newi);
 814:     if (s == SIGINT && value("nosave") != NOSTR || fsize(newi) == 0)
 815:         goto done;
 816:     if ((dbuf = fopen(deadletter, "w")) == NULL)
 817:         goto done;
 818:     chmod(deadletter, 0600);
 819:     while ((c = getc(newi)) != EOF)
 820:         putc(c, dbuf);
 821:     fclose(dbuf);
 822: 
 823: done:
 824:     fclose(newi);
 825:     sigset(SIGINT, savesig);
 826:     sigset(SIGHUP, savehup);
 827: # ifdef VMUNIX
 828:     sigset(SIGCONT, savecont);
 829: # endif VMUNIX
 830:     if (rcvmode) {
 831:         if (s == SIGHUP)
 832:             hangup(SIGHUP);
 833:         else
 834:             stop(s);
 835:     }
 836:     else
 837:         exit(1);
 838: }
 839: 
 840: /*
 841:  * Acknowledge an interrupt signal from the tty by typing an @
 842:  */
 843: 
 844: intack(s)
 845: {
 846: 
 847:     puts("@");
 848:     fflush(stdout);
 849:     clearerr(stdin);
 850: }
 851: 
 852: /*
 853:  * Add a string to the end of a header entry field.
 854:  */
 855: 
 856: char *
 857: addto(hf, news)
 858:     char hf[], news[];
 859: {
 860:     register char *cp, *cp2, *linebuf;
 861: 
 862:     if (hf == NOSTR)
 863:         hf = "";
 864:     if (*news == '\0')
 865:         return(hf);
 866:     linebuf = salloc(strlen(hf) + strlen(news) + 2);
 867:     for (cp = hf; any(*cp, " \t"); cp++)
 868:         ;
 869:     for (cp2 = linebuf; *cp;)
 870:         *cp2++ = *cp++;
 871:     *cp2++ = ' ';
 872:     for (cp = news; any(*cp, " \t"); cp++)
 873:         ;
 874:     while (*cp != '\0')
 875:         *cp2++ = *cp++;
 876:     *cp2 = '\0';
 877:     return(linebuf);
 878: }

Defined functions

addto defined in line 856; used 4 times
collcont defined in line 772; used 2 times
collect defined in line 46; used 2 times
collhupsig defined in line 794; used 2 times
collintsig defined in line 788; used 2 times
collrub defined in line 801; used 6 times
exwrite defined in line 449; used 3 times
forward defined in line 685; used 1 times
intack defined in line 844; used 3 times
mesedit defined in line 500; used 2 times
mespipe defined in line 601; used 2 times
psig defined in line 436; never used
transmit defined in line 731; used 2 times

Defined variables

coljmp defined in line 44; used 2 times
hadintr defined in line 42; used 5 times
hf defined in line 41; used 11 times
sccsid defined in line 8; never used
Last modified: 1985-06-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1945
Valid CSS Valid XHTML 1.0 Strict