[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.4

1.4     ! millert     1: /*     $OpenBSD: quit.c,v 1.3 1997/03/29 03:01:47 millert Exp $        */
        !             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.4     ! millert    41: static char rcsid[] = "$OpenBSD: quit.c,v 1.3 1997/03/29 03:01:47 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.1       deraadt    81:        register struct message *mp;
                     82:        register int c;
                     83:        extern char *tempQuit, *tempResid;
                     84:        struct stat minfo;
                     85:        char *mbox;
                     86:
                     87:        /*
                     88:         * If we are read only, we can't do anything,
                     89:         * so just return quickly.
                     90:         */
                     91:        if (readonly)
                     92:                return;
                     93:        /*
                     94:         * If editing (not reading system mail box), then do the work
                     95:         * in edstop()
                     96:         */
                     97:        if (edit) {
                     98:                edstop();
                     99:                return;
                    100:        }
                    101:
                    102:        /*
                    103:         * See if there any messages to save in mbox.  If no, we
                    104:         * can save copying mbox to /tmp and back.
                    105:         *
                    106:         * Check also to see if any files need to be preserved.
                    107:         * Delete all untouched messages to keep them out of mbox.
                    108:         * If all the messages are to be preserved, just exit with
                    109:         * a message.
                    110:         */
                    111:
                    112:        fbuf = Fopen(mailname, "r");
                    113:        if (fbuf == NULL)
                    114:                goto newmail;
1.2       deraadt   115:        if (flock(fileno(fbuf), LOCK_EX) == -1) {
1.4     ! millert   116:                warn("Unable to lock mailbox");
        !           117:                (void)Fclose(fbuf);
1.2       deraadt   118:                return;
                    119:        }
1.3       millert   120:        if (!spool_lock()) {
1.4     ! millert   121:                (void)Fclose(fbuf);
1.3       millert   122:                return;                 /* mail.local printed error for us */
                    123:        }
1.1       deraadt   124:        rbuf = NULL;
                    125:        if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
1.4     ! millert   126:                puts("New mail has arrived.");
1.1       deraadt   127:                rbuf = Fopen(tempResid, "w");
                    128:                if (rbuf == NULL || fbuf == NULL)
                    129:                        goto newmail;
                    130: #ifdef APPEND
                    131:                fseek(fbuf, (long)mailsize, 0);
                    132:                while ((c = getc(fbuf)) != EOF)
                    133:                        (void) putc(c, rbuf);
                    134: #else
                    135:                p = minfo.st_size - mailsize;
                    136:                while (p-- > 0) {
                    137:                        c = getc(fbuf);
                    138:                        if (c == EOF)
                    139:                                goto newmail;
                    140:                        (void) putc(c, rbuf);
                    141:                }
                    142: #endif
1.4     ! millert   143:                (void)Fclose(rbuf);
1.1       deraadt   144:                if ((rbuf = Fopen(tempResid, "r")) == NULL)
                    145:                        goto newmail;
                    146:                rm(tempResid);
                    147:        }
                    148:
                    149:        /*
                    150:         * Adjust the message flags in each message.
                    151:         */
                    152:
                    153:        anystat = 0;
                    154:        autohold = value("hold") != NOSTR;
                    155:        holdbit = autohold ? MPRESERVE : MBOX;
                    156:        nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
                    157:        if (value("keepsave") != NOSTR)
                    158:                nohold &= ~MSAVED;
                    159:        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
                    160:                if (mp->m_flag & MNEW) {
                    161:                        mp->m_flag &= ~MNEW;
                    162:                        mp->m_flag |= MSTATUS;
                    163:                }
                    164:                if (mp->m_flag & MSTATUS)
                    165:                        anystat++;
                    166:                if ((mp->m_flag & MTOUCH) == 0)
                    167:                        mp->m_flag |= MPRESERVE;
                    168:                if ((mp->m_flag & nohold) == 0)
                    169:                        mp->m_flag |= holdbit;
                    170:        }
                    171:        modify = 0;
                    172:        if (Tflag != NOSTR) {
                    173:                if ((readstat = Fopen(Tflag, "w")) == NULL)
                    174:                        Tflag = NOSTR;
                    175:        }
                    176:        for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
                    177:                if (mp->m_flag & MBOX)
                    178:                        c++;
                    179:                if (mp->m_flag & MPRESERVE)
                    180:                        p++;
                    181:                if (mp->m_flag & MODIFY)
                    182:                        modify++;
                    183:                if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
                    184:                        char *id;
                    185:
                    186:                        if ((id = hfield("article-id", mp)) != NOSTR)
                    187:                                fprintf(readstat, "%s\n", id);
                    188:                }
                    189:        }
                    190:        if (Tflag != NOSTR)
1.4     ! millert   191:                (void)Fclose(readstat);
1.1       deraadt   192:        if (p == msgCount && !modify && !anystat) {
                    193:                printf("Held %d message%s in %s\n",
                    194:                        p, p == 1 ? "" : "s", mailname);
1.4     ! millert   195:                (void)Fclose(fbuf);
1.3       millert   196:                spool_unlock();
1.1       deraadt   197:                return;
                    198:        }
                    199:        if (c == 0) {
                    200:                if (p != 0) {
                    201:                        writeback(rbuf);
1.4     ! millert   202:                        (void)Fclose(fbuf);
1.3       millert   203:                        spool_unlock();
1.1       deraadt   204:                        return;
                    205:                }
                    206:                goto cream;
                    207:        }
                    208:
                    209:        /*
                    210:         * Create another temporary file and copy user's mbox file
                    211:         * darin.  If there is no mbox, copy nothing.
                    212:         * If he has specified "append" don't copy his mailbox,
                    213:         * just copy saveable entries at the end.
                    214:         */
                    215:
                    216:        mbox = expand("&");
                    217:        mcount = c;
                    218:        if (value("append") == NOSTR) {
                    219:                if ((obuf = Fopen(tempQuit, "w")) == NULL) {
1.4     ! millert   220:                        warn(tempQuit);
        !           221:                        (void)Fclose(fbuf);
1.3       millert   222:                        spool_unlock();
1.1       deraadt   223:                        return;
                    224:                }
                    225:                if ((ibuf = Fopen(tempQuit, "r")) == NULL) {
1.4     ! millert   226:                        warn(tempQuit);
1.1       deraadt   227:                        rm(tempQuit);
1.4     ! millert   228:                        (void)Fclose(obuf);
        !           229:                        (void)Fclose(fbuf);
1.3       millert   230:                        spool_unlock();
1.1       deraadt   231:                        return;
                    232:                }
                    233:                rm(tempQuit);
                    234:                if ((abuf = Fopen(mbox, "r")) != NULL) {
                    235:                        while ((c = getc(abuf)) != EOF)
                    236:                                (void) putc(c, obuf);
1.4     ! millert   237:                        (void)Fclose(abuf);
1.1       deraadt   238:                }
                    239:                if (ferror(obuf)) {
1.4     ! millert   240:                        warn(tempQuit);
        !           241:                        (void)Fclose(ibuf);
        !           242:                        (void)Fclose(obuf);
        !           243:                        (void)Fclose(fbuf);
1.3       millert   244:                        spool_unlock();
1.1       deraadt   245:                        return;
                    246:                }
1.4     ! millert   247:                (void)Fclose(obuf);
        !           248:                (void)close(creat(mbox, 0600));
1.1       deraadt   249:                if ((obuf = Fopen(mbox, "r+")) == NULL) {
1.4     ! millert   250:                        warn(mbox);
        !           251:                        (void)Fclose(ibuf);
        !           252:                        (void)Fclose(fbuf);
1.3       millert   253:                        spool_unlock();
1.1       deraadt   254:                        return;
                    255:                }
                    256:        }
1.2       deraadt   257:        else {
1.1       deraadt   258:                if ((obuf = Fopen(mbox, "a")) == NULL) {
1.4     ! millert   259:                        warn(mbox);
        !           260:                        (void)Fclose(fbuf);
1.3       millert   261:                        spool_unlock();
1.1       deraadt   262:                        return;
                    263:                }
                    264:                fchmod(fileno(obuf), 0600);
                    265:        }
                    266:        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                    267:                if (mp->m_flag & MBOX)
                    268:                        if (send(mp, obuf, saveignore, NOSTR) < 0) {
1.4     ! millert   269:                                warn(mbox);
        !           270:                                (void)Fclose(ibuf);
        !           271:                                (void)Fclose(obuf);
        !           272:                                (void)Fclose(fbuf);
1.3       millert   273:                                spool_unlock();
1.1       deraadt   274:                                return;
                    275:                        }
                    276:
                    277:        /*
                    278:         * Copy the user's old mbox contents back
                    279:         * to the end of the stuff we just saved.
                    280:         * If we are appending, this is unnecessary.
                    281:         */
                    282:
                    283:        if (value("append") == NOSTR) {
                    284:                rewind(ibuf);
                    285:                c = getc(ibuf);
                    286:                while (c != EOF) {
                    287:                        (void) putc(c, obuf);
                    288:                        if (ferror(obuf))
                    289:                                break;
                    290:                        c = getc(ibuf);
                    291:                }
1.4     ! millert   292:                (void)Fclose(ibuf);
1.1       deraadt   293:                fflush(obuf);
                    294:        }
                    295:        trunc(obuf);
                    296:        if (ferror(obuf)) {
1.4     ! millert   297:                warn(mbox);
        !           298:                (void)Fclose(obuf);
        !           299:                (void)Fclose(fbuf);
1.3       millert   300:                spool_unlock();
1.1       deraadt   301:                return;
                    302:        }
1.4     ! millert   303:        (void)Fclose(obuf);
1.1       deraadt   304:        if (mcount == 1)
1.4     ! millert   305:                puts("Saved 1 message in mbox");
1.1       deraadt   306:        else
                    307:                printf("Saved %d messages in mbox\n", mcount);
                    308:
                    309:        /*
                    310:         * Now we are ready to copy back preserved files to
                    311:         * the system mailbox, if any were requested.
                    312:         */
                    313:
                    314:        if (p != 0) {
                    315:                writeback(rbuf);
1.4     ! millert   316:                (void)Fclose(fbuf);
1.3       millert   317:                spool_unlock();
1.1       deraadt   318:                return;
                    319:        }
                    320:
                    321:        /*
                    322:         * Finally, remove his /usr/mail file.
                    323:         * If new mail has arrived, copy it back.
                    324:         */
                    325:
                    326: cream:
                    327:        if (rbuf != NULL) {
                    328:                abuf = Fopen(mailname, "r+");
                    329:                if (abuf == NULL)
                    330:                        goto newmail;
                    331:                while ((c = getc(rbuf)) != EOF)
                    332:                        (void) putc(c, abuf);
1.4     ! millert   333:                (void)Fclose(rbuf);
1.1       deraadt   334:                trunc(abuf);
1.4     ! millert   335:                (void)Fclose(abuf);
1.1       deraadt   336:                alter(mailname);
1.4     ! millert   337:                (void)Fclose(fbuf);
1.3       millert   338:                spool_unlock();
1.1       deraadt   339:                return;
                    340:        }
                    341:        demail();
1.4     ! millert   342:        (void)Fclose(fbuf);
1.3       millert   343:        spool_unlock();
1.1       deraadt   344:        return;
                    345:
                    346: newmail:
1.4     ! millert   347:        puts("Thou hast new mail.");
1.2       deraadt   348:        if (fbuf != NULL) {
1.4     ! millert   349:                (void)Fclose(fbuf);
1.3       millert   350:                spool_unlock();
1.2       deraadt   351:        }
1.1       deraadt   352: }
                    353:
                    354: /*
                    355:  * Preserve all the appropriate messages back in the system
                    356:  * mailbox, and print a nice message indicated how many were
                    357:  * saved.  On any error, just return -1.  Else return 0.
                    358:  * Incorporate the any new mail that we found.
                    359:  */
                    360: int
                    361: writeback(res)
                    362:        register FILE *res;
                    363: {
                    364:        register struct message *mp;
                    365:        register int p, c;
                    366:        FILE *obuf;
                    367:
                    368:        p = 0;
                    369:        if ((obuf = Fopen(mailname, "r+")) == NULL) {
1.4     ! millert   370:                warn(mailname);
1.1       deraadt   371:                return(-1);
                    372:        }
                    373: #ifndef APPEND
                    374:        if (res != NULL)
                    375:                while ((c = getc(res)) != EOF)
                    376:                        (void) putc(c, obuf);
                    377: #endif
                    378:        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                    379:                if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
                    380:                        p++;
                    381:                        if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) {
1.4     ! millert   382:                                warn(mailname);
        !           383:                                (void)Fclose(obuf);
1.1       deraadt   384:                                return(-1);
                    385:                        }
                    386:                }
                    387: #ifdef APPEND
                    388:        if (res != NULL)
                    389:                while ((c = getc(res)) != EOF)
                    390:                        (void) putc(c, obuf);
                    391: #endif
                    392:        fflush(obuf);
                    393:        trunc(obuf);
                    394:        if (ferror(obuf)) {
1.4     ! millert   395:                warn(mailname);
        !           396:                (void)Fclose(obuf);
1.1       deraadt   397:                return(-1);
                    398:        }
                    399:        if (res != NULL)
1.4     ! millert   400:                (void)Fclose(res);
        !           401:        (void)Fclose(obuf);
1.1       deraadt   402:        alter(mailname);
                    403:        if (p == 1)
                    404:                printf("Held 1 message in %s\n", mailname);
                    405:        else
                    406:                printf("Held %d messages in %s\n", p, mailname);
                    407:        return(0);
                    408: }
                    409:
                    410: /*
                    411:  * Terminate an editing session by attempting to write out the user's
                    412:  * file from the temporary.  Save any new stuff appended to the file.
                    413:  */
                    414: void
                    415: edstop()
                    416: {
                    417:        extern char *tmpdir;
                    418:        register int gotcha, c;
                    419:        register struct message *mp;
1.2       deraadt   420:        FILE *obuf, *ibuf, *readstat = NULL;
1.1       deraadt   421:        struct stat statb;
1.3       millert   422:        char tempname[MAXPATHLEN];
1.1       deraadt   423:
                    424:        if (readonly)
                    425:                return;
                    426:        holdsigs();
                    427:        if (Tflag != NOSTR) {
                    428:                if ((readstat = Fopen(Tflag, "w")) == NULL)
                    429:                        Tflag = NOSTR;
                    430:        }
                    431:        for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
                    432:                if (mp->m_flag & MNEW) {
                    433:                        mp->m_flag &= ~MNEW;
                    434:                        mp->m_flag |= MSTATUS;
                    435:                }
                    436:                if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
                    437:                        gotcha++;
                    438:                if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
                    439:                        char *id;
                    440:
                    441:                        if ((id = hfield("article-id", mp)) != NOSTR)
                    442:                                fprintf(readstat, "%s\n", id);
                    443:                }
                    444:        }
                    445:        if (Tflag != NOSTR)
1.4     ! millert   446:                (void)Fclose(readstat);
1.1       deraadt   447:        if (!gotcha || Tflag != NOSTR)
                    448:                goto done;
                    449:        ibuf = NULL;
                    450:        if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
1.3       millert   451:                int fd;
1.1       deraadt   452:
1.3       millert   453:                snprintf(tempname, sizeof(tempname), "%s/%s", tmpdir,
                    454:                    "mboxXXXXXXXXXX");
                    455:                if ((fd = mkstemp(tempname)) == -1 ||
                    456:                    (obuf = Fdopen(fd, "w")) == NULL) {
1.4     ! millert   457:                        warn(tempname);
1.1       deraadt   458:                        relsesigs();
                    459:                        reset(0);
                    460:                }
                    461:                if ((ibuf = Fopen(mailname, "r")) == NULL) {
1.4     ! millert   462:                        warn(mailname);
        !           463:                        (void)Fclose(obuf);
1.1       deraadt   464:                        rm(tempname);
                    465:                        relsesigs();
                    466:                        reset(0);
                    467:                }
                    468:                fseek(ibuf, (long)mailsize, 0);
                    469:                while ((c = getc(ibuf)) != EOF)
                    470:                        (void) putc(c, obuf);
1.4     ! millert   471:                (void)Fclose(ibuf);
        !           472:                (void)Fclose(obuf);
1.1       deraadt   473:                if ((ibuf = Fopen(tempname, "r")) == NULL) {
1.4     ! millert   474:                        warn(tempname);
1.1       deraadt   475:                        rm(tempname);
                    476:                        relsesigs();
                    477:                        reset(0);
                    478:                }
                    479:                rm(tempname);
                    480:        }
                    481:        printf("\"%s\" ", mailname);
                    482:        fflush(stdout);
                    483:        if ((obuf = Fopen(mailname, "r+")) == NULL) {
1.4     ! millert   484:                warn(mailname);
1.1       deraadt   485:                relsesigs();
                    486:                reset(0);
                    487:        }
                    488:        trunc(obuf);
                    489:        c = 0;
                    490:        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
                    491:                if ((mp->m_flag & MDELETED) != 0)
                    492:                        continue;
                    493:                c++;
                    494:                if (send(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) {
1.4     ! millert   495:                        warn(mailname);
1.1       deraadt   496:                        relsesigs();
                    497:                        reset(0);
                    498:                }
                    499:        }
                    500:        gotcha = (c == 0 && ibuf == NULL);
                    501:        if (ibuf != NULL) {
                    502:                while ((c = getc(ibuf)) != EOF)
                    503:                        (void) putc(c, obuf);
1.4     ! millert   504:                (void)Fclose(ibuf);
1.1       deraadt   505:        }
                    506:        fflush(obuf);
                    507:        if (ferror(obuf)) {
1.4     ! millert   508:                warn(mailname);
1.1       deraadt   509:                relsesigs();
                    510:                reset(0);
                    511:        }
1.4     ! millert   512:        (void)Fclose(obuf);
1.1       deraadt   513:        if (gotcha) {
                    514:                rm(mailname);
1.4     ! millert   515:                puts("removed");
1.1       deraadt   516:        } else
1.4     ! millert   517:                puts("complete");
1.1       deraadt   518:        fflush(stdout);
                    519:
                    520: done:
                    521:        relsesigs();
                    522: }