Annotation of researchv10no/lbin/mailx/collect.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.