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

Annotation of src/usr.bin/mail/quit.c, Revision 1.12.2.1

1.12.2.1! jason       1: /*     $OpenBSD: quit.c,v 1.13 2000/06/30 16:00:18 millert Exp $       */
1.4       millert     2: /*     $NetBSD: quit.c,v 1.6 1996/12/28 07:11:07 tls 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.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  */
                     36:
                     37: #ifndef lint
1.2       deraadt    38: #if 0
1.4       millert    39: static char sccsid[] = "@(#)quit.c     8.2 (Berkeley) 4/28/95";
1.2       deraadt    40: #else
1.12.2.1! jason      41: static char rcsid[] = "$OpenBSD: quit.c,v 1.13 2000/06/30 16:00:18 millert Exp $";
1.2       deraadt    42: #endif
1.1       deraadt    43: #endif /* not lint */
                     44:
                     45: #include "rcv.h"
                     46: #include <fcntl.h>
                     47: #include "extern.h"
                     48:
                     49: /*
                     50:  * Rcv -- receive mail rationally.
                     51:  *
                     52:  * Termination processing.
                     53:  */
                     54:
                     55: /*
                     56:  * The "quit" command.
                     57:  */
                     58: int
1.2       deraadt    59: quitcmd(v)
                     60:        void *v;
1.1       deraadt    61: {
                     62:        /*
                     63:         * If we are sourcing, then return 1 so execute() can handle it.
                     64:         * Otherwise, return -1 to abort command loop.
                     65:         */
                     66:        if (sourcing)
1.4       millert    67:                return(1);
                     68:        return(-1);
1.1       deraadt    69: }
                     70:
                     71: /*
                     72:  * Save all of the undetermined messages at the top of "mbox"
                     73:  * Save all untouched messages back in the system mailbox.
                     74:  * Remove the system mailbox, if none saved there.
                     75:  */
                     76: void
                     77: quit()
                     78: {
                     79:        int mcount, p, modify, autohold, anystat, holdbit, nohold;
1.2       deraadt    80:        FILE *ibuf = NULL, *obuf, *fbuf, *rbuf, *readstat = NULL, *abuf;
1.9       millert    81:        struct message *mp;
1.7       millert    82:        int c, fd;
1.1       deraadt    83:        struct stat minfo;
1.8       millert    84:        char *mbox, tempname[PATHSIZE];
1.1       deraadt    85:
                     86:        /*
                     87:         * If we are read only, we can't do anything,
                     88:         * so just return quickly.
                     89:         */
                     90:        if (readonly)
                     91:                return;
                     92:        /*
                     93:         * If editing (not reading system mail box), then do the work
                     94:         * in edstop()
                     95:         */
                     96:        if (edit) {
                     97:                edstop();
                     98:                return;
                     99:        }
                    100:
                    101:        /*
                    102:         * See if there any messages to save in mbox.  If no, we
                    103:         * can save copying mbox to /tmp and back.
                    104:         *
                    105:         * Check also to see if any files need to be preserved.
                    106:         * Delete all untouched messages to keep them out of mbox.
                    107:         * If all the messages are to be preserved, just exit with
                    108:         * a message.
                    109:         */
                    110:
                    111:        fbuf = Fopen(mailname, "r");
                    112:        if (fbuf == NULL)
                    113:                goto newmail;
1.2       deraadt   114:        if (flock(fileno(fbuf), LOCK_EX) == -1) {
1.4       millert   115:                warn("Unable to lock mailbox");
                    116:                (void)Fclose(fbuf);
1.2       deraadt   117:                return;
                    118:        }
1.3       millert   119:        if (!spool_lock()) {
1.4       millert   120:                (void)Fclose(fbuf);
1.11      millert   121:                return;                 /* lockspool printed error for us */
1.3       millert   122:        }
1.1       deraadt   123:        rbuf = NULL;
                    124:        if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
1.4       millert   125:                puts("New mail has arrived.");
1.7       millert   126:                (void)snprintf(tempname, sizeof(tempname),
                    127:                    "%s/mail.RqXXXXXXXXXX", tmpdir);
                    128:                if ((fd = mkstemp(tempname)) == -1 ||
                    129:                    (rbuf = Fdopen(fd, "w")) == NULL)
1.1       deraadt   130:                        goto newmail;
                    131: #ifdef APPEND
                    132:                fseek(fbuf, (long)mailsize, 0);
                    133:                while ((c = getc(fbuf)) != EOF)
1.5       millert   134:                        (void)putc(c, rbuf);
1.1       deraadt   135: #else
                    136:                p = minfo.st_size - mailsize;
                    137:                while (p-- > 0) {
                    138:                        c = getc(fbuf);
                    139:                        if (c == EOF)
                    140:                                goto newmail;
1.5       millert   141:                        (void)putc(c, rbuf);
1.1       deraadt   142:                }
                    143: #endif
1.4       millert   144:                (void)Fclose(rbuf);
1.7       millert   145:                if ((rbuf = Fopen(tempname, "r")) == NULL)
1.1       deraadt   146:                        goto newmail;
1.8       millert   147:                (void)rm(tempname);
1.1       deraadt   148:        }
                    149:
                    150:        /*
                    151:         * Adjust the message flags in each message.
                    152:         */
                    153:
                    154:        anystat = 0;
1.6       millert   155:        autohold = value("hold") != NULL;
1.1       deraadt   156:        holdbit = autohold ? MPRESERVE : MBOX;
                    157:        nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
1.6       millert   158:        if (value("keepsave") != NULL)
1.1       deraadt   159:                nohold &= ~MSAVED;
                    160:        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
                    161:                if (mp->m_flag & MNEW) {
                    162:                        mp->m_flag &= ~MNEW;
                    163:                        mp->m_flag |= MSTATUS;
                    164:                }
                    165:                if (mp->m_flag & MSTATUS)
                    166:                        anystat++;
                    167:                if ((mp->m_flag & MTOUCH) == 0)
                    168:                        mp->m_flag |= MPRESERVE;
                    169:                if ((mp->m_flag & nohold) == 0)
                    170:                        mp->m_flag |= holdbit;
                    171:        }
                    172:        modify = 0;
1.6       millert   173:        if (Tflag != NULL) {
1.1       deraadt   174:                if ((readstat = Fopen(Tflag, "w")) == NULL)
1.6       millert   175:                        Tflag = NULL;
1.1       deraadt   176:        }
                    177:        for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
                    178:                if (mp->m_flag & MBOX)
                    179:                        c++;
                    180:                if (mp->m_flag & MPRESERVE)
                    181:                        p++;
                    182:                if (mp->m_flag & MODIFY)
                    183:                        modify++;
1.6       millert   184:                if (Tflag != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
1.1       deraadt   185:                        char *id;
                    186:
1.6       millert   187:                        if ((id = hfield("article-id", mp)) != NULL)
1.1       deraadt   188:                                fprintf(readstat, "%s\n", id);
                    189:                }
                    190:        }
1.6       millert   191:        if (Tflag != NULL)
1.4       millert   192:                (void)Fclose(readstat);
1.1       deraadt   193:        if (p == msgCount && !modify && !anystat) {
                    194:                printf("Held %d message%s in %s\n",
                    195:                        p, p == 1 ? "" : "s", mailname);
1.4       millert   196:                (void)Fclose(fbuf);
1.3       millert   197:                spool_unlock();
1.1       deraadt   198:                return;
                    199:        }
                    200:        if (c == 0) {
                    201:                if (p != 0) {
                    202:                        writeback(rbuf);
1.4       millert   203:                        (void)Fclose(fbuf);
1.3       millert   204:                        spool_unlock();
1.1       deraadt   205:                        return;
                    206:                }
                    207:                goto cream;
                    208:        }
                    209:
                    210:        /*
                    211:         * Create another temporary file and copy user's mbox file
                    212:         * darin.  If there is no mbox, copy nothing.
                    213:         * If he has specified "append" don't copy his mailbox,
                    214:         * just copy saveable entries at the end.
                    215:         */
                    216:
                    217:        mbox = expand("&");
                    218:        mcount = c;
1.6       millert   219:        if (value("append") == NULL) {
1.7       millert   220:                (void)snprintf(tempname, sizeof(tempname),
                    221:                    "%s/mail.RmXXXXXXXXXX", tmpdir);
                    222:                if ((fd = mkstemp(tempname)) == -1 ||
                    223:                    (obuf = Fdopen(fd, "w")) == NULL) {
1.12.2.1! jason     224:                        warn("%s", tempname);
1.4       millert   225:                        (void)Fclose(fbuf);
1.3       millert   226:                        spool_unlock();
1.1       deraadt   227:                        return;
                    228:                }
1.7       millert   229:                if ((ibuf = Fopen(tempname, "r")) == NULL) {
1.12.2.1! jason     230:                        warn("%s", tempname);
1.8       millert   231:                        (void)rm(tempname);
1.4       millert   232:                        (void)Fclose(obuf);
                    233:                        (void)Fclose(fbuf);
1.3       millert   234:                        spool_unlock();
1.1       deraadt   235:                        return;
                    236:                }
1.8       millert   237:                (void)rm(tempname);
1.1       deraadt   238:                if ((abuf = Fopen(mbox, "r")) != NULL) {
                    239:                        while ((c = getc(abuf)) != EOF)
1.5       millert   240:                                (void)putc(c, obuf);
1.4       millert   241:                        (void)Fclose(abuf);
1.1       deraadt   242:                }
                    243:                if (ferror(obuf)) {
1.12.2.1! jason     244:                        warn("%s", tempname);
1.4       millert   245:                        (void)Fclose(ibuf);
                    246:                        (void)Fclose(obuf);
                    247:                        (void)Fclose(fbuf);
1.3       millert   248:                        spool_unlock();
1.1       deraadt   249:                        return;
                    250:                }
1.4       millert   251:                (void)Fclose(obuf);
                    252:                (void)close(creat(mbox, 0600));
1.1       deraadt   253:                if ((obuf = Fopen(mbox, "r+")) == NULL) {
1.12.2.1! jason     254:                        warn("%s", mbox);
1.4       millert   255:                        (void)Fclose(ibuf);
                    256:                        (void)Fclose(fbuf);
1.3       millert   257:                        spool_unlock();
1.1       deraadt   258:                        return;
                    259:                }
                    260:        }
1.2       deraadt   261:        else {
1.1       deraadt   262:                if ((obuf = Fopen(mbox, "a")) == NULL) {
1.12.2.1! jason     263:                        warn("%s", mbox);
1.4       millert   264:                        (void)Fclose(fbuf);
1.3       millert   265:                        spool_unlock();
1.1       deraadt   266:                        return;
                    267:                }
                    268:                fchmod(fileno(obuf), 0600);
                    269:        }
                    270:        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                    271:                if (mp->m_flag & MBOX)
1.12      millert   272:                        if (sendmessage(mp, obuf, saveignore, NULL) < 0) {
1.12.2.1! jason     273:                                warn("%s", mbox);
1.4       millert   274:                                (void)Fclose(ibuf);
                    275:                                (void)Fclose(obuf);
                    276:                                (void)Fclose(fbuf);
1.3       millert   277:                                spool_unlock();
1.1       deraadt   278:                                return;
                    279:                        }
                    280:
                    281:        /*
                    282:         * Copy the user's old mbox contents back
                    283:         * to the end of the stuff we just saved.
                    284:         * If we are appending, this is unnecessary.
                    285:         */
                    286:
1.6       millert   287:        if (value("append") == NULL) {
1.1       deraadt   288:                rewind(ibuf);
                    289:                c = getc(ibuf);
                    290:                while (c != EOF) {
1.5       millert   291:                        (void)putc(c, obuf);
1.1       deraadt   292:                        if (ferror(obuf))
                    293:                                break;
                    294:                        c = getc(ibuf);
                    295:                }
1.4       millert   296:                (void)Fclose(ibuf);
1.1       deraadt   297:                fflush(obuf);
                    298:        }
                    299:        trunc(obuf);
                    300:        if (ferror(obuf)) {
1.12.2.1! jason     301:                warn("%s", mbox);
1.4       millert   302:                (void)Fclose(obuf);
                    303:                (void)Fclose(fbuf);
1.3       millert   304:                spool_unlock();
1.1       deraadt   305:                return;
                    306:        }
1.4       millert   307:        (void)Fclose(obuf);
1.1       deraadt   308:        if (mcount == 1)
1.4       millert   309:                puts("Saved 1 message in mbox");
1.1       deraadt   310:        else
                    311:                printf("Saved %d messages in mbox\n", mcount);
                    312:
                    313:        /*
                    314:         * Now we are ready to copy back preserved files to
                    315:         * the system mailbox, if any were requested.
                    316:         */
                    317:
                    318:        if (p != 0) {
                    319:                writeback(rbuf);
1.4       millert   320:                (void)Fclose(fbuf);
1.3       millert   321:                spool_unlock();
1.1       deraadt   322:                return;
                    323:        }
                    324:
                    325:        /*
1.10      millert   326:         * Finally, remove his /var/mail file.
1.1       deraadt   327:         * If new mail has arrived, copy it back.
                    328:         */
                    329:
                    330: cream:
                    331:        if (rbuf != NULL) {
                    332:                abuf = Fopen(mailname, "r+");
                    333:                if (abuf == NULL)
                    334:                        goto newmail;
                    335:                while ((c = getc(rbuf)) != EOF)
1.5       millert   336:                        (void)putc(c, abuf);
1.4       millert   337:                (void)Fclose(rbuf);
1.1       deraadt   338:                trunc(abuf);
1.4       millert   339:                (void)Fclose(abuf);
1.1       deraadt   340:                alter(mailname);
1.4       millert   341:                (void)Fclose(fbuf);
1.3       millert   342:                spool_unlock();
1.1       deraadt   343:                return;
                    344:        }
                    345:        demail();
1.4       millert   346:        (void)Fclose(fbuf);
1.3       millert   347:        spool_unlock();
1.1       deraadt   348:        return;
                    349:
                    350: newmail:
1.4       millert   351:        puts("Thou hast new mail.");
1.2       deraadt   352:        if (fbuf != NULL) {
1.4       millert   353:                (void)Fclose(fbuf);
1.3       millert   354:                spool_unlock();
1.2       deraadt   355:        }
1.1       deraadt   356: }
                    357:
                    358: /*
                    359:  * Preserve all the appropriate messages back in the system
                    360:  * mailbox, and print a nice message indicated how many were
                    361:  * saved.  On any error, just return -1.  Else return 0.
                    362:  * Incorporate the any new mail that we found.
                    363:  */
                    364: int
                    365: writeback(res)
1.9       millert   366:        FILE *res;
1.1       deraadt   367: {
1.9       millert   368:        struct message *mp;
                    369:        int p, c;
1.1       deraadt   370:        FILE *obuf;
                    371:
                    372:        p = 0;
                    373:        if ((obuf = Fopen(mailname, "r+")) == NULL) {
1.12.2.1! jason     374:                warn("%s", mailname);
1.1       deraadt   375:                return(-1);
                    376:        }
                    377: #ifndef APPEND
                    378:        if (res != NULL)
                    379:                while ((c = getc(res)) != EOF)
1.5       millert   380:                        (void)putc(c, obuf);
1.1       deraadt   381: #endif
                    382:        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                    383:                if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
                    384:                        p++;
1.12      millert   385:                        if (sendmessage(mp, obuf, NULL, NULL) < 0) {
1.12.2.1! jason     386:                                warn("%s", mailname);
1.4       millert   387:                                (void)Fclose(obuf);
1.1       deraadt   388:                                return(-1);
                    389:                        }
                    390:                }
                    391: #ifdef APPEND
                    392:        if (res != NULL)
                    393:                while ((c = getc(res)) != EOF)
1.5       millert   394:                        (void)putc(c, obuf);
1.1       deraadt   395: #endif
                    396:        fflush(obuf);
                    397:        trunc(obuf);
                    398:        if (ferror(obuf)) {
1.12.2.1! jason     399:                warn("%s", mailname);
1.4       millert   400:                (void)Fclose(obuf);
1.1       deraadt   401:                return(-1);
                    402:        }
                    403:        if (res != NULL)
1.4       millert   404:                (void)Fclose(res);
                    405:        (void)Fclose(obuf);
1.1       deraadt   406:        alter(mailname);
                    407:        if (p == 1)
                    408:                printf("Held 1 message in %s\n", mailname);
                    409:        else
                    410:                printf("Held %d messages in %s\n", p, mailname);
                    411:        return(0);
                    412: }
                    413:
                    414: /*
                    415:  * Terminate an editing session by attempting to write out the user's
                    416:  * file from the temporary.  Save any new stuff appended to the file.
                    417:  */
                    418: void
                    419: edstop()
                    420: {
1.9       millert   421:        int gotcha, c;
                    422:        struct message *mp;
1.2       deraadt   423:        FILE *obuf, *ibuf, *readstat = NULL;
1.1       deraadt   424:        struct stat statb;
1.8       millert   425:        char tempname[PATHSIZE];
1.1       deraadt   426:
                    427:        if (readonly)
                    428:                return;
                    429:        holdsigs();
1.6       millert   430:        if (Tflag != NULL) {
1.1       deraadt   431:                if ((readstat = Fopen(Tflag, "w")) == NULL)
1.6       millert   432:                        Tflag = NULL;
1.1       deraadt   433:        }
                    434:        for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
                    435:                if (mp->m_flag & MNEW) {
                    436:                        mp->m_flag &= ~MNEW;
                    437:                        mp->m_flag |= MSTATUS;
                    438:                }
                    439:                if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
                    440:                        gotcha++;
1.6       millert   441:                if (Tflag != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
1.1       deraadt   442:                        char *id;
                    443:
1.6       millert   444:                        if ((id = hfield("article-id", mp)) != NULL)
1.1       deraadt   445:                                fprintf(readstat, "%s\n", id);
                    446:                }
                    447:        }
1.6       millert   448:        if (Tflag != NULL)
1.4       millert   449:                (void)Fclose(readstat);
1.6       millert   450:        if (!gotcha || Tflag != NULL)
1.1       deraadt   451:                goto done;
                    452:        ibuf = NULL;
                    453:        if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
1.3       millert   454:                int fd;
1.1       deraadt   455:
1.8       millert   456:                (void)snprintf(tempname, sizeof(tempname), "%s/mbox.XXXXXXXXXX",
1.7       millert   457:                    tmpdir);
1.3       millert   458:                if ((fd = mkstemp(tempname)) == -1 ||
                    459:                    (obuf = Fdopen(fd, "w")) == NULL) {
1.12.2.1! jason     460:                        warn("%s", tempname);
1.1       deraadt   461:                        relsesigs();
                    462:                        reset(0);
                    463:                }
                    464:                if ((ibuf = Fopen(mailname, "r")) == NULL) {
1.12.2.1! jason     465:                        warn("%s", mailname);
1.4       millert   466:                        (void)Fclose(obuf);
1.8       millert   467:                        (void)rm(tempname);
1.1       deraadt   468:                        relsesigs();
                    469:                        reset(0);
                    470:                }
                    471:                fseek(ibuf, (long)mailsize, 0);
                    472:                while ((c = getc(ibuf)) != EOF)
1.5       millert   473:                        (void)putc(c, obuf);
1.4       millert   474:                (void)Fclose(ibuf);
                    475:                (void)Fclose(obuf);
1.1       deraadt   476:                if ((ibuf = Fopen(tempname, "r")) == NULL) {
1.12.2.1! jason     477:                        warn("%s", tempname);
1.8       millert   478:                        (void)rm(tempname);
1.1       deraadt   479:                        relsesigs();
                    480:                        reset(0);
                    481:                }
1.8       millert   482:                (void)rm(tempname);
1.1       deraadt   483:        }
                    484:        printf("\"%s\" ", mailname);
                    485:        fflush(stdout);
                    486:        if ((obuf = Fopen(mailname, "r+")) == NULL) {
1.12.2.1! jason     487:                warn("%s", mailname);
1.1       deraadt   488:                relsesigs();
                    489:                reset(0);
                    490:        }
                    491:        trunc(obuf);
                    492:        c = 0;
                    493:        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
                    494:                if ((mp->m_flag & MDELETED) != 0)
                    495:                        continue;
                    496:                c++;
1.12      millert   497:                if (sendmessage(mp, obuf, NULL, NULL) < 0) {
1.12.2.1! jason     498:                        warn("%s", mailname);
1.1       deraadt   499:                        relsesigs();
                    500:                        reset(0);
                    501:                }
                    502:        }
                    503:        gotcha = (c == 0 && ibuf == NULL);
                    504:        if (ibuf != NULL) {
                    505:                while ((c = getc(ibuf)) != EOF)
1.5       millert   506:                        (void)putc(c, obuf);
1.4       millert   507:                (void)Fclose(ibuf);
1.1       deraadt   508:        }
                    509:        fflush(obuf);
                    510:        if (ferror(obuf)) {
1.12.2.1! jason     511:                warn("%s", mailname);
1.1       deraadt   512:                relsesigs();
                    513:                reset(0);
                    514:        }
1.4       millert   515:        (void)Fclose(obuf);
1.1       deraadt   516:        if (gotcha) {
1.8       millert   517:                (void)rm(mailname);
1.4       millert   518:                puts("removed");
1.1       deraadt   519:        } else
1.4       millert   520:                puts("complete");
1.1       deraadt   521:        fflush(stdout);
                    522:
                    523: done:
                    524:        relsesigs();
                    525: }