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