Annotation of researchv10no/lbin/mailx/collect.c, revision 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.