122464Sdist /*
262083Sbostic * Copyright (c) 1980, 1993
362083Sbostic * The Regents of the University of California. All rights reserved.
433499Sbostic *
542741Sbostic * %sccs.include.redist.c%
622464Sdist */
722464Sdist
834905Sbostic #ifndef lint
9*69020Sbostic static char sccsid[] = "@(#)quit.c 8.2 (Berkeley) 04/28/95";
1034905Sbostic #endif /* not lint */
111243Skas
121243Skas #include "rcv.h"
1354505Sbostic #include <fcntl.h>
1454505Sbostic #include "extern.h"
151243Skas
161243Skas /*
171243Skas * Rcv -- receive mail rationally.
181243Skas *
191243Skas * Termination processing.
201243Skas */
211243Skas
221243Skas /*
2336554Sedward * The "quit" command.
2436554Sedward */
2554505Sbostic int
quitcmd()2636554Sedward quitcmd()
2736554Sedward {
2836554Sedward /*
2936554Sedward * If we are sourcing, then return 1 so execute() can handle it.
3036554Sedward * Otherwise, return -1 to abort command loop.
3136554Sedward */
3236554Sedward if (sourcing)
3336554Sedward return 1;
3436554Sedward return -1;
3536554Sedward }
3636554Sedward
3736554Sedward /*
381243Skas * Save all of the undetermined messages at the top of "mbox"
391243Skas * Save all untouched messages back in the system mailbox.
401243Skas * Remove the system mailbox, if none saved there.
411243Skas */
4254505Sbostic void
quit()431243Skas quit()
441243Skas {
454338Skurt int mcount, p, modify, autohold, anystat, holdbit, nohold;
4616733Sralph FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
471243Skas register struct message *mp;
481243Skas register int c;
491243Skas extern char tempQuit[], tempResid[];
501243Skas struct stat minfo;
5134753Sedward char *mbox;
521243Skas
531243Skas /*
541314Skas * If we are read only, we can't do anything,
551314Skas * so just return quickly.
561314Skas */
571314Skas if (readonly)
581314Skas return;
591314Skas /*
6036554Sedward * If editing (not reading system mail box), then do the work
6136554Sedward * in edstop()
6236554Sedward */
6336554Sedward if (edit) {
6436554Sedward edstop();
6536554Sedward return;
6636554Sedward }
6736554Sedward
6836554Sedward /*
691243Skas * See if there any messages to save in mbox. If no, we
701243Skas * can save copying mbox to /tmp and back.
711243Skas *
721243Skas * Check also to see if any files need to be preserved.
731243Skas * Delete all untouched messages to keep them out of mbox.
741243Skas * If all the messages are to be preserved, just exit with
751243Skas * a message.
761243Skas */
771243Skas
7843865Sedward fbuf = Fopen(mailname, "r");
7916733Sralph if (fbuf == NULL)
8016733Sralph goto newmail;
8116733Sralph flock(fileno(fbuf), LOCK_EX);
821243Skas rbuf = NULL;
8316733Sralph if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
841243Skas printf("New mail has arrived.\n");
8543865Sedward rbuf = Fopen(tempResid, "w");
861243Skas if (rbuf == NULL || fbuf == NULL)
871243Skas goto newmail;
881243Skas #ifdef APPEND
8954505Sbostic fseek(fbuf, (long)mailsize, 0);
901243Skas while ((c = getc(fbuf)) != EOF)
9136554Sedward (void) putc(c, rbuf);
921243Skas #else
931243Skas p = minfo.st_size - mailsize;
941243Skas while (p-- > 0) {
951243Skas c = getc(fbuf);
961243Skas if (c == EOF)
971243Skas goto newmail;
9836554Sedward (void) putc(c, rbuf);
991243Skas }
1001243Skas #endif
10143865Sedward Fclose(rbuf);
10243865Sedward if ((rbuf = Fopen(tempResid, "r")) == NULL)
1031243Skas goto newmail;
10446349Sedward rm(tempResid);
1051243Skas }
1061486Skas
1071486Skas /*
1081486Skas * Adjust the message flags in each message.
1091486Skas */
1101486Skas
1111486Skas anystat = 0;
1123322Skas autohold = value("hold") != NOSTR;
1133322Skas holdbit = autohold ? MPRESERVE : MBOX;
1144338Skurt nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
1154338Skurt if (value("keepsave") != NOSTR)
1164338Skurt nohold &= ~MSAVED;
1171243Skas for (mp = &message[0]; mp < &message[msgCount]; mp++) {
1181486Skas if (mp->m_flag & MNEW) {
1191486Skas mp->m_flag &= ~MNEW;
1201486Skas mp->m_flag |= MSTATUS;
1211486Skas }
1221486Skas if (mp->m_flag & MSTATUS)
1231486Skas anystat++;
1241243Skas if ((mp->m_flag & MTOUCH) == 0)
1253322Skas mp->m_flag |= MPRESERVE;
1264338Skurt if ((mp->m_flag & nohold) == 0)
1273322Skas mp->m_flag |= holdbit;
1281243Skas }
1291243Skas modify = 0;
1304020Skurt if (Tflag != NOSTR) {
13143865Sedward if ((readstat = Fopen(Tflag, "w")) == NULL)
1324020Skurt Tflag = NOSTR;
1334020Skurt }
1341243Skas for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
1353322Skas if (mp->m_flag & MBOX)
1361243Skas c++;
1373322Skas if (mp->m_flag & MPRESERVE)
1381243Skas p++;
1391243Skas if (mp->m_flag & MODIFY)
1401243Skas modify++;
1414020Skurt if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
14234754Sedward char *id;
14334754Sedward
14434754Sedward if ((id = hfield("article-id", mp)) != NOSTR)
1454020Skurt fprintf(readstat, "%s\n", id);
1464020Skurt }
1471243Skas }
1484020Skurt if (Tflag != NOSTR)
14943865Sedward Fclose(readstat);
1501486Skas if (p == msgCount && !modify && !anystat) {
15134754Sedward printf("Held %d message%s in %s\n",
15234754Sedward p, p == 1 ? "" : "s", mailname);
15343865Sedward Fclose(fbuf);
1541243Skas return;
1551243Skas }
1561243Skas if (c == 0) {
1571243Skas if (p != 0) {
1581243Skas writeback(rbuf);
15943865Sedward Fclose(fbuf);
1601243Skas return;
1611243Skas }
1621243Skas goto cream;
1631243Skas }
1641243Skas
1651243Skas /*
1661243Skas * Create another temporary file and copy user's mbox file
1671243Skas * darin. If there is no mbox, copy nothing.
1681243Skas * If he has specified "append" don't copy his mailbox,
1691243Skas * just copy saveable entries at the end.
1701243Skas */
1711243Skas
17234753Sedward mbox = expand("&");
1731243Skas mcount = c;
1741243Skas if (value("append") == NOSTR) {
17543865Sedward if ((obuf = Fopen(tempQuit, "w")) == NULL) {
1761243Skas perror(tempQuit);
17743865Sedward Fclose(fbuf);
1781243Skas return;
1791243Skas }
18043865Sedward if ((ibuf = Fopen(tempQuit, "r")) == NULL) {
1811243Skas perror(tempQuit);
18246349Sedward rm(tempQuit);
18343865Sedward Fclose(obuf);
18443865Sedward Fclose(fbuf);
1851243Skas return;
1861243Skas }
18746349Sedward rm(tempQuit);
18843865Sedward if ((abuf = Fopen(mbox, "r")) != NULL) {
18916733Sralph while ((c = getc(abuf)) != EOF)
19036554Sedward (void) putc(c, obuf);
19143865Sedward Fclose(abuf);
1921243Skas }
1931243Skas if (ferror(obuf)) {
1941243Skas perror(tempQuit);
19543865Sedward Fclose(ibuf);
19643865Sedward Fclose(obuf);
19743865Sedward Fclose(fbuf);
1981243Skas return;
1991243Skas }
20043865Sedward Fclose(obuf);
2011243Skas close(creat(mbox, 0600));
20243865Sedward if ((obuf = Fopen(mbox, "r+")) == NULL) {
2031243Skas perror(mbox);
20443865Sedward Fclose(ibuf);
20543865Sedward Fclose(fbuf);
2061243Skas return;
2071243Skas }
2081243Skas }
20926488Smckusick if (value("append") != NOSTR) {
21043865Sedward if ((obuf = Fopen(mbox, "a")) == NULL) {
2111243Skas perror(mbox);
21243865Sedward Fclose(fbuf);
2131243Skas return;
2141243Skas }
21526488Smckusick fchmod(fileno(obuf), 0600);
21626488Smckusick }
2171243Skas for (mp = &message[0]; mp < &message[msgCount]; mp++)
2183322Skas if (mp->m_flag & MBOX)
21934969Sedward if (send(mp, obuf, saveignore, NOSTR) < 0) {
2201243Skas perror(mbox);
22143865Sedward Fclose(ibuf);
22243865Sedward Fclose(obuf);
22343865Sedward Fclose(fbuf);
2241243Skas return;
2251243Skas }
2261243Skas
2271243Skas /*
2281243Skas * Copy the user's old mbox contents back
2291243Skas * to the end of the stuff we just saved.
2301243Skas * If we are appending, this is unnecessary.
2311243Skas */
2321243Skas
2331243Skas if (value("append") == NOSTR) {
2341243Skas rewind(ibuf);
2351243Skas c = getc(ibuf);
2361243Skas while (c != EOF) {
23736554Sedward (void) putc(c, obuf);
2381243Skas if (ferror(obuf))
2391243Skas break;
2401243Skas c = getc(ibuf);
2411243Skas }
24243865Sedward Fclose(ibuf);
2431243Skas }
244*69020Sbostic fflush(obuf);
24512818Sleres trunc(obuf);
2461243Skas if (ferror(obuf)) {
2471243Skas perror(mbox);
24843865Sedward Fclose(obuf);
24943865Sedward Fclose(fbuf);
2501243Skas return;
2511243Skas }
25243865Sedward Fclose(obuf);
2531243Skas if (mcount == 1)
2541243Skas printf("Saved 1 message in mbox\n");
2551243Skas else
2561243Skas printf("Saved %d messages in mbox\n", mcount);
2571243Skas
2581243Skas /*
2591243Skas * Now we are ready to copy back preserved files to
2601243Skas * the system mailbox, if any were requested.
2611243Skas */
2621243Skas
2631243Skas if (p != 0) {
2641243Skas writeback(rbuf);
26543865Sedward Fclose(fbuf);
2661243Skas return;
2671243Skas }
2681243Skas
2691243Skas /*
2701243Skas * Finally, remove his /usr/mail file.
2711243Skas * If new mail has arrived, copy it back.
2721243Skas */
2731243Skas
2741243Skas cream:
2751243Skas if (rbuf != NULL) {
27643865Sedward abuf = Fopen(mailname, "r+");
27716733Sralph if (abuf == NULL)
2781243Skas goto newmail;
2791243Skas while ((c = getc(rbuf)) != EOF)
28036554Sedward (void) putc(c, abuf);
28143865Sedward Fclose(rbuf);
28216733Sralph trunc(abuf);
28343865Sedward Fclose(abuf);
28416733Sralph alter(mailname);
28543865Sedward Fclose(fbuf);
2861243Skas return;
2871243Skas }
2881243Skas demail();
28943865Sedward Fclose(fbuf);
2901243Skas return;
2911243Skas
2921243Skas newmail:
2931243Skas printf("Thou hast new mail.\n");
29421092Sserge if (fbuf != NULL)
29543865Sedward Fclose(fbuf);
2961243Skas }
2971243Skas
2981243Skas /*
2991243Skas * Preserve all the appropriate messages back in the system
3001243Skas * mailbox, and print a nice message indicated how many were
3011243Skas * saved. On any error, just return -1. Else return 0.
3021243Skas * Incorporate the any new mail that we found.
3031243Skas */
30454505Sbostic int
writeback(res)3051243Skas writeback(res)
3061243Skas register FILE *res;
3071243Skas {
3081243Skas register struct message *mp;
3091243Skas register int p, c;
3101243Skas FILE *obuf;
3111243Skas
3121243Skas p = 0;
31343865Sedward if ((obuf = Fopen(mailname, "r+")) == NULL) {
3141243Skas perror(mailname);
3151243Skas return(-1);
3161243Skas }
3171243Skas #ifndef APPEND
3181243Skas if (res != NULL)
3191243Skas while ((c = getc(res)) != EOF)
32036554Sedward (void) putc(c, obuf);
3211243Skas #endif
3221243Skas for (mp = &message[0]; mp < &message[msgCount]; mp++)
3231243Skas if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
3241243Skas p++;
32534969Sedward if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) {
3261243Skas perror(mailname);
32743865Sedward Fclose(obuf);
3281243Skas return(-1);
3291243Skas }
3301243Skas }
3311243Skas #ifdef APPEND
3321243Skas if (res != NULL)
3331243Skas while ((c = getc(res)) != EOF)
33436554Sedward (void) putc(c, obuf);
3351243Skas #endif
3361243Skas fflush(obuf);
33712818Sleres trunc(obuf);
3381243Skas if (ferror(obuf)) {
3391243Skas perror(mailname);
34043865Sedward Fclose(obuf);
3411243Skas return(-1);
3421243Skas }
3431243Skas if (res != NULL)
34443865Sedward Fclose(res);
34543865Sedward Fclose(obuf);
3461243Skas alter(mailname);
3471243Skas if (p == 1)
3481243Skas printf("Held 1 message in %s\n", mailname);
3491243Skas else
3501243Skas printf("Held %d messages in %s\n", p, mailname);
3511243Skas return(0);
3521243Skas }
35336554Sedward
35436554Sedward /*
35536554Sedward * Terminate an editing session by attempting to write out the user's
35636554Sedward * file from the temporary. Save any new stuff appended to the file.
35736554Sedward */
35854505Sbostic void
edstop()35936554Sedward edstop()
36036554Sedward {
36152909Sbostic extern char *tmpdir;
36236554Sedward register int gotcha, c;
36336554Sedward register struct message *mp;
36436554Sedward FILE *obuf, *ibuf, *readstat;
36536554Sedward struct stat statb;
36636554Sedward char tempname[30];
36736554Sedward char *mktemp();
36836554Sedward
36936554Sedward if (readonly)
37036554Sedward return;
37136554Sedward holdsigs();
37236554Sedward if (Tflag != NOSTR) {
37343865Sedward if ((readstat = Fopen(Tflag, "w")) == NULL)
37436554Sedward Tflag = NOSTR;
37536554Sedward }
37636554Sedward for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
37736554Sedward if (mp->m_flag & MNEW) {
37836554Sedward mp->m_flag &= ~MNEW;
37936554Sedward mp->m_flag |= MSTATUS;
38036554Sedward }
38136554Sedward if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
38236554Sedward gotcha++;
38336554Sedward if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
38436554Sedward char *id;
38536554Sedward
38636554Sedward if ((id = hfield("article-id", mp)) != NOSTR)
38736554Sedward fprintf(readstat, "%s\n", id);
38836554Sedward }
38936554Sedward }
39036554Sedward if (Tflag != NOSTR)
39143865Sedward Fclose(readstat);
39236554Sedward if (!gotcha || Tflag != NOSTR)
39336554Sedward goto done;
39436554Sedward ibuf = NULL;
39536554Sedward if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
39652909Sbostic strcpy(tempname, tmpdir);
39738698Sbostic strcat(tempname, "mboxXXXXXX");
39836554Sedward mktemp(tempname);
39943865Sedward if ((obuf = Fopen(tempname, "w")) == NULL) {
40036554Sedward perror(tempname);
40136554Sedward relsesigs();
40236554Sedward reset(0);
40336554Sedward }
40443865Sedward if ((ibuf = Fopen(mailname, "r")) == NULL) {
40536554Sedward perror(mailname);
40643865Sedward Fclose(obuf);
40746349Sedward rm(tempname);
40836554Sedward relsesigs();
40936554Sedward reset(0);
41036554Sedward }
41154505Sbostic fseek(ibuf, (long)mailsize, 0);
41236554Sedward while ((c = getc(ibuf)) != EOF)
41336554Sedward (void) putc(c, obuf);
41443865Sedward Fclose(ibuf);
41543865Sedward Fclose(obuf);
41643865Sedward if ((ibuf = Fopen(tempname, "r")) == NULL) {
41736554Sedward perror(tempname);
41846349Sedward rm(tempname);
41936554Sedward relsesigs();
42036554Sedward reset(0);
42136554Sedward }
42246349Sedward rm(tempname);
42336554Sedward }
42436554Sedward printf("\"%s\" ", mailname);
42536554Sedward fflush(stdout);
42643865Sedward if ((obuf = Fopen(mailname, "r+")) == NULL) {
42736554Sedward perror(mailname);
42836554Sedward relsesigs();
42936554Sedward reset(0);
43036554Sedward }
43136554Sedward trunc(obuf);
43236554Sedward c = 0;
43336554Sedward for (mp = &message[0]; mp < &message[msgCount]; mp++) {
43436554Sedward if ((mp->m_flag & MDELETED) != 0)
43536554Sedward continue;
43636554Sedward c++;
43736554Sedward if (send(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) {
43836554Sedward perror(mailname);
43936554Sedward relsesigs();
44036554Sedward reset(0);
44136554Sedward }
44236554Sedward }
44336554Sedward gotcha = (c == 0 && ibuf == NULL);
44436554Sedward if (ibuf != NULL) {
44536554Sedward while ((c = getc(ibuf)) != EOF)
44636554Sedward (void) putc(c, obuf);
44743865Sedward Fclose(ibuf);
44836554Sedward }
44936554Sedward fflush(obuf);
45036554Sedward if (ferror(obuf)) {
45136554Sedward perror(mailname);
45236554Sedward relsesigs();
45336554Sedward reset(0);
45436554Sedward }
45543865Sedward Fclose(obuf);
45636554Sedward if (gotcha) {
45746349Sedward rm(mailname);
45836554Sedward printf("removed\n");
45936554Sedward } else
46036554Sedward printf("complete\n");
46136554Sedward fflush(stdout);
46236554Sedward
46336554Sedward done:
46436554Sedward relsesigs();
46536554Sedward }
466