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

Annotation of src/usr.bin/mail/send.c, Revision 1.23

1.23    ! okan        1: /*     $OpenBSD: send.c,v 1.22 2009/10/27 23:59:40 deraadt Exp $       */
1.2       deraadt     2: /*     $NetBSD: send.c,v 1.6 1996/06/08 19:48:39 christos Exp $        */
                      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.17      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: #include "rcv.h"
                     34: #include "extern.h"
                     35:
1.15      millert    36: static volatile sig_atomic_t sendsignal;       /* Interrupted by a signal? */
                     37:
1.1       deraadt    38: /*
                     39:  * Mail -- a mail program
                     40:  *
                     41:  * Mail to others.
                     42:  */
                     43:
                     44: /*
                     45:  * Send message described by the passed pointer to the
                     46:  * passed output buffer.  Return -1 on error.
                     47:  * Adjust the status: field if need be.
                     48:  * If doign is given, suppress ignored header fields.
                     49:  * prefix is a string to prepend to each output line.
                     50:  */
                     51: int
1.14      millert    52: sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
                     53:            char *prefix)
1.1       deraadt    54: {
1.7       millert    55:        int count;
1.9       millert    56:        FILE *ibuf;
1.1       deraadt    57:        char line[LINESIZE];
1.16      pjanzen    58:        char visline[4 * LINESIZE - 3];
1.2       deraadt    59:        int ishead, infld, ignoring = 0, dostat, firstline;
1.9       millert    60:        char *cp, *cp2;
                     61:        int c = 0;
1.1       deraadt    62:        int length;
1.2       deraadt    63:        int prefixlen = 0;
1.15      millert    64:        int rval;
1.16      pjanzen    65:        int dovis;
1.15      millert    66:        struct sigaction act, saveint;
                     67:        sigset_t oset;
                     68:
                     69:        sendsignal = 0;
                     70:        rval = -1;
1.16      pjanzen    71:        dovis = isatty(fileno(obuf));
1.15      millert    72:        sigemptyset(&act.sa_mask);
                     73:        act.sa_flags = SA_RESTART;
                     74:        act.sa_handler = sendint;
                     75:        (void)sigaction(SIGINT, &act, &saveint);
                     76:        (void)sigprocmask(SIG_UNBLOCK, &intset, &oset);
1.1       deraadt    77:
                     78:        /*
                     79:         * Compute the prefix string, without trailing whitespace
                     80:         */
1.5       millert    81:        if (prefix != NULL) {
1.1       deraadt    82:                cp2 = 0;
                     83:                for (cp = prefix; *cp; cp++)
                     84:                        if (*cp != ' ' && *cp != '\t')
                     85:                                cp2 = cp;
                     86:                prefixlen = cp2 == 0 ? 0 : cp2 - prefix + 1;
                     87:        }
                     88:        ibuf = setinput(mp);
                     89:        count = mp->m_size;
                     90:        ishead = 1;
                     91:        dostat = doign == 0 || !isign("status", doign);
                     92:        infld = 0;
                     93:        firstline = 1;
                     94:        /*
                     95:         * Process headers first
                     96:         */
                     97:        while (count > 0 && ishead) {
1.3       millert    98:                if (fgets(line, sizeof(line), ibuf) == NULL)
1.1       deraadt    99:                        break;
                    100:                count -= length = strlen(line);
                    101:                if (firstline) {
1.3       millert   102:                        /*
1.1       deraadt   103:                         * First line is the From line, so no headers
                    104:                         * there to worry about
                    105:                         */
                    106:                        firstline = 0;
                    107:                        ignoring = doign == ignoreall;
                    108:                } else if (line[0] == '\n') {
                    109:                        /*
                    110:                         * If line is blank, we've reached end of
                    111:                         * headers, so force out status: field
                    112:                         * and note that we are no longer in header
                    113:                         * fields
                    114:                         */
                    115:                        if (dostat) {
1.15      millert   116:                                if (statusput(mp, obuf, prefix) == -1)
                    117:                                        goto out;
1.1       deraadt   118:                                dostat = 0;
                    119:                        }
                    120:                        ishead = 0;
                    121:                        ignoring = doign == ignoreall;
                    122:                } else if (infld && (line[0] == ' ' || line[0] == '\t')) {
                    123:                        /*
                    124:                         * If this line is a continuation (via space or tab)
                    125:                         * of a previous header field, just echo it
                    126:                         * (unless the field should be ignored).
                    127:                         * In other words, nothing to do.
                    128:                         */
                    129:                } else {
                    130:                        /*
                    131:                         * Pick up the header field if we have one.
                    132:                         */
1.23    ! okan      133:                        for (cp = line;
        !           134:                            (c = (unsigned char)*cp++) && c != ':' && !isspace(c); )
1.1       deraadt   135:                                ;
                    136:                        cp2 = --cp;
1.23    ! okan      137:                        while (isspace((unsigned char)*cp++))
1.1       deraadt   138:                                ;
                    139:                        if (cp[-1] != ':') {
                    140:                                /*
                    141:                                 * Not a header line, force out status:
                    142:                                 * This happens in uucp style mail where
                    143:                                 * there are no headers at all.
                    144:                                 */
                    145:                                if (dostat) {
1.15      millert   146:                                        if (statusput(mp, obuf, prefix) == -1)
                    147:                                                goto out;
1.1       deraadt   148:                                        dostat = 0;
                    149:                                }
                    150:                                if (doign != ignoreall)
                    151:                                        /* add blank line */
1.4       millert   152:                                        (void)putc('\n', obuf);
1.1       deraadt   153:                                ishead = 0;
                    154:                                ignoring = 0;
                    155:                        } else {
                    156:                                /*
                    157:                                 * If it is an ignored field and
                    158:                                 * we care about such things, skip it.
                    159:                                 */
                    160:                                *cp2 = 0;       /* temporarily null terminate */
                    161:                                if (doign && isign(line, doign))
                    162:                                        ignoring = 1;
1.19      martynas  163:                                else if (strcasecmp(line, "status") == 0) {
1.1       deraadt   164:                                        /*
                    165:                                         * If the field is "status," go compute
                    166:                                         * and print the real Status: field
                    167:                                         */
                    168:                                        if (dostat) {
1.15      millert   169:                                                if (statusput(mp, obuf, prefix) == -1)
                    170:                                                        goto out;
1.1       deraadt   171:                                                dostat = 0;
                    172:                                        }
                    173:                                        ignoring = 1;
                    174:                                } else {
                    175:                                        ignoring = 0;
                    176:                                        *cp2 = c;       /* restore */
                    177:                                }
                    178:                                infld = 1;
                    179:                        }
                    180:                }
                    181:                if (!ignoring) {
                    182:                        /*
                    183:                         * Strip trailing whitespace from prefix
                    184:                         * if line is blank.
                    185:                         */
1.13      millert   186:                        if (prefix != NULL) {
1.1       deraadt   187:                                if (length > 1)
                    188:                                        fputs(prefix, obuf);
                    189:                                else
1.4       millert   190:                                        (void)fwrite(prefix, sizeof(*prefix),
1.1       deraadt   191:                                                        prefixlen, obuf);
1.13      millert   192:                        }
1.16      pjanzen   193:                        if (dovis) {
                    194:                                length = strvis(visline, line, VIS_SAFE|VIS_NOSLASH);
                    195:                                (void)fwrite(visline, sizeof(*visline), length, obuf);
                    196:                        } else
                    197:                                (void)fwrite(line, sizeof(*line), length, obuf);
1.1       deraadt   198:                        if (ferror(obuf))
1.15      millert   199:                                goto out;
1.1       deraadt   200:                }
1.15      millert   201:                if (sendsignal == SIGINT)
                    202:                        goto out;
1.1       deraadt   203:        }
                    204:        /*
                    205:         * Copy out message body
                    206:         */
                    207:        if (doign == ignoreall)
                    208:                count--;                /* skip final blank line */
1.13      millert   209:        while (count > 0) {
                    210:                if (fgets(line, sizeof(line), ibuf) == NULL) {
                    211:                        c = 0;
                    212:                        break;
                    213:                }
                    214:                count -= c = strlen(line);
                    215:                if (prefix != NULL) {
1.1       deraadt   216:                        /*
                    217:                         * Strip trailing whitespace from prefix
                    218:                         * if line is blank.
                    219:                         */
                    220:                        if (c > 1)
                    221:                                fputs(prefix, obuf);
                    222:                        else
1.4       millert   223:                                (void)fwrite(prefix, sizeof(*prefix),
1.1       deraadt   224:                                                prefixlen, obuf);
                    225:                }
1.13      millert   226:                /*
                    227:                 * We can't read the record file (or inbox for recipient)
                    228:                 * properly with 'From ' lines in the message body (from
                    229:                 * forwarded messages or sentences starting with "From "),
                    230:                 * so we will prepend those lines with a '>'.
                    231:                 */
                    232:                if (strncmp(line, "From ", 5) == 0)
                    233:                        (void)fwrite(">", 1, 1, obuf); /* '>' before 'From ' */
1.16      pjanzen   234:                if (dovis) {
                    235:                        length = strvis(visline, line, VIS_SAFE|VIS_NOSLASH);
                    236:                        (void)fwrite(visline, sizeof(*visline), length, obuf);
                    237:                } else
                    238:                        (void)fwrite(line, sizeof(*line), c, obuf);
1.15      millert   239:                if (ferror(obuf) || sendsignal == SIGINT)
                    240:                        goto out;
1.13      millert   241:        }
1.1       deraadt   242:        if (doign == ignoreall && c > 0 && line[c - 1] != '\n')
                    243:                /* no final blank line */
                    244:                if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF)
1.15      millert   245:                        goto out;
                    246:        rval = 0;
                    247: out:
                    248:        sendsignal = 0;
                    249:        (void)sigprocmask(SIG_SETMASK, &oset, NULL);
                    250:        (void)sigaction(SIGINT, &saveint, NULL);
                    251:        return(rval);
1.1       deraadt   252: }
                    253:
                    254: /*
                    255:  * Output a reasonable looking status field.
                    256:  */
1.15      millert   257: int
1.14      millert   258: statusput(struct message *mp, FILE *obuf, char *prefix)
1.1       deraadt   259: {
                    260:        char statout[3];
1.9       millert   261:        char *cp = statout;
1.1       deraadt   262:
                    263:        if (mp->m_flag & MREAD)
                    264:                *cp++ = 'R';
                    265:        if ((mp->m_flag & MNEW) == 0)
                    266:                *cp++ = 'O';
                    267:        *cp = 0;
1.15      millert   268:        if (statout[0]) {
1.1       deraadt   269:                fprintf(obuf, "%sStatus: %s\n",
1.5       millert   270:                        prefix == NULL ? "" : prefix, statout);
1.15      millert   271:                return(ferror(obuf) ? -1 : 0);
                    272:        }
                    273:        return(0);
1.1       deraadt   274: }
                    275:
                    276: /*
                    277:  * Interface between the argument list and the mail1 routine
                    278:  * which does all the dirty work.
                    279:  */
                    280: int
1.14      millert   281: mail(struct name *to, struct name *cc, struct name *bcc, struct name *smopts,
                    282:      char *subject)
1.1       deraadt   283: {
                    284:        struct header head;
                    285:
                    286:        head.h_to = to;
                    287:        head.h_subject = subject;
                    288:        head.h_cc = cc;
                    289:        head.h_bcc = bcc;
                    290:        head.h_smopts = smopts;
                    291:        mail1(&head, 0);
                    292:        return(0);
                    293: }
                    294:
                    295:
                    296: /*
                    297:  * Send mail to a bunch of user names.  The interface is through
                    298:  * the mail routine below.
                    299:  */
                    300: int
1.14      millert   301: sendmail(void *v)
1.1       deraadt   302: {
1.2       deraadt   303:        char *str = v;
1.1       deraadt   304:        struct header head;
                    305:
                    306:        head.h_to = extract(str, GTO);
1.5       millert   307:        head.h_subject = NULL;
1.14      millert   308:        head.h_cc = NULL;
                    309:        head.h_bcc = NULL;
                    310:        head.h_smopts = NULL;
1.1       deraadt   311:        mail1(&head, 0);
                    312:        return(0);
                    313: }
                    314:
                    315: /*
                    316:  * Mail a message on standard input to the people indicated
                    317:  * in the passed header.  (Internal interface).
                    318:  */
                    319: void
1.14      millert   320: mail1(struct header *hp, int printheaders)
1.1       deraadt   321: {
                    322:        char *cp;
1.14      millert   323:        pid_t pid;
1.1       deraadt   324:        char **namelist;
                    325:        struct name *to;
                    326:        FILE *mtf;
                    327:
                    328:        /*
                    329:         * Collect user's mail from standard input.
                    330:         * Get the result as mtf.
                    331:         */
                    332:        if ((mtf = collect(hp, printheaders)) == NULL)
                    333:                return;
1.13      millert   334:        if (fsize(mtf) == 0) {
1.20      martynas  335:                if (value("skipempty") != NULL)
                    336:                        goto out;
1.21      martynas  337:                if (hp->h_subject == NULL || *hp->h_subject == '\0')
1.3       millert   338:                        puts("No message, no subject; hope that's ok");
1.1       deraadt   339:                else
1.3       millert   340:                        puts("Null message body; hope that's ok");
1.13      millert   341:        }
1.1       deraadt   342:        /*
                    343:         * Now, take the user names from the combined
                    344:         * to and cc lists and do all the alias
                    345:         * processing.
                    346:         */
                    347:        senderr = 0;
                    348:        to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc)));
1.14      millert   349:        if (to == NULL) {
1.3       millert   350:                puts("No recipients specified");
1.1       deraadt   351:                senderr++;
                    352:        }
                    353:        /*
                    354:         * Look through the recipient list for names with /'s
                    355:         * in them which we write to as files directly.
                    356:         */
                    357:        to = outof(to, mtf, hp);
                    358:        if (senderr)
                    359:                savedeadletter(mtf);
                    360:        to = elide(to);
                    361:        if (count(to) == 0)
                    362:                goto out;
                    363:        fixhead(hp, to);
                    364:        if ((mtf = infix(hp, mtf)) == NULL) {
1.3       millert   365:                fputs(". . . message lost, sorry.\n", stderr);
1.1       deraadt   366:                return;
                    367:        }
1.12      mickey    368:        namelist = unpack(hp->h_smopts, to);
1.1       deraadt   369:        if (debug) {
                    370:                char **t;
                    371:
1.3       millert   372:                fputs("Sendmail arguments:", stdout);
1.5       millert   373:                for (t = namelist; *t != NULL; t++)
1.1       deraadt   374:                        printf(" \"%s\"", *t);
1.3       millert   375:                putchar('\n');
1.1       deraadt   376:                goto out;
                    377:        }
1.5       millert   378:        if ((cp = value("record")) != NULL)
1.4       millert   379:                (void)savemail(expand(cp), mtf);
1.1       deraadt   380:        /*
                    381:         * Fork, set up the temporary mail file as standard
                    382:         * input for "mail", and exec with the user list we generated
                    383:         * far above.
                    384:         */
                    385:        pid = fork();
                    386:        if (pid == -1) {
1.3       millert   387:                warn("fork");
1.1       deraadt   388:                savedeadletter(mtf);
                    389:                goto out;
                    390:        }
                    391:        if (pid == 0) {
1.2       deraadt   392:                sigset_t nset;
1.6       millert   393:
1.2       deraadt   394:                sigemptyset(&nset);
                    395:                sigaddset(&nset, SIGHUP);
                    396:                sigaddset(&nset, SIGINT);
                    397:                sigaddset(&nset, SIGQUIT);
                    398:                sigaddset(&nset, SIGTSTP);
                    399:                sigaddset(&nset, SIGTTIN);
                    400:                sigaddset(&nset, SIGTTOU);
                    401:                prepare_child(&nset, fileno(mtf), -1);
1.5       millert   402:                if ((cp = value("sendmail")) != NULL)
1.1       deraadt   403:                        cp = expand(cp);
                    404:                else
                    405:                        cp = _PATH_SENDMAIL;
                    406:                execv(cp, namelist);
1.11      millert   407:                warn("%s", cp);
1.1       deraadt   408:                _exit(1);
                    409:        }
1.5       millert   410:        if (value("verbose") != NULL)
1.4       millert   411:                (void)wait_child(pid);
1.1       deraadt   412:        else
                    413:                free_child(pid);
                    414: out:
1.3       millert   415:        (void)Fclose(mtf);
1.1       deraadt   416: }
                    417:
                    418: /*
                    419:  * Fix the header by glopping all of the expanded names from
                    420:  * the distribution list into the appropriate fields.
                    421:  */
                    422: void
1.14      millert   423: fixhead(struct header *hp, struct name *tolist)
1.1       deraadt   424: {
1.9       millert   425:        struct name *np;
1.1       deraadt   426:
1.14      millert   427:        hp->h_to = NULL;
                    428:        hp->h_cc = NULL;
                    429:        hp->h_bcc = NULL;
                    430:        for (np = tolist; np != NULL; np = np->n_flink)
1.1       deraadt   431:                if ((np->n_type & GMASK) == GTO)
                    432:                        hp->h_to =
                    433:                                cat(hp->h_to, nalloc(np->n_name, np->n_type));
                    434:                else if ((np->n_type & GMASK) == GCC)
                    435:                        hp->h_cc =
                    436:                                cat(hp->h_cc, nalloc(np->n_name, np->n_type));
                    437:                else if ((np->n_type & GMASK) == GBCC)
                    438:                        hp->h_bcc =
                    439:                                cat(hp->h_bcc, nalloc(np->n_name, np->n_type));
                    440: }
                    441:
                    442: /*
                    443:  * Prepend a header in front of the collected stuff
                    444:  * and return the new file.
                    445:  */
                    446: FILE *
1.14      millert   447: infix(struct header *hp, FILE *fi)
1.1       deraadt   448: {
1.9       millert   449:        FILE *nfo, *nfi;
1.8       millert   450:        int c, fd;
                    451:        char tempname[PATHSIZE];
1.1       deraadt   452:
1.8       millert   453:        (void)snprintf(tempname, sizeof(tempname),
                    454:            "%s/mail.RsXXXXXXXXXX", tmpdir);
                    455:        if ((fd = mkstemp(tempname)) == -1 ||
                    456:            (nfo = Fdopen(fd, "w")) == NULL) {
1.11      millert   457:                warn("%s", tempname);
1.1       deraadt   458:                return(fi);
                    459:        }
1.8       millert   460:        if ((nfi = Fopen(tempname, "r")) == NULL) {
1.11      millert   461:                warn("%s", tempname);
1.3       millert   462:                (void)Fclose(nfo);
1.8       millert   463:                (void)rm(tempname);
1.1       deraadt   464:                return(fi);
                    465:        }
1.8       millert   466:        (void)rm(tempname);
1.4       millert   467:        (void)puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GNL|GCOMMA);
1.1       deraadt   468:        c = getc(fi);
                    469:        while (c != EOF) {
1.4       millert   470:                (void)putc(c, nfo);
1.1       deraadt   471:                c = getc(fi);
                    472:        }
                    473:        if (ferror(fi)) {
1.3       millert   474:                warn("read");
1.1       deraadt   475:                rewind(fi);
                    476:                return(fi);
                    477:        }
1.4       millert   478:        (void)fflush(nfo);
1.1       deraadt   479:        if (ferror(nfo)) {
1.11      millert   480:                warn("%s", tempname);
1.3       millert   481:                (void)Fclose(nfo);
                    482:                (void)Fclose(nfi);
1.1       deraadt   483:                rewind(fi);
                    484:                return(fi);
                    485:        }
1.3       millert   486:        (void)Fclose(nfo);
                    487:        (void)Fclose(fi);
1.1       deraadt   488:        rewind(nfi);
                    489:        return(nfi);
                    490: }
                    491:
                    492: /*
                    493:  * Dump the to, subject, cc header on the
                    494:  * passed file buffer.
                    495:  */
                    496: int
1.14      millert   497: puthead(struct header *hp, FILE *fo, int w)
1.1       deraadt   498: {
1.9       millert   499:        int gotcha;
1.1       deraadt   500:
                    501:        gotcha = 0;
1.14      millert   502:        if (hp->h_to != NULL && w & GTO)
1.1       deraadt   503:                fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++;
1.5       millert   504:        if (hp->h_subject != NULL && w & GSUBJECT)
1.1       deraadt   505:                fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
1.14      millert   506:        if (hp->h_cc != NULL && w & GCC)
1.1       deraadt   507:                fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++;
1.14      millert   508:        if (hp->h_bcc != NULL && w & GBCC)
1.1       deraadt   509:                fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++;
                    510:        if (gotcha && w & GNL)
1.4       millert   511:                (void)putc('\n', fo);
1.1       deraadt   512:        return(0);
                    513: }
                    514:
                    515: /*
                    516:  * Format the given header line to not exceed 72 characters.
                    517:  */
                    518: void
1.14      millert   519: fmt(char *str, struct name *np, FILE *fo, int comma)
1.1       deraadt   520: {
1.9       millert   521:        int col, len;
1.1       deraadt   522:
                    523:        comma = comma ? 1 : 0;
                    524:        col = strlen(str);
                    525:        if (col)
                    526:                fputs(str, fo);
1.14      millert   527:        for (; np != NULL; np = np->n_flink) {
                    528:                if (np->n_flink == NULL)
1.1       deraadt   529:                        comma = 0;
                    530:                len = strlen(np->n_name);
                    531:                col++;          /* for the space */
                    532:                if (col + len + comma > 72 && col > 4) {
                    533:                        fputs("\n    ", fo);
                    534:                        col = 4;
                    535:                } else
                    536:                        putc(' ', fo);
                    537:                fputs(np->n_name, fo);
                    538:                if (comma)
                    539:                        putc(',', fo);
                    540:                col += len + comma;
                    541:        }
                    542:        putc('\n', fo);
                    543: }
                    544:
                    545: /*
                    546:  * Save the outgoing mail on the passed file.
                    547:  */
                    548: /*ARGSUSED*/
                    549: int
1.14      millert   550: savemail(char *name, FILE *fi)
1.1       deraadt   551: {
1.9       millert   552:        FILE *fo;
1.1       deraadt   553:        char buf[BUFSIZ];
1.2       deraadt   554:        time_t now;
1.18      millert   555:        mode_t m;
1.1       deraadt   556:
1.18      millert   557:        m = umask(077);
                    558:        fo = Fopen(name, "a");
                    559:        (void)umask(m);
                    560:        if (fo == NULL) {
1.11      millert   561:                warn("%s", name);
1.3       millert   562:                return(-1);
1.1       deraadt   563:        }
1.4       millert   564:        (void)time(&now);
1.1       deraadt   565:        fprintf(fo, "From %s %s", myname, ctime(&now));
1.13      millert   566:        while (fgets(buf, sizeof(buf), fi) == buf) {
                    567:                /*
                    568:                 * We can't read the record file (or inbox for recipient)
                    569:                 * in the message body (from forwarded messages or sentences
                    570:                 * starting with "From "), so we will prepend those lines with
                    571:                 * a '>'.
                    572:                 */
                    573:                if (strncmp(buf, "From ", 5) == 0)
                    574:                        (void)fwrite(">", 1, 1, fo);   /* '>' before 'From ' */
                    575:                (void)fwrite(buf, 1, strlen(buf), fo);
                    576:        }
1.4       millert   577:        (void)putc('\n', fo);
                    578:        (void)fflush(fo);
1.1       deraadt   579:        if (ferror(fo))
1.11      millert   580:                warn("%s", name);
1.3       millert   581:        (void)Fclose(fo);
1.1       deraadt   582:        rewind(fi);
1.3       millert   583:        return(0);
1.15      millert   584: }
                    585:
                    586: /*ARGSUSED*/
                    587: void
                    588: sendint(int s)
                    589: {
                    590:
                    591:        sendsignal = s;
1.1       deraadt   592: }