4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.bin / mail / quit.c
index 4dc515c..0d5f2af 100644 (file)
@@ -1,7 +1,17 @@
-#
+/*
+ * Copyright (c) 1980, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)quit.c     8.1 (Berkeley) %G%";
+#endif /* not lint */
 
 #include "rcv.h"
 
 #include "rcv.h"
-#include <sys/stat.h>
+#include <fcntl.h>
+#include "extern.h"
 
 /*
  * Rcv -- receive mail rationally.
 
 /*
  * Rcv -- receive mail rationally.
  * Termination processing.
  */
 
  * Termination processing.
  */
 
-static char *SccsId = "@(#)quit.c      1.1 %G%";
+/*
+ * The "quit" command.
+ */
+int
+quitcmd()
+{
+       /*
+        * If we are sourcing, then return 1 so execute() can handle it.
+        * Otherwise, return -1 to abort command loop.
+        */
+       if (sourcing)
+               return 1;
+       return -1;
+}
 
 /*
  * Save all of the undetermined messages at the top of "mbox"
  * Save all untouched messages back in the system mailbox.
  * Remove the system mailbox, if none saved there.
  */
 
 /*
  * Save all of the undetermined messages at the top of "mbox"
  * Save all untouched messages back in the system mailbox.
  * Remove the system mailbox, if none saved there.
  */
-
+void
 quit()
 {
 quit()
 {
-       int mcount, p, modify;
-       FILE *ibuf, *obuf, *fbuf, *rbuf;
+       int mcount, p, modify, autohold, anystat, holdbit, nohold;
+       FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
        register struct message *mp;
        register int c;
        extern char tempQuit[], tempResid[];
        struct stat minfo;
        register struct message *mp;
        register int c;
        extern char tempQuit[], tempResid[];
        struct stat minfo;
+       char *mbox;
+
+       /*
+        * If we are read only, we can't do anything,
+        * so just return quickly.
+        */
+       if (readonly)
+               return;
+       /*
+        * If editing (not reading system mail box), then do the work
+        * in edstop()
+        */
+       if (edit) {
+               edstop();
+               return;
+       }
 
        /*
         * See if there any messages to save in mbox.  If no, we
 
        /*
         * See if there any messages to save in mbox.  If no, we
@@ -34,72 +73,90 @@ quit()
         * Delete all untouched messages to keep them out of mbox.
         * If all the messages are to be preserved, just exit with
         * a message.
         * Delete all untouched messages to keep them out of mbox.
         * If all the messages are to be preserved, just exit with
         * a message.
-        *
-        * If the luser has sent mail to himself, refuse to do
-        * anything with the mailbox, unless mail locking works.
         */
 
         */
 
-       lock(mailname);
-#ifndef CANLOCK
-       if (selfsent) {
-               printf("You have new mail.\n");
-               unlock();
-               return;
-       }
-#endif
+       fbuf = Fopen(mailname, "r");
+       if (fbuf == NULL)
+               goto newmail;
+       flock(fileno(fbuf), LOCK_EX);
        rbuf = NULL;
        rbuf = NULL;
-       if (stat(mailname, &minfo) >= 0 && minfo.st_size > mailsize) {
+       if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
                printf("New mail has arrived.\n");
                printf("New mail has arrived.\n");
-               rbuf = fopen(tempResid, "w");
-               fbuf = fopen(mailname, "r");
+               rbuf = Fopen(tempResid, "w");
                if (rbuf == NULL || fbuf == NULL)
                        goto newmail;
 #ifdef APPEND
                if (rbuf == NULL || fbuf == NULL)
                        goto newmail;
 #ifdef APPEND
-               fseek(fbuf, mailsize, 0);
+               fseek(fbuf, (long)mailsize, 0);
                while ((c = getc(fbuf)) != EOF)
                while ((c = getc(fbuf)) != EOF)
-                       putc(c, rbuf);
+                       (void) putc(c, rbuf);
 #else
                p = minfo.st_size - mailsize;
                while (p-- > 0) {
                        c = getc(fbuf);
                        if (c == EOF)
                                goto newmail;
 #else
                p = minfo.st_size - mailsize;
                while (p-- > 0) {
                        c = getc(fbuf);
                        if (c == EOF)
                                goto newmail;
-                       putc(c, rbuf);
+                       (void) putc(c, rbuf);
                }
 #endif
                }
 #endif
-               fclose(fbuf);
-               fclose(rbuf);
-               if ((rbuf = fopen(tempResid, "r")) == NULL)
+               Fclose(rbuf);
+               if ((rbuf = Fopen(tempResid, "r")) == NULL)
                        goto newmail;
                        goto newmail;
-               remove(tempResid);
+               rm(tempResid);
        }
        }
+
+       /*
+        * Adjust the message flags in each message.
+        */
+
+       anystat = 0;
+       autohold = value("hold") != NOSTR;
+       holdbit = autohold ? MPRESERVE : MBOX;
+       nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
+       if (value("keepsave") != NOSTR)
+               nohold &= ~MSAVED;
        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
-               if (mp->m_flag & MDELETED)
-                       mp->m_flag = MDELETED|MTOUCH;
+               if (mp->m_flag & MNEW) {
+                       mp->m_flag &= ~MNEW;
+                       mp->m_flag |= MSTATUS;
+               }
+               if (mp->m_flag & MSTATUS)
+                       anystat++;
                if ((mp->m_flag & MTOUCH) == 0)
                if ((mp->m_flag & MTOUCH) == 0)
-                       mp->m_flag |= MDELETED;
+                       mp->m_flag |= MPRESERVE;
+               if ((mp->m_flag & nohold) == 0)
+                       mp->m_flag |= holdbit;
        }
        modify = 0;
        }
        modify = 0;
+       if (Tflag != NOSTR) {
+               if ((readstat = Fopen(Tflag, "w")) == NULL)
+                       Tflag = NOSTR;
+       }
        for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
        for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
-               if ((mp->m_flag & (MSAVED|MDELETED|MPRESERVE)) == 0)
+               if (mp->m_flag & MBOX)
                        c++;
                        c++;
-               if ((mp->m_flag & MPRESERVE) || (mp->m_flag & MTOUCH) == 0)
+               if (mp->m_flag & MPRESERVE)
                        p++;
                if (mp->m_flag & MODIFY)
                        modify++;
                        p++;
                if (mp->m_flag & MODIFY)
                        modify++;
+               if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
+                       char *id;
+
+                       if ((id = hfield("article-id", mp)) != NOSTR)
+                               fprintf(readstat, "%s\n", id);
+               }
        }
        }
-       if (p == msgCount && !modify) {
-               if (p == 1)
-                       printf("Held 1 message in %s\n", mailname);
-               else
-                       printf("Held %2d messages in %s\n", p, mailname);
-               unlock();
+       if (Tflag != NOSTR)
+               Fclose(readstat);
+       if (p == msgCount && !modify && !anystat) {
+               printf("Held %d message%s in %s\n",
+                       p, p == 1 ? "" : "s", mailname);
+               Fclose(fbuf);
                return;
        }
        if (c == 0) {
                if (p != 0) {
                        writeback(rbuf);
                return;
        }
        if (c == 0) {
                if (p != 0) {
                        writeback(rbuf);
-                       unlock();
+                       Fclose(fbuf);
                        return;
                }
                goto cream;
                        return;
                }
                goto cream;
@@ -112,55 +169,58 @@ quit()
         * just copy saveable entries at the end.
         */
 
         * just copy saveable entries at the end.
         */
 
+       mbox = expand("&");
        mcount = c;
        if (value("append") == NOSTR) {
        mcount = c;
        if (value("append") == NOSTR) {
-               if ((obuf = fopen(tempQuit, "w")) == NULL) {
+               if ((obuf = Fopen(tempQuit, "w")) == NULL) {
                        perror(tempQuit);
                        perror(tempQuit);
-                       unlock();
+                       Fclose(fbuf);
                        return;
                }
                        return;
                }
-               if ((ibuf = fopen(tempQuit, "r")) == NULL) {
+               if ((ibuf = Fopen(tempQuit, "r")) == NULL) {
                        perror(tempQuit);
                        perror(tempQuit);
-                       remove(tempQuit);
-                       fclose(obuf);
-                       unlock();
+                       rm(tempQuit);
+                       Fclose(obuf);
+                       Fclose(fbuf);
                        return;
                }
                        return;
                }
-               remove(tempQuit);
-               if ((fbuf = fopen(mbox, "r")) != NULL) {
-                       while ((c = getc(fbuf)) != EOF)
-                               putc(c, obuf);
-                       fclose(fbuf);
+               rm(tempQuit);
+               if ((abuf = Fopen(mbox, "r")) != NULL) {
+                       while ((c = getc(abuf)) != EOF)
+                               (void) putc(c, obuf);
+                       Fclose(abuf);
                }
                if (ferror(obuf)) {
                        perror(tempQuit);
                }
                if (ferror(obuf)) {
                        perror(tempQuit);
-                       fclose(ibuf);
-                       fclose(obuf);
-                       unlock();
+                       Fclose(ibuf);
+                       Fclose(obuf);
+                       Fclose(fbuf);
                        return;
                }
                        return;
                }
-               fclose(obuf);
+               Fclose(obuf);
                close(creat(mbox, 0600));
                close(creat(mbox, 0600));
-               if ((obuf = fopen(mbox, "w")) == NULL) {
+               if ((obuf = Fopen(mbox, "r+")) == NULL) {
                        perror(mbox);
                        perror(mbox);
-                       fclose(ibuf);
-                       unlock();
+                       Fclose(ibuf);
+                       Fclose(fbuf);
                        return;
                }
        }
                        return;
                }
        }
-       if (value("append") != NOSTR)
-               if ((obuf = fopen(mbox, "a")) == NULL) {
+       if (value("append") != NOSTR) {
+               if ((obuf = Fopen(mbox, "a")) == NULL) {
                        perror(mbox);
                        perror(mbox);
-                       unlock();
+                       Fclose(fbuf);
                        return;
                }
                        return;
                }
+               fchmod(fileno(obuf), 0600);
+       }
        for (mp = &message[0]; mp < &message[msgCount]; mp++)
        for (mp = &message[0]; mp < &message[msgCount]; mp++)
-               if ((mp->m_flag & (MDELETED|MSAVED|MPRESERVE)) == 0)
-                       if (send(mp, obuf) < 0) {
+               if (mp->m_flag & MBOX)
+                       if (send(mp, obuf, saveignore, NOSTR) < 0) {
                                perror(mbox);
                                perror(mbox);
-                               fclose(ibuf);
-                               fclose(obuf);
-                               unlock();
+                               Fclose(ibuf);
+                               Fclose(obuf);
+                               Fclose(fbuf);
                                return;
                        }
 
                                return;
                        }
 
@@ -174,21 +234,22 @@ quit()
                rewind(ibuf);
                c = getc(ibuf);
                while (c != EOF) {
                rewind(ibuf);
                c = getc(ibuf);
                while (c != EOF) {
-                       putc(c, obuf);
+                       (void) putc(c, obuf);
                        if (ferror(obuf))
                                break;
                        c = getc(ibuf);
                }
                        if (ferror(obuf))
                                break;
                        c = getc(ibuf);
                }
-               fclose(ibuf);
+               Fclose(ibuf);
                fflush(obuf);
        }
                fflush(obuf);
        }
+       trunc(obuf);
        if (ferror(obuf)) {
                perror(mbox);
        if (ferror(obuf)) {
                perror(mbox);
-               fclose(obuf);
-               unlock();
+               Fclose(obuf);
+               Fclose(fbuf);
                return;
        }
                return;
        }
-       fclose(obuf);
+       Fclose(obuf);
        if (mcount == 1)
                printf("Saved 1 message in mbox\n");
        else
        if (mcount == 1)
                printf("Saved 1 message in mbox\n");
        else
@@ -201,7 +262,7 @@ quit()
 
        if (p != 0) {
                writeback(rbuf);
 
        if (p != 0) {
                writeback(rbuf);
-               unlock();
+               Fclose(fbuf);
                return;
        }
 
                return;
        }
 
@@ -212,24 +273,26 @@ quit()
 
 cream:
        if (rbuf != NULL) {
 
 cream:
        if (rbuf != NULL) {
-               fbuf = fopen(mailname, "w");
-               if (fbuf == NULL)
+               abuf = Fopen(mailname, "r+");
+               if (abuf == NULL)
                        goto newmail;
                while ((c = getc(rbuf)) != EOF)
                        goto newmail;
                while ((c = getc(rbuf)) != EOF)
-                       putc(c, fbuf);
-               fclose(rbuf);
-               fclose(fbuf);
+                       (void) putc(c, abuf);
+               Fclose(rbuf);
+               trunc(abuf);
+               Fclose(abuf);
                alter(mailname);
                alter(mailname);
-               unlock();
+               Fclose(fbuf);
                return;
        }
        demail();
                return;
        }
        demail();
-       unlock();
+       Fclose(fbuf);
        return;
 
 newmail:
        printf("Thou hast new mail.\n");
        return;
 
 newmail:
        printf("Thou hast new mail.\n");
-       unlock();
+       if (fbuf != NULL)
+               Fclose(fbuf);
 }
 
 /*
 }
 
 /*
@@ -238,7 +301,7 @@ newmail:
  * saved.  On any error, just return -1.  Else return 0.
  * Incorporate the any new mail that we found.
  */
  * saved.  On any error, just return -1.  Else return 0.
  * Incorporate the any new mail that we found.
  */
-
+int
 writeback(res)
        register FILE *res;
 {
 writeback(res)
        register FILE *res;
 {
@@ -247,38 +310,39 @@ writeback(res)
        FILE *obuf;
 
        p = 0;
        FILE *obuf;
 
        p = 0;
-       if ((obuf = fopen(mailname, "w")) == NULL) {
+       if ((obuf = Fopen(mailname, "r+")) == NULL) {
                perror(mailname);
                return(-1);
        }
 #ifndef APPEND
        if (res != NULL)
                while ((c = getc(res)) != EOF)
                perror(mailname);
                return(-1);
        }
 #ifndef APPEND
        if (res != NULL)
                while ((c = getc(res)) != EOF)
-                       putc(c, obuf);
+                       (void) putc(c, obuf);
 #endif
        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
                        p++;
 #endif
        for (mp = &message[0]; mp < &message[msgCount]; mp++)
                if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
                        p++;
-                       if (send(mp, obuf) < 0) {
+                       if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) {
                                perror(mailname);
                                perror(mailname);
-                               fclose(obuf);
+                               Fclose(obuf);
                                return(-1);
                        }
                }
 #ifdef APPEND
        if (res != NULL)
                while ((c = getc(res)) != EOF)
                                return(-1);
                        }
                }
 #ifdef APPEND
        if (res != NULL)
                while ((c = getc(res)) != EOF)
-                       putc(c, obuf);
+                       (void) putc(c, obuf);
 #endif
        fflush(obuf);
 #endif
        fflush(obuf);
+       trunc(obuf);
        if (ferror(obuf)) {
                perror(mailname);
        if (ferror(obuf)) {
                perror(mailname);
-               fclose(obuf);
+               Fclose(obuf);
                return(-1);
        }
        if (res != NULL)
                return(-1);
        }
        if (res != NULL)
-               fclose(res);
-       fclose(obuf);
+               Fclose(res);
+       Fclose(obuf);
        alter(mailname);
        if (p == 1)
                printf("Held 1 message in %s\n", mailname);
        alter(mailname);
        if (p == 1)
                printf("Held 1 message in %s\n", mailname);
@@ -286,3 +350,116 @@ writeback(res)
                printf("Held %d messages in %s\n", p, mailname);
        return(0);
 }
                printf("Held %d messages in %s\n", p, mailname);
        return(0);
 }
+
+/*
+ * Terminate an editing session by attempting to write out the user's
+ * file from the temporary.  Save any new stuff appended to the file.
+ */
+void
+edstop()
+{
+       extern char *tmpdir;
+       register int gotcha, c;
+       register struct message *mp;
+       FILE *obuf, *ibuf, *readstat;
+       struct stat statb;
+       char tempname[30];
+       char *mktemp();
+
+       if (readonly)
+               return;
+       holdsigs();
+       if (Tflag != NOSTR) {
+               if ((readstat = Fopen(Tflag, "w")) == NULL)
+                       Tflag = NOSTR;
+       }
+       for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
+               if (mp->m_flag & MNEW) {
+                       mp->m_flag &= ~MNEW;
+                       mp->m_flag |= MSTATUS;
+               }
+               if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
+                       gotcha++;
+               if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
+                       char *id;
+
+                       if ((id = hfield("article-id", mp)) != NOSTR)
+                               fprintf(readstat, "%s\n", id);
+               }
+       }
+       if (Tflag != NOSTR)
+               Fclose(readstat);
+       if (!gotcha || Tflag != NOSTR)
+               goto done;
+       ibuf = NULL;
+       if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
+               strcpy(tempname, tmpdir);
+               strcat(tempname, "mboxXXXXXX");
+               mktemp(tempname);
+               if ((obuf = Fopen(tempname, "w")) == NULL) {
+                       perror(tempname);
+                       relsesigs();
+                       reset(0);
+               }
+               if ((ibuf = Fopen(mailname, "r")) == NULL) {
+                       perror(mailname);
+                       Fclose(obuf);
+                       rm(tempname);
+                       relsesigs();
+                       reset(0);
+               }
+               fseek(ibuf, (long)mailsize, 0);
+               while ((c = getc(ibuf)) != EOF)
+                       (void) putc(c, obuf);
+               Fclose(ibuf);
+               Fclose(obuf);
+               if ((ibuf = Fopen(tempname, "r")) == NULL) {
+                       perror(tempname);
+                       rm(tempname);
+                       relsesigs();
+                       reset(0);
+               }
+               rm(tempname);
+       }
+       printf("\"%s\" ", mailname);
+       fflush(stdout);
+       if ((obuf = Fopen(mailname, "r+")) == NULL) {
+               perror(mailname);
+               relsesigs();
+               reset(0);
+       }
+       trunc(obuf);
+       c = 0;
+       for (mp = &message[0]; mp < &message[msgCount]; mp++) {
+               if ((mp->m_flag & MDELETED) != 0)
+                       continue;
+               c++;
+               if (send(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) {
+                       perror(mailname);
+                       relsesigs();
+                       reset(0);
+               }
+       }
+       gotcha = (c == 0 && ibuf == NULL);
+       if (ibuf != NULL) {
+               while ((c = getc(ibuf)) != EOF)
+                       (void) putc(c, obuf);
+               Fclose(ibuf);
+       }
+       fflush(obuf);
+       if (ferror(obuf)) {
+               perror(mailname);
+               relsesigs();
+               reset(0);
+       }
+       Fclose(obuf);
+       if (gotcha) {
+               rm(mailname);
+               printf("removed\n");
+       } else
+               printf("complete\n");
+       fflush(stdout);
+
+done:
+       relsesigs();
+}