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

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