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