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

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