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

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