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