[BACK]Return to collect.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mail

Annotation of src/usr.bin/mail/collect.c, Revision 1.26

1.26    ! avsm        1: /*     $OpenBSD: collect.c,v 1.25 2003/06/03 02:56:11 millert Exp $    */
1.6       millert     2: /*     $NetBSD: collect.c,v 1.9 1997/07/09 05:25:45 mikel Exp $        */
1.2       deraadt     3:
1.1       deraadt     4: /*
                      5:  * Copyright (c) 1980, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
1.25      millert    16:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: #ifndef lint
1.2       deraadt    34: #if 0
1.23      millert    35: static const char sccsid[] = "@(#)collect.c    8.2 (Berkeley) 4/19/94";
1.2       deraadt    36: #else
1.26    ! avsm       37: static const char rcsid[] = "$OpenBSD: collect.c,v 1.25 2003/06/03 02:56:11 millert Exp $";
1.2       deraadt    38: #endif
1.1       deraadt    39: #endif /* not lint */
                     40:
                     41: /*
                     42:  * Mail -- a mail program
                     43:  *
                     44:  * Collect input from standard input, handling
                     45:  * ~ escapes.
                     46:  */
                     47:
                     48: #include "rcv.h"
                     49: #include "extern.h"
                     50:
                     51: /*
                     52:  * Read a message from standard output and return a read file to it
                     53:  * or NULL on error.
                     54:  */
                     55:
                     56: /*
                     57:  * The following hokiness with global variables is so that on
                     58:  * receipt of an interrupt signal, the partial message can be salted
                     59:  * away on dead.letter.
                     60:  */
                     61: static FILE    *collf;                 /* File for saving away */
                     62: static int     hadintr;                /* Have seen one SIGINT so far */
                     63:
                     64: FILE *
1.23      millert    65: collect(struct header *hp, int printheaders)
1.1       deraadt    66: {
                     67:        FILE *fbuf;
1.22      millert    68:        int lc, cc, fd, c, t, lastlong, rc, sig;
                     69:        int escape, eofcount, longline;
                     70:        char getsub;
1.21      millert    71:        char linebuf[LINESIZE], tempname[PATHSIZE], *cp;
1.1       deraadt    72:
                     73:        collf = NULL;
1.22      millert    74:        eofcount = 0;
                     75:        hadintr = 0;
                     76:        lastlong = 0;
                     77:        longline = 0;
                     78:        if ((cp = value("escape")) != NULL)
                     79:                escape = *cp;
                     80:        else
                     81:                escape = ESCAPE;
                     82:        noreset++;
1.1       deraadt    83:
1.12      millert    84:        (void)snprintf(tempname, sizeof(tempname),
                     85:            "%s/mail.RsXXXXXXXXXX", tmpdir);
                     86:        if ((fd = mkstemp(tempname)) == -1 ||
                     87:            (collf = Fdopen(fd, "w+")) == NULL) {
1.19      millert    88:                warn("%s", tempname);
1.1       deraadt    89:                goto err;
                     90:        }
1.12      millert    91:        (void)rm(tempname);
1.1       deraadt    92:
                     93:        /*
                     94:         * If we are going to prompt for a subject,
                     95:         * refrain from printing a newline after
                     96:         * the headers (since some people mind).
                     97:         */
                     98:        t = GTO|GSUBJECT|GCC|GNL;
                     99:        getsub = 0;
1.8       millert   100:        if (hp->h_subject == NULL && value("interactive") != NULL &&
                    101:            (value("ask") != NULL || value("asksub") != NULL))
1.1       deraadt   102:                t &= ~GNL, getsub++;
                    103:        if (printheaders) {
                    104:                puthead(hp, stdout, t);
                    105:                fflush(stdout);
                    106:        }
1.22      millert   107:        if (getsub && gethfromtty(hp, GSUBJECT) == -1)
                    108:                goto err;
1.1       deraadt   109:
1.22      millert   110:        if (0) {
1.1       deraadt   111: cont:
1.22      millert   112:                /* Come here for printing the after-suspend message. */
                    113:                if (isatty(0)) {
                    114:                        puts("(continue)");
1.1       deraadt   115:                        fflush(stdout);
                    116:                }
                    117:        }
                    118:        for (;;) {
1.22      millert   119:                c = readline(stdin, linebuf, LINESIZE, &sig);
                    120:
                    121:                /* Act on any signal caught during readline() ignoring 'c' */
                    122:                switch (sig) {
                    123:                case 0:
                    124:                        break;
                    125:                case SIGINT:
                    126:                        if (collabort())
                    127:                                goto err;
                    128:                        continue;
                    129:                case SIGHUP:
                    130:                        rewind(collf);
                    131:                        savedeadletter(collf);
                    132:                        /*
                    133:                         * Let's pretend nobody else wants to clean up,
                    134:                         * a true statement at this time.
                    135:                         */
                    136:                        exit(1);
                    137:                default:
                    138:                        /* Stopped due to job control */
                    139:                        (void)kill(0, sig);
                    140:                        goto cont;
                    141:                }
                    142:
                    143:                /* No signal, check for error */
1.1       deraadt   144:                if (c < 0) {
1.8       millert   145:                        if (value("interactive") != NULL &&
                    146:                            value("ignoreeof") != NULL && ++eofcount < 25) {
1.6       millert   147:                                puts("Use \".\" to terminate letter");
1.1       deraadt   148:                                continue;
                    149:                        }
                    150:                        break;
                    151:                }
1.6       millert   152:                lastlong = longline;
                    153:                longline = (c == LINESIZE - 1);
1.1       deraadt   154:                eofcount = 0;
                    155:                hadintr = 0;
                    156:                if (linebuf[0] == '.' && linebuf[1] == '\0' &&
1.8       millert   157:                    value("interactive") != NULL && !lastlong &&
                    158:                    (value("dot") != NULL || value("ignoreeof") != NULL))
1.1       deraadt   159:                        break;
1.24      millert   160:                if (linebuf[0] != escape || value("interactive") == NULL ||
                    161:                    lastlong) {
1.6       millert   162:                        if (putline(collf, linebuf, !longline) < 0)
1.1       deraadt   163:                                goto err;
                    164:                        continue;
                    165:                }
                    166:                c = linebuf[1];
                    167:                switch (c) {
                    168:                default:
                    169:                        /*
                    170:                         * On double escape, just send the single one.
                    171:                         * Otherwise, it's an error.
                    172:                         */
                    173:                        if (c == escape) {
1.6       millert   174:                                if (putline(collf, &linebuf[1], !longline) < 0)
1.1       deraadt   175:                                        goto err;
                    176:                                else
                    177:                                        break;
                    178:                        }
1.6       millert   179:                        puts("Unknown tilde escape.");
1.1       deraadt   180:                        break;
                    181:                case 'C':
                    182:                        /*
                    183:                         * Dump core.
                    184:                         */
1.2       deraadt   185:                        core(NULL);
1.1       deraadt   186:                        break;
                    187:                case '!':
                    188:                        /*
                    189:                         * Shell escape, send the balance of the
                    190:                         * line to sh -c.
                    191:                         */
                    192:                        shell(&linebuf[2]);
                    193:                        break;
                    194:                case ':':
                    195:                case '_':
                    196:                        /*
                    197:                         * Escape to command mode, but be nice!
                    198:                         */
                    199:                        execute(&linebuf[2], 1);
                    200:                        goto cont;
                    201:                case '.':
                    202:                        /*
                    203:                         * Simulate end of file on input.
                    204:                         */
                    205:                        goto out;
                    206:                case 'q':
                    207:                        /*
                    208:                         * Force a quit of sending mail.
                    209:                         * Act like an interrupt happened.
                    210:                         */
                    211:                        hadintr++;
1.22      millert   212:                        collabort();
                    213:                        fputs("Interrupt\n", stderr);
                    214:                        goto err;
1.1       deraadt   215:                case 'h':
                    216:                        /*
                    217:                         * Grab a bunch of headers.
                    218:                         */
                    219:                        grabh(hp, GTO|GSUBJECT|GCC|GBCC);
                    220:                        goto cont;
                    221:                case 't':
                    222:                        /*
                    223:                         * Add to the To list.
                    224:                         */
                    225:                        hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO));
                    226:                        break;
                    227:                case 's':
                    228:                        /*
                    229:                         * Set the Subject list.
                    230:                         */
                    231:                        cp = &linebuf[2];
                    232:                        while (isspace(*cp))
                    233:                                cp++;
                    234:                        hp->h_subject = savestr(cp);
                    235:                        break;
                    236:                case 'c':
                    237:                        /*
                    238:                         * Add to the CC list.
                    239:                         */
                    240:                        hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC));
                    241:                        break;
                    242:                case 'b':
                    243:                        /*
                    244:                         * Add stuff to blind carbon copies list.
                    245:                         */
                    246:                        hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC));
                    247:                        break;
                    248:                case 'd':
1.23      millert   249:                        linebuf[2] = '\0';
                    250:                        strlcat(linebuf, getdeadletter(), sizeof(linebuf));
1.1       deraadt   251:                        /* fall into . . . */
                    252:                case 'r':
                    253:                case '<':
                    254:                        /*
                    255:                         * Invoke a file:
                    256:                         * Search for the file name,
                    257:                         * then open it and copy the contents to collf.
                    258:                         */
                    259:                        cp = &linebuf[2];
                    260:                        while (isspace(*cp))
                    261:                                cp++;
                    262:                        if (*cp == '\0') {
1.6       millert   263:                                puts("Interpolate what file?");
1.1       deraadt   264:                                break;
                    265:                        }
                    266:                        cp = expand(cp);
1.8       millert   267:                        if (cp == NULL)
1.1       deraadt   268:                                break;
                    269:                        if (isdir(cp)) {
                    270:                                printf("%s: Directory\n", cp);
                    271:                                break;
                    272:                        }
                    273:                        if ((fbuf = Fopen(cp, "r")) == NULL) {
1.19      millert   274:                                warn("%s", cp);
1.1       deraadt   275:                                break;
                    276:                        }
                    277:                        printf("\"%s\" ", cp);
                    278:                        fflush(stdout);
                    279:                        lc = 0;
                    280:                        cc = 0;
1.22      millert   281:                        while ((rc = readline(fbuf, linebuf, LINESIZE, NULL)) >= 0) {
1.6       millert   282:                                if (rc != LINESIZE - 1)
                    283:                                        lc++;
                    284:                                if ((t = putline(collf, linebuf,
                    285:                                                 rc != LINESIZE-1)) < 0) {
                    286:                                        (void)Fclose(fbuf);
1.1       deraadt   287:                                        goto err;
                    288:                                }
                    289:                                cc += t;
                    290:                        }
1.6       millert   291:                        (void)Fclose(fbuf);
1.1       deraadt   292:                        printf("%d/%d\n", lc, cc);
                    293:                        break;
                    294:                case 'w':
                    295:                        /*
                    296:                         * Write the message on a file.
                    297:                         */
                    298:                        cp = &linebuf[2];
                    299:                        while (*cp == ' ' || *cp == '\t')
                    300:                                cp++;
                    301:                        if (*cp == '\0') {
1.6       millert   302:                                fputs("Write what file!?\n", stderr);
1.1       deraadt   303:                                break;
                    304:                        }
1.8       millert   305:                        if ((cp = expand(cp)) == NULL)
1.1       deraadt   306:                                break;
                    307:                        rewind(collf);
                    308:                        exwrite(cp, collf, 1);
                    309:                        break;
                    310:                case 'm':
                    311:                case 'M':
                    312:                case 'f':
                    313:                case 'F':
                    314:                        /*
                    315:                         * Interpolate the named messages, if we
                    316:                         * are in receiving mail mode.  Does the
                    317:                         * standard list processing garbage.
                    318:                         * If ~f is given, we don't shift over.
                    319:                         */
1.12      millert   320:                        if (forward(linebuf + 2, collf, tempname, c) < 0)
1.1       deraadt   321:                                goto err;
                    322:                        goto cont;
                    323:                case '?':
                    324:                        if ((fbuf = Fopen(_PATH_TILDE, "r")) == NULL) {
1.6       millert   325:                                warn(_PATH_TILDE);
1.1       deraadt   326:                                break;
                    327:                        }
                    328:                        while ((t = getc(fbuf)) != EOF)
1.7       millert   329:                                (void)putchar(t);
1.6       millert   330:                        (void)Fclose(fbuf);
1.1       deraadt   331:                        break;
                    332:                case 'p':
                    333:                        /*
                    334:                         * Print out the current state of the
                    335:                         * message without altering anything.
                    336:                         */
                    337:                        rewind(collf);
1.6       millert   338:                        puts("-------\nMessage contains:");
1.1       deraadt   339:                        puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL);
                    340:                        while ((t = getc(collf)) != EOF)
1.7       millert   341:                                (void)putchar(t);
1.1       deraadt   342:                        goto cont;
                    343:                case '|':
                    344:                        /*
                    345:                         * Pipe message through command.
                    346:                         * Collect output as new message.
                    347:                         */
                    348:                        rewind(collf);
                    349:                        mespipe(collf, &linebuf[2]);
                    350:                        goto cont;
                    351:                case 'v':
                    352:                case 'e':
                    353:                        /*
                    354:                         * Edit the current message.
                    355:                         * 'e' means to use EDITOR
                    356:                         * 'v' means to use VISUAL
                    357:                         */
                    358:                        rewind(collf);
                    359:                        mesedit(collf, c);
                    360:                        goto cont;
                    361:                }
                    362:        }
1.11      millert   363:
                    364:        if (value("interactive") != NULL) {
                    365:                if (value("askcc") != NULL || value("askbcc") != NULL) {
1.22      millert   366:                        if (value("askcc") != NULL) {
                    367:                                if (gethfromtty(hp, GCC) == -1)
                    368:                                        goto err;
                    369:                        }
                    370:                        if (value("askbcc") != NULL) {
                    371:                                if (gethfromtty(hp, GBCC) == -1)
                    372:                                        goto err;
                    373:                        }
1.11      millert   374:                } else {
                    375:                        puts("EOT");
                    376:                        (void)fflush(stdout);
                    377:                }
                    378:        }
1.1       deraadt   379:        goto out;
                    380: err:
                    381:        if (collf != NULL) {
1.6       millert   382:                (void)Fclose(collf);
1.1       deraadt   383:                collf = NULL;
                    384:        }
                    385: out:
                    386:        if (collf != NULL)
                    387:                rewind(collf);
                    388:        noreset--;
1.6       millert   389:        return(collf);
1.1       deraadt   390: }
                    391:
                    392: /*
                    393:  * Write a file, ex-like if f set.
                    394:  */
                    395: int
1.23      millert   396: exwrite(char *name, FILE *fp, int f)
1.1       deraadt   397: {
1.15      millert   398:        FILE *of;
                    399:        int c;
1.11      millert   400:        ssize_t cc, lc;
1.1       deraadt   401:        struct stat junk;
                    402:
                    403:        if (f) {
                    404:                printf("\"%s\" ", name);
                    405:                fflush(stdout);
                    406:        }
1.15      millert   407:        if (stat(name, &junk) >= 0 && S_ISREG(junk.st_mode)) {
1.1       deraadt   408:                if (!f)
                    409:                        fprintf(stderr, "%s: ", name);
1.6       millert   410:                fputs("File exists\n", stderr);
1.1       deraadt   411:                return(-1);
                    412:        }
                    413:        if ((of = Fopen(name, "w")) == NULL) {
1.8       millert   414:                warn(NULL);
1.1       deraadt   415:                return(-1);
                    416:        }
                    417:        lc = 0;
                    418:        cc = 0;
                    419:        while ((c = getc(fp)) != EOF) {
                    420:                cc++;
                    421:                if (c == '\n')
                    422:                        lc++;
1.7       millert   423:                (void)putc(c, of);
1.1       deraadt   424:                if (ferror(of)) {
1.19      millert   425:                        warn("%s", name);
1.6       millert   426:                        (void)Fclose(of);
1.1       deraadt   427:                        return(-1);
                    428:                }
                    429:        }
1.6       millert   430:        (void)Fclose(of);
1.11      millert   431:        printf("%d/%d\n", lc, cc);
1.1       deraadt   432:        fflush(stdout);
                    433:        return(0);
                    434: }
                    435:
                    436: /*
                    437:  * Edit the message being collected on fp.
                    438:  * On return, make the edit file the new temp file.
                    439:  */
                    440: void
1.23      millert   441: mesedit(FILE *fp, int c)
1.1       deraadt   442: {
1.22      millert   443:        FILE *nf;
                    444:        struct sigaction oact;
                    445:        sigset_t oset;
1.1       deraadt   446:
1.22      millert   447:        (void)ignoresig(SIGINT, &oact, &oset);
                    448:        nf = run_editor(fp, (off_t)-1, c, 0);
1.1       deraadt   449:        if (nf != NULL) {
                    450:                fseek(nf, 0L, 2);
                    451:                collf = nf;
1.6       millert   452:                (void)Fclose(fp);
1.1       deraadt   453:        }
1.22      millert   454:        (void)sigprocmask(SIG_SETMASK, &oset, NULL);
                    455:        (void)sigaction(SIGINT, &oact, NULL);
1.1       deraadt   456: }
                    457:
                    458: /*
                    459:  * Pipe the message through the command.
                    460:  * Old message is on stdin of command;
                    461:  * New message collected from stdout.
                    462:  * Sh -c must return 0 to accept the new message.
                    463:  */
                    464: void
1.23      millert   465: mespipe(FILE *fp, char *cmd)
1.1       deraadt   466: {
                    467:        FILE *nf;
1.12      millert   468:        int fd;
                    469:        char *shell, tempname[PATHSIZE];
1.22      millert   470:        struct sigaction oact;
                    471:        sigset_t oset;
1.1       deraadt   472:
1.22      millert   473:        (void)ignoresig(SIGINT, &oact, &oset);
1.12      millert   474:        (void)snprintf(tempname, sizeof(tempname),
                    475:            "%s/mail.ReXXXXXXXXXX", tmpdir);
                    476:        if ((fd = mkstemp(tempname)) == -1 ||
                    477:            (nf = Fdopen(fd, "w+")) == NULL) {
1.19      millert   478:                warn("%s", tempname);
1.1       deraadt   479:                goto out;
                    480:        }
1.12      millert   481:        (void)rm(tempname);
1.1       deraadt   482:        /*
                    483:         * stdin = current message.
                    484:         * stdout = new message.
                    485:         */
1.20      millert   486:        shell = value("SHELL");
1.1       deraadt   487:        if (run_command(shell,
1.8       millert   488:            0, fileno(fp), fileno(nf), "-c", cmd, NULL) < 0) {
1.6       millert   489:                (void)Fclose(nf);
1.1       deraadt   490:                goto out;
                    491:        }
                    492:        if (fsize(nf) == 0) {
                    493:                fprintf(stderr, "No bytes from \"%s\" !?\n", cmd);
1.6       millert   494:                (void)Fclose(nf);
1.1       deraadt   495:                goto out;
                    496:        }
                    497:        /*
                    498:         * Take new files.
                    499:         */
1.7       millert   500:        (void)fseek(nf, 0L, 2);
1.1       deraadt   501:        collf = nf;
1.6       millert   502:        (void)Fclose(fp);
1.1       deraadt   503: out:
1.22      millert   504:        (void)sigprocmask(SIG_SETMASK, &oset, NULL);
                    505:        (void)sigaction(SIGINT, &oact, NULL);
1.1       deraadt   506: }
                    507:
                    508: /*
                    509:  * Interpolate the named messages into the current
                    510:  * message, preceding each line with a tab.
                    511:  * Return a count of the number of characters now in
                    512:  * the message, or -1 if an error is encountered writing
                    513:  * the message temporary.  The flag argument is 'm' if we
                    514:  * should shift over and 'f' if not.
                    515:  */
                    516: int
1.23      millert   517: forward(char *ms, FILE *fp, char *fn, int f)
1.1       deraadt   518: {
1.15      millert   519:        int *msgvec;
1.1       deraadt   520:        struct ignoretab *ig;
                    521:        char *tabst;
                    522:
1.7       millert   523:        msgvec = (int *)salloc((msgCount+1) * sizeof(*msgvec));
1.8       millert   524:        if (msgvec == NULL)
1.1       deraadt   525:                return(0);
                    526:        if (getmsglist(ms, msgvec, 0) < 0)
                    527:                return(0);
                    528:        if (*msgvec == 0) {
                    529:                *msgvec = first(0, MMNORM);
1.26    ! avsm      530:                if (*msgvec == 0) {
1.6       millert   531:                        puts("No appropriate messages");
1.1       deraadt   532:                        return(0);
                    533:                }
                    534:                msgvec[1] = NULL;
                    535:        }
                    536:        if (f == 'f' || f == 'F')
1.8       millert   537:                tabst = NULL;
                    538:        else if ((tabst = value("indentprefix")) == NULL)
1.1       deraadt   539:                tabst = "\t";
                    540:        ig = isupper(f) ? NULL : ignore;
1.6       millert   541:        fputs("Interpolating:", stdout);
1.1       deraadt   542:        for (; *msgvec != 0; msgvec++) {
                    543:                struct message *mp = message + *msgvec - 1;
                    544:
                    545:                touch(mp);
                    546:                printf(" %d", *msgvec);
1.18      millert   547:                if (sendmessage(mp, fp, ig, tabst) < 0) {
1.19      millert   548:                        warn("%s", fn);
1.1       deraadt   549:                        return(-1);
                    550:                }
                    551:        }
1.6       millert   552:        putchar('\n');
1.1       deraadt   553:        return(0);
                    554: }
                    555:
                    556: /*
1.22      millert   557:  * User aborted during message composition.
                    558:  * Save the partial message in ~/dead.letter.
1.1       deraadt   559:  */
1.22      millert   560: int
1.23      millert   561: collabort(void)
1.1       deraadt   562: {
                    563:        /*
                    564:         * the control flow is subtle, because we can be called from ~q.
                    565:         */
1.5       deraadt   566:        if (hadintr == 0 && isatty(0)) {
1.8       millert   567:                if (value("ignore") != NULL) {
1.1       deraadt   568:                        puts("@");
                    569:                        fflush(stdout);
                    570:                        clearerr(stdin);
1.22      millert   571:                } else {
                    572:                        fflush(stdout);
                    573:                        fputs("\n(Interrupt -- one more to kill letter)\n",
                    574:                            stderr);
                    575:                        hadintr++;
1.1       deraadt   576:                }
1.22      millert   577:                return(0);
1.1       deraadt   578:        }
1.22      millert   579:        fflush(stdout);
1.1       deraadt   580:        rewind(collf);
1.8       millert   581:        if (value("nosave") == NULL)
1.1       deraadt   582:                savedeadletter(collf);
1.22      millert   583:        return(1);
1.1       deraadt   584: }
                    585:
                    586: void
1.23      millert   587: savedeadletter(FILE *fp)
1.1       deraadt   588: {
1.15      millert   589:        FILE *dbuf;
                    590:        int c;
1.1       deraadt   591:        char *cp;
                    592:
                    593:        if (fsize(fp) == 0)
                    594:                return;
                    595:        cp = getdeadletter();
                    596:        c = umask(077);
                    597:        dbuf = Fopen(cp, "a");
1.7       millert   598:        (void)umask(c);
1.1       deraadt   599:        if (dbuf == NULL)
                    600:                return;
                    601:        while ((c = getc(fp)) != EOF)
1.7       millert   602:                (void)putc(c, dbuf);
1.6       millert   603:        (void)Fclose(dbuf);
1.1       deraadt   604:        rewind(fp);
1.11      millert   605: }
                    606:
1.22      millert   607: int
1.23      millert   608: gethfromtty(struct header *hp, int gflags)
1.11      millert   609: {
1.22      millert   610:
                    611:        hadintr = 0;
                    612:        while (grabh(hp, gflags) != 0) {
                    613:                if (collabort())
                    614:                        return(-1);
1.11      millert   615:        }
1.22      millert   616:        return(0);
1.1       deraadt   617: }