home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / mail / quit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  10.9 KB  |  488 lines

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