xref: /original-bsd/usr.bin/mail/quit.c (revision ba72ef4c)
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.3 10/10/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, autohold;
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 	for (mp = &message[0]; mp < &message[msgCount]; mp++) {
84 		if (mp->m_flag & MDELETED)
85 			mp->m_flag = MDELETED|MTOUCH;
86 		if ((mp->m_flag & MTOUCH) == 0)
87 			mp->m_flag |= MDELETED;
88 	}
89 	autohold = value("hold") != NOSTR;
90 	modify = 0;
91 	for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
92 		if ((mp->m_flag & (MSAVED|MDELETED)) == 0 && autohold)
93 			mp->m_flag |= MPRESERVE;
94 		if ((mp->m_flag & (MSAVED|MDELETED|MPRESERVE)) == 0)
95 			c++;
96 		if ((mp->m_flag & MPRESERVE) || (mp->m_flag & MTOUCH) == 0)
97 			p++;
98 		if (mp->m_flag & MODIFY)
99 			modify++;
100 	}
101 	if (p == msgCount && !modify) {
102 		if (p == 1)
103 			printf("Held 1 message in %s\n", mailname);
104 		else
105 			printf("Held %2d messages in %s\n", p, mailname);
106 		unlock();
107 		return;
108 	}
109 	if (c == 0) {
110 		if (p != 0) {
111 			writeback(rbuf);
112 			unlock();
113 			return;
114 		}
115 		goto cream;
116 	}
117 
118 	/*
119 	 * Create another temporary file and copy user's mbox file
120 	 * darin.  If there is no mbox, copy nothing.
121 	 * If he has specified "append" don't copy his mailbox,
122 	 * just copy saveable entries at the end.
123 	 */
124 
125 	mcount = c;
126 	if (value("append") == NOSTR) {
127 		if ((obuf = fopen(tempQuit, "w")) == NULL) {
128 			perror(tempQuit);
129 			unlock();
130 			return;
131 		}
132 		if ((ibuf = fopen(tempQuit, "r")) == NULL) {
133 			perror(tempQuit);
134 			remove(tempQuit);
135 			fclose(obuf);
136 			unlock();
137 			return;
138 		}
139 		remove(tempQuit);
140 		if ((fbuf = fopen(mbox, "r")) != NULL) {
141 			while ((c = getc(fbuf)) != EOF)
142 				putc(c, obuf);
143 			fclose(fbuf);
144 		}
145 		if (ferror(obuf)) {
146 			perror(tempQuit);
147 			fclose(ibuf);
148 			fclose(obuf);
149 			unlock();
150 			return;
151 		}
152 		fclose(obuf);
153 		close(creat(mbox, 0600));
154 		if ((obuf = fopen(mbox, "w")) == NULL) {
155 			perror(mbox);
156 			fclose(ibuf);
157 			unlock();
158 			return;
159 		}
160 	}
161 	if (value("append") != NOSTR)
162 		if ((obuf = fopen(mbox, "a")) == NULL) {
163 			perror(mbox);
164 			unlock();
165 			return;
166 		}
167 	for (mp = &message[0]; mp < &message[msgCount]; mp++)
168 		if ((mp->m_flag & (MDELETED|MSAVED|MPRESERVE)) == 0)
169 			if (send(mp, obuf) < 0) {
170 				perror(mbox);
171 				fclose(ibuf);
172 				fclose(obuf);
173 				unlock();
174 				return;
175 			}
176 
177 	/*
178 	 * Copy the user's old mbox contents back
179 	 * to the end of the stuff we just saved.
180 	 * If we are appending, this is unnecessary.
181 	 */
182 
183 	if (value("append") == NOSTR) {
184 		rewind(ibuf);
185 		c = getc(ibuf);
186 		while (c != EOF) {
187 			putc(c, obuf);
188 			if (ferror(obuf))
189 				break;
190 			c = getc(ibuf);
191 		}
192 		fclose(ibuf);
193 		fflush(obuf);
194 	}
195 	if (ferror(obuf)) {
196 		perror(mbox);
197 		fclose(obuf);
198 		unlock();
199 		return;
200 	}
201 	fclose(obuf);
202 	if (mcount == 1)
203 		printf("Saved 1 message in mbox\n");
204 	else
205 		printf("Saved %d messages in mbox\n", mcount);
206 
207 	/*
208 	 * Now we are ready to copy back preserved files to
209 	 * the system mailbox, if any were requested.
210 	 */
211 
212 	if (p != 0) {
213 		writeback(rbuf);
214 		unlock();
215 		return;
216 	}
217 
218 	/*
219 	 * Finally, remove his /usr/mail file.
220 	 * If new mail has arrived, copy it back.
221 	 */
222 
223 cream:
224 	if (rbuf != NULL) {
225 		fbuf = fopen(mailname, "w");
226 		if (fbuf == NULL)
227 			goto newmail;
228 		while ((c = getc(rbuf)) != EOF)
229 			putc(c, fbuf);
230 		fclose(rbuf);
231 		fclose(fbuf);
232 		alter(mailname);
233 		unlock();
234 		return;
235 	}
236 	demail();
237 	unlock();
238 	return;
239 
240 newmail:
241 	printf("Thou hast new mail.\n");
242 	unlock();
243 }
244 
245 /*
246  * Preserve all the appropriate messages back in the system
247  * mailbox, and print a nice message indicated how many were
248  * saved.  On any error, just return -1.  Else return 0.
249  * Incorporate the any new mail that we found.
250  */
251 
252 writeback(res)
253 	register FILE *res;
254 {
255 	register struct message *mp;
256 	register int p, c;
257 	FILE *obuf;
258 
259 	p = 0;
260 	if ((obuf = fopen(mailname, "w")) == NULL) {
261 		perror(mailname);
262 		return(-1);
263 	}
264 #ifndef APPEND
265 	if (res != NULL)
266 		while ((c = getc(res)) != EOF)
267 			putc(c, obuf);
268 #endif
269 	for (mp = &message[0]; mp < &message[msgCount]; mp++)
270 		if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
271 			p++;
272 			if (send(mp, obuf) < 0) {
273 				perror(mailname);
274 				fclose(obuf);
275 				return(-1);
276 			}
277 		}
278 #ifdef APPEND
279 	if (res != NULL)
280 		while ((c = getc(res)) != EOF)
281 			putc(c, obuf);
282 #endif
283 	fflush(obuf);
284 	if (ferror(obuf)) {
285 		perror(mailname);
286 		fclose(obuf);
287 		return(-1);
288 	}
289 	if (res != NULL)
290 		fclose(res);
291 	fclose(obuf);
292 	alter(mailname);
293 	if (p == 1)
294 		printf("Held 1 message in %s\n", mailname);
295 	else
296 		printf("Held %d messages in %s\n", p, mailname);
297 	return(0);
298 }
299