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