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

Defined functions

addto defined in line 848; used 4 times
collcont defined in line 761; used 2 times
collect defined in line 40; used 2 times
collhupsig defined in line 783; used 2 times
collintsig defined in line 777; used 2 times
collrub defined in line 790; used 6 times
exwrite defined in line 438; used 3 times
forward defined in line 674; used 1 times
intack defined in line 836; used 3 times
mesedit defined in line 489; used 2 times
mespipe defined in line 590; used 2 times
psig defined in line 425; never used
transmit defined in line 720; used 2 times

Defined variables

SccsId defined in line 10; never used
coljmp defined in line 38; used 2 times
hadintr defined in line 36; used 5 times
hf defined in line 35; used 11 times
Last modified: 1983-07-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1698
Valid CSS Valid XHTML 1.0 Strict