xref: /original-bsd/usr.bin/mail/quit.c (revision 552e81d8)
1 #
2 
3 #include "rcv.h"
4 #include <sys/stat.h>
5 
6 /*
7  * Rcv -- receive mail rationally.
8  *
9  * Termination processing.
10  */
11 
12 static char *SccsId = "@(#)quit.c	1.1 10/08/80";
13 
14 /*
15  * Save all of the undetermined messages at the top of "mbox"
16  * Save all untouched messages back in the system mailbox.
17  * Remove the system mailbox, if none saved there.
18  */
19 
20 quit()
21 {
22 	int mcount, p, modify;
23 	FILE *ibuf, *obuf, *fbuf, *rbuf;
24 	register struct message *mp;
25 	register int c;
26 	extern char tempQuit[], tempResid[];
27 	struct stat minfo;
28 
29 	/*
30 	 * See if there any messages to save in mbox.  If no, we
31 	 * can save copying mbox to /tmp and back.
32 	 *
33 	 * Check also to see if any files need to be preserved.
34 	 * Delete all untouched messages to keep them out of mbox.
35 	 * If all the messages are to be preserved, just exit with
36 	 * a message.
37 	 *
38 	 * If the luser has sent mail to himself, refuse to do
39 	 * anything with the mailbox, unless mail locking works.
40 	 */
41 
42 	lock(mailname);
43 #ifndef CANLOCK
44 	if (selfsent) {
45 		printf("You have new mail.\n");
46 		unlock();
47 		return;
48 	}
49 #endif
50 	rbuf = NULL;
51 	if (stat(mailname, &minfo) >= 0 && minfo.st_size > mailsize) {
52 		printf("New mail has arrived.\n");
53 		rbuf = fopen(tempResid, "w");
54 		fbuf = fopen(mailname, "r");
55 		if (rbuf == NULL || fbuf == NULL)
56 			goto newmail;
57 #ifdef APPEND
58 		fseek(fbuf, mailsize, 0);
59 		while ((c = getc(fbuf)) != EOF)
60 			putc(c, rbuf);
61 #else
62 		p = minfo.st_size - mailsize;
63 		while (p-- > 0) {
64 			c = getc(fbuf);
65 			if (c == EOF)
66 				goto newmail;
67 			putc(c, rbuf);
68 		}
69 #endif
70 		fclose(fbuf);
71 		fclose(rbuf);
72 		if ((rbuf = fopen(tempResid, "r")) == NULL)
73 			goto newmail;
74 		remove(tempResid);
75 	}
76 	for (mp = &message[0]; mp < &message[msgCount]; mp++) {
77 		if (mp->m_flag & MDELETED)
78 			mp->m_flag = MDELETED|MTOUCH;
79 		if ((mp->m_flag & MTOUCH) == 0)
80 			mp->m_flag |= MDELETED;
81 	}
82 	modify = 0;
83 	for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
84 		if ((mp->m_flag & (MSAVED|MDELETED|MPRESERVE)) == 0)
85 			c++;
86 		if ((mp->m_flag & MPRESERVE) || (mp->m_flag & MTOUCH) == 0)
87 			p++;
88 		if (mp->m_flag & MODIFY)
89 			modify++;
90 	}
91 	if (p == msgCount && !modify) {
92 		if (p == 1)
93 			printf("Held 1 message in %s\n", mailname);
94 		else
95 			printf("Held %2d messages in %s\n", p, mailname);
96 		unlock();
97 		return;
98 	}
99 	if (c == 0) {
100 		if (p != 0) {
101 			writeback(rbuf);
102 			unlock();
103 			return;
104 		}
105 		goto cream;
106 	}
107 
108 	/*
109 	 * Create another temporary file and copy user's mbox file
110 	 * darin.  If there is no mbox, copy nothing.
111 	 * If he has specified "append" don't copy his mailbox,
112 	 * just copy saveable entries at the end.
113 	 */
114 
115 	mcount = c;
116 	if (value("append") == NOSTR) {
117 		if ((obuf = fopen(tempQuit, "w")) == NULL) {
118 			perror(tempQuit);
119 			unlock();
120 			return;
121 		}
122 		if ((ibuf = fopen(tempQuit, "r")) == NULL) {
123 			perror(tempQuit);
124 			remove(tempQuit);
125 			fclose(obuf);
126 			unlock();
127 			return;
128 		}
129 		remove(tempQuit);
130 		if ((fbuf = fopen(mbox, "r")) != NULL) {
131 			while ((c = getc(fbuf)) != EOF)
132 				putc(c, obuf);
133 			fclose(fbuf);
134 		}
135 		if (ferror(obuf)) {
136 			perror(tempQuit);
137 			fclose(ibuf);
138 			fclose(obuf);
139 			unlock();
140 			return;
141 		}
142 		fclose(obuf);
143 		close(creat(mbox, 0600));
144 		if ((obuf = fopen(mbox, "w")) == NULL) {
145 			perror(mbox);
146 			fclose(ibuf);
147 			unlock();
148 			return;
149 		}
150 	}
151 	if (value("append") != NOSTR)
152 		if ((obuf = fopen(mbox, "a")) == NULL) {
153 			perror(mbox);
154 			unlock();
155 			return;
156 		}
157 	for (mp = &message[0]; mp < &message[msgCount]; mp++)
158 		if ((mp->m_flag & (MDELETED|MSAVED|MPRESERVE)) == 0)
159 			if (send(mp, obuf) < 0) {
160 				perror(mbox);
161 				fclose(ibuf);
162 				fclose(obuf);
163 				unlock();
164 				return;
165 			}
166 
167 	/*
168 	 * Copy the user's old mbox contents back
169 	 * to the end of the stuff we just saved.
170 	 * If we are appending, this is unnecessary.
171 	 */
172 
173 	if (value("append") == NOSTR) {
174 		rewind(ibuf);
175 		c = getc(ibuf);
176 		while (c != EOF) {
177 			putc(c, obuf);
178 			if (ferror(obuf))
179 				break;
180 			c = getc(ibuf);
181 		}
182 		fclose(ibuf);
183 		fflush(obuf);
184 	}
185 	if (ferror(obuf)) {
186 		perror(mbox);
187 		fclose(obuf);
188 		unlock();
189 		return;
190 	}
191 	fclose(obuf);
192 	if (mcount == 1)
193 		printf("Saved 1 message in mbox\n");
194 	else
195 		printf("Saved %d messages in mbox\n", mcount);
196 
197 	/*
198 	 * Now we are ready to copy back preserved files to
199 	 * the system mailbox, if any were requested.
200 	 */
201 
202 	if (p != 0) {
203 		writeback(rbuf);
204 		unlock();
205 		return;
206 	}
207 
208 	/*
209 	 * Finally, remove his /usr/mail file.
210 	 * If new mail has arrived, copy it back.
211 	 */
212 
213 cream:
214 	if (rbuf != NULL) {
215 		fbuf = fopen(mailname, "w");
216 		if (fbuf == NULL)
217 			goto newmail;
218 		while ((c = getc(rbuf)) != EOF)
219 			putc(c, fbuf);
220 		fclose(rbuf);
221 		fclose(fbuf);
222 		alter(mailname);
223 		unlock();
224 		return;
225 	}
226 	demail();
227 	unlock();
228 	return;
229 
230 newmail:
231 	printf("Thou hast new mail.\n");
232 	unlock();
233 }
234 
235 /*
236  * Preserve all the appropriate messages back in the system
237  * mailbox, and print a nice message indicated how many were
238  * saved.  On any error, just return -1.  Else return 0.
239  * Incorporate the any new mail that we found.
240  */
241 
242 writeback(res)
243 	register FILE *res;
244 {
245 	register struct message *mp;
246 	register int p, c;
247 	FILE *obuf;
248 
249 	p = 0;
250 	if ((obuf = fopen(mailname, "w")) == NULL) {
251 		perror(mailname);
252 		return(-1);
253 	}
254 #ifndef APPEND
255 	if (res != NULL)
256 		while ((c = getc(res)) != EOF)
257 			putc(c, obuf);
258 #endif
259 	for (mp = &message[0]; mp < &message[msgCount]; mp++)
260 		if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
261 			p++;
262 			if (send(mp, obuf) < 0) {
263 				perror(mailname);
264 				fclose(obuf);
265 				return(-1);
266 			}
267 		}
268 #ifdef APPEND
269 	if (res != NULL)
270 		while ((c = getc(res)) != EOF)
271 			putc(c, obuf);
272 #endif
273 	fflush(obuf);
274 	if (ferror(obuf)) {
275 		perror(mailname);
276 		fclose(obuf);
277 		return(-1);
278 	}
279 	if (res != NULL)
280 		fclose(res);
281 	fclose(obuf);
282 	alter(mailname);
283 	if (p == 1)
284 		printf("Held 1 message in %s\n", mailname);
285 	else
286 		printf("Held %d messages in %s\n", p, mailname);
287 	return(0);
288 }
289