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: }