Commit | Line | Data |
---|---|---|
761330fe DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
0c5f72fb KB |
3 | * All rights reserved. |
4 | * | |
f15db449 | 5 | * %sccs.include.redist.c% |
761330fe DF |
6 | */ |
7 | ||
acfc7e9b | 8 | #ifndef lint |
f629a181 | 9 | static char sccsid[] = "@(#)quit.c 5.17 (Berkeley) %G%"; |
acfc7e9b | 10 | #endif /* not lint */ |
865dca9a KS |
11 | |
12 | #include "rcv.h" | |
13 | #include <sys/stat.h> | |
4e161d3b | 14 | #include <sys/file.h> |
865dca9a KS |
15 | |
16 | /* | |
17 | * Rcv -- receive mail rationally. | |
18 | * | |
19 | * Termination processing. | |
20 | */ | |
21 | ||
2ee3bce2 EW |
22 | /* |
23 | * The "quit" command. | |
24 | */ | |
25 | quitcmd() | |
26 | { | |
27 | /* | |
28 | * If we are sourcing, then return 1 so execute() can handle it. | |
29 | * Otherwise, return -1 to abort command loop. | |
30 | */ | |
31 | if (sourcing) | |
32 | return 1; | |
33 | return -1; | |
34 | } | |
35 | ||
865dca9a KS |
36 | /* |
37 | * Save all of the undetermined messages at the top of "mbox" | |
38 | * Save all untouched messages back in the system mailbox. | |
39 | * Remove the system mailbox, if none saved there. | |
40 | */ | |
41 | ||
42 | quit() | |
43 | { | |
c2483c81 | 44 | int mcount, p, modify, autohold, anystat, holdbit, nohold; |
4e161d3b | 45 | FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf; |
865dca9a KS |
46 | register struct message *mp; |
47 | register int c; | |
48 | extern char tempQuit[], tempResid[]; | |
49 | struct stat minfo; | |
2a0f6531 | 50 | char *mbox; |
865dca9a | 51 | |
3ecebc0f KS |
52 | /* |
53 | * If we are read only, we can't do anything, | |
54 | * so just return quickly. | |
55 | */ | |
3ecebc0f KS |
56 | if (readonly) |
57 | return; | |
2ee3bce2 EW |
58 | /* |
59 | * If editing (not reading system mail box), then do the work | |
60 | * in edstop() | |
61 | */ | |
62 | if (edit) { | |
63 | edstop(); | |
64 | return; | |
65 | } | |
66 | ||
865dca9a KS |
67 | /* |
68 | * See if there any messages to save in mbox. If no, we | |
69 | * can save copying mbox to /tmp and back. | |
70 | * | |
71 | * Check also to see if any files need to be preserved. | |
72 | * Delete all untouched messages to keep them out of mbox. | |
73 | * If all the messages are to be preserved, just exit with | |
74 | * a message. | |
865dca9a KS |
75 | */ |
76 | ||
07b0d286 | 77 | fbuf = Fopen(mailname, "r"); |
4e161d3b RC |
78 | if (fbuf == NULL) |
79 | goto newmail; | |
80 | flock(fileno(fbuf), LOCK_EX); | |
865dca9a | 81 | rbuf = NULL; |
4e161d3b | 82 | if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) { |
865dca9a | 83 | printf("New mail has arrived.\n"); |
07b0d286 | 84 | rbuf = Fopen(tempResid, "w"); |
865dca9a KS |
85 | if (rbuf == NULL || fbuf == NULL) |
86 | goto newmail; | |
87 | #ifdef APPEND | |
88 | fseek(fbuf, mailsize, 0); | |
89 | while ((c = getc(fbuf)) != EOF) | |
2ee3bce2 | 90 | (void) putc(c, rbuf); |
865dca9a KS |
91 | #else |
92 | p = minfo.st_size - mailsize; | |
93 | while (p-- > 0) { | |
94 | c = getc(fbuf); | |
95 | if (c == EOF) | |
96 | goto newmail; | |
2ee3bce2 | 97 | (void) putc(c, rbuf); |
865dca9a KS |
98 | } |
99 | #endif | |
07b0d286 EW |
100 | Fclose(rbuf); |
101 | if ((rbuf = Fopen(tempResid, "r")) == NULL) | |
865dca9a | 102 | goto newmail; |
a7585c01 | 103 | rm(tempResid); |
865dca9a | 104 | } |
63e83a9b KS |
105 | |
106 | /* | |
107 | * Adjust the message flags in each message. | |
108 | */ | |
109 | ||
110 | anystat = 0; | |
252cba79 KS |
111 | autohold = value("hold") != NOSTR; |
112 | holdbit = autohold ? MPRESERVE : MBOX; | |
c2483c81 KS |
113 | nohold = MBOX|MSAVED|MDELETED|MPRESERVE; |
114 | if (value("keepsave") != NOSTR) | |
115 | nohold &= ~MSAVED; | |
865dca9a | 116 | for (mp = &message[0]; mp < &message[msgCount]; mp++) { |
63e83a9b KS |
117 | if (mp->m_flag & MNEW) { |
118 | mp->m_flag &= ~MNEW; | |
119 | mp->m_flag |= MSTATUS; | |
120 | } | |
121 | if (mp->m_flag & MSTATUS) | |
122 | anystat++; | |
865dca9a | 123 | if ((mp->m_flag & MTOUCH) == 0) |
252cba79 | 124 | mp->m_flag |= MPRESERVE; |
c2483c81 | 125 | if ((mp->m_flag & nohold) == 0) |
252cba79 | 126 | mp->m_flag |= holdbit; |
865dca9a KS |
127 | } |
128 | modify = 0; | |
f0d15113 | 129 | if (Tflag != NOSTR) { |
07b0d286 | 130 | if ((readstat = Fopen(Tflag, "w")) == NULL) |
f0d15113 KS |
131 | Tflag = NOSTR; |
132 | } | |
865dca9a | 133 | for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) { |
252cba79 | 134 | if (mp->m_flag & MBOX) |
865dca9a | 135 | c++; |
252cba79 | 136 | if (mp->m_flag & MPRESERVE) |
865dca9a KS |
137 | p++; |
138 | if (mp->m_flag & MODIFY) | |
139 | modify++; | |
f0d15113 | 140 | if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { |
4d20fb09 EW |
141 | char *id; |
142 | ||
143 | if ((id = hfield("article-id", mp)) != NOSTR) | |
f0d15113 KS |
144 | fprintf(readstat, "%s\n", id); |
145 | } | |
865dca9a | 146 | } |
f0d15113 | 147 | if (Tflag != NOSTR) |
07b0d286 | 148 | Fclose(readstat); |
63e83a9b | 149 | if (p == msgCount && !modify && !anystat) { |
4d20fb09 EW |
150 | printf("Held %d message%s in %s\n", |
151 | p, p == 1 ? "" : "s", mailname); | |
07b0d286 | 152 | Fclose(fbuf); |
865dca9a KS |
153 | return; |
154 | } | |
155 | if (c == 0) { | |
156 | if (p != 0) { | |
157 | writeback(rbuf); | |
07b0d286 | 158 | Fclose(fbuf); |
865dca9a KS |
159 | return; |
160 | } | |
161 | goto cream; | |
162 | } | |
163 | ||
164 | /* | |
165 | * Create another temporary file and copy user's mbox file | |
166 | * darin. If there is no mbox, copy nothing. | |
167 | * If he has specified "append" don't copy his mailbox, | |
168 | * just copy saveable entries at the end. | |
169 | */ | |
170 | ||
2a0f6531 | 171 | mbox = expand("&"); |
865dca9a KS |
172 | mcount = c; |
173 | if (value("append") == NOSTR) { | |
07b0d286 | 174 | if ((obuf = Fopen(tempQuit, "w")) == NULL) { |
865dca9a | 175 | perror(tempQuit); |
07b0d286 | 176 | Fclose(fbuf); |
865dca9a KS |
177 | return; |
178 | } | |
07b0d286 | 179 | if ((ibuf = Fopen(tempQuit, "r")) == NULL) { |
865dca9a | 180 | perror(tempQuit); |
a7585c01 | 181 | rm(tempQuit); |
07b0d286 EW |
182 | Fclose(obuf); |
183 | Fclose(fbuf); | |
865dca9a KS |
184 | return; |
185 | } | |
a7585c01 | 186 | rm(tempQuit); |
07b0d286 | 187 | if ((abuf = Fopen(mbox, "r")) != NULL) { |
4e161d3b | 188 | while ((c = getc(abuf)) != EOF) |
2ee3bce2 | 189 | (void) putc(c, obuf); |
07b0d286 | 190 | Fclose(abuf); |
865dca9a KS |
191 | } |
192 | if (ferror(obuf)) { | |
193 | perror(tempQuit); | |
07b0d286 EW |
194 | Fclose(ibuf); |
195 | Fclose(obuf); | |
196 | Fclose(fbuf); | |
865dca9a KS |
197 | return; |
198 | } | |
07b0d286 | 199 | Fclose(obuf); |
865dca9a | 200 | close(creat(mbox, 0600)); |
07b0d286 | 201 | if ((obuf = Fopen(mbox, "r+")) == NULL) { |
865dca9a | 202 | perror(mbox); |
07b0d286 EW |
203 | Fclose(ibuf); |
204 | Fclose(fbuf); | |
865dca9a KS |
205 | return; |
206 | } | |
207 | } | |
8fd89bb1 | 208 | if (value("append") != NOSTR) { |
07b0d286 | 209 | if ((obuf = Fopen(mbox, "a")) == NULL) { |
865dca9a | 210 | perror(mbox); |
07b0d286 | 211 | Fclose(fbuf); |
865dca9a KS |
212 | return; |
213 | } | |
8fd89bb1 KM |
214 | fchmod(fileno(obuf), 0600); |
215 | } | |
865dca9a | 216 | for (mp = &message[0]; mp < &message[msgCount]; mp++) |
252cba79 | 217 | if (mp->m_flag & MBOX) |
2de8fc95 | 218 | if (send(mp, obuf, saveignore, NOSTR) < 0) { |
865dca9a | 219 | perror(mbox); |
07b0d286 EW |
220 | Fclose(ibuf); |
221 | Fclose(obuf); | |
222 | Fclose(fbuf); | |
865dca9a KS |
223 | return; |
224 | } | |
225 | ||
226 | /* | |
227 | * Copy the user's old mbox contents back | |
228 | * to the end of the stuff we just saved. | |
229 | * If we are appending, this is unnecessary. | |
230 | */ | |
231 | ||
232 | if (value("append") == NOSTR) { | |
233 | rewind(ibuf); | |
234 | c = getc(ibuf); | |
235 | while (c != EOF) { | |
2ee3bce2 | 236 | (void) putc(c, obuf); |
865dca9a KS |
237 | if (ferror(obuf)) |
238 | break; | |
239 | c = getc(ibuf); | |
240 | } | |
07b0d286 | 241 | Fclose(ibuf); |
865dca9a KS |
242 | fflush(obuf); |
243 | } | |
ed3b895e | 244 | trunc(obuf); |
865dca9a KS |
245 | if (ferror(obuf)) { |
246 | perror(mbox); | |
07b0d286 EW |
247 | Fclose(obuf); |
248 | Fclose(fbuf); | |
865dca9a KS |
249 | return; |
250 | } | |
07b0d286 | 251 | Fclose(obuf); |
865dca9a KS |
252 | if (mcount == 1) |
253 | printf("Saved 1 message in mbox\n"); | |
254 | else | |
255 | printf("Saved %d messages in mbox\n", mcount); | |
256 | ||
257 | /* | |
258 | * Now we are ready to copy back preserved files to | |
259 | * the system mailbox, if any were requested. | |
260 | */ | |
261 | ||
262 | if (p != 0) { | |
263 | writeback(rbuf); | |
07b0d286 | 264 | Fclose(fbuf); |
865dca9a KS |
265 | return; |
266 | } | |
267 | ||
268 | /* | |
269 | * Finally, remove his /usr/mail file. | |
270 | * If new mail has arrived, copy it back. | |
271 | */ | |
272 | ||
273 | cream: | |
274 | if (rbuf != NULL) { | |
07b0d286 | 275 | abuf = Fopen(mailname, "r+"); |
4e161d3b | 276 | if (abuf == NULL) |
865dca9a KS |
277 | goto newmail; |
278 | while ((c = getc(rbuf)) != EOF) | |
2ee3bce2 | 279 | (void) putc(c, abuf); |
07b0d286 | 280 | Fclose(rbuf); |
4e161d3b | 281 | trunc(abuf); |
07b0d286 | 282 | Fclose(abuf); |
865dca9a | 283 | alter(mailname); |
07b0d286 | 284 | Fclose(fbuf); |
865dca9a KS |
285 | return; |
286 | } | |
287 | demail(); | |
07b0d286 | 288 | Fclose(fbuf); |
865dca9a KS |
289 | return; |
290 | ||
291 | newmail: | |
292 | printf("Thou hast new mail.\n"); | |
cb674576 | 293 | if (fbuf != NULL) |
07b0d286 | 294 | Fclose(fbuf); |
865dca9a KS |
295 | } |
296 | ||
297 | /* | |
298 | * Preserve all the appropriate messages back in the system | |
299 | * mailbox, and print a nice message indicated how many were | |
300 | * saved. On any error, just return -1. Else return 0. | |
301 | * Incorporate the any new mail that we found. | |
302 | */ | |
865dca9a KS |
303 | writeback(res) |
304 | register FILE *res; | |
305 | { | |
306 | register struct message *mp; | |
307 | register int p, c; | |
308 | FILE *obuf; | |
309 | ||
310 | p = 0; | |
07b0d286 | 311 | if ((obuf = Fopen(mailname, "r+")) == NULL) { |
865dca9a KS |
312 | perror(mailname); |
313 | return(-1); | |
314 | } | |
315 | #ifndef APPEND | |
316 | if (res != NULL) | |
317 | while ((c = getc(res)) != EOF) | |
2ee3bce2 | 318 | (void) putc(c, obuf); |
865dca9a KS |
319 | #endif |
320 | for (mp = &message[0]; mp < &message[msgCount]; mp++) | |
321 | if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) { | |
322 | p++; | |
2de8fc95 | 323 | if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) { |
865dca9a | 324 | perror(mailname); |
07b0d286 | 325 | Fclose(obuf); |
865dca9a KS |
326 | return(-1); |
327 | } | |
328 | } | |
329 | #ifdef APPEND | |
330 | if (res != NULL) | |
331 | while ((c = getc(res)) != EOF) | |
2ee3bce2 | 332 | (void) putc(c, obuf); |
865dca9a KS |
333 | #endif |
334 | fflush(obuf); | |
ed3b895e | 335 | trunc(obuf); |
865dca9a KS |
336 | if (ferror(obuf)) { |
337 | perror(mailname); | |
07b0d286 | 338 | Fclose(obuf); |
865dca9a KS |
339 | return(-1); |
340 | } | |
341 | if (res != NULL) | |
07b0d286 EW |
342 | Fclose(res); |
343 | Fclose(obuf); | |
865dca9a KS |
344 | alter(mailname); |
345 | if (p == 1) | |
346 | printf("Held 1 message in %s\n", mailname); | |
347 | else | |
348 | printf("Held %d messages in %s\n", p, mailname); | |
349 | return(0); | |
350 | } | |
2ee3bce2 EW |
351 | |
352 | /* | |
353 | * Terminate an editing session by attempting to write out the user's | |
354 | * file from the temporary. Save any new stuff appended to the file. | |
355 | */ | |
356 | edstop() | |
357 | { | |
f629a181 | 358 | extern char *tmpdir; |
2ee3bce2 EW |
359 | register int gotcha, c; |
360 | register struct message *mp; | |
361 | FILE *obuf, *ibuf, *readstat; | |
362 | struct stat statb; | |
363 | char tempname[30]; | |
364 | char *mktemp(); | |
365 | ||
366 | if (readonly) | |
367 | return; | |
368 | holdsigs(); | |
369 | if (Tflag != NOSTR) { | |
07b0d286 | 370 | if ((readstat = Fopen(Tflag, "w")) == NULL) |
2ee3bce2 EW |
371 | Tflag = NOSTR; |
372 | } | |
373 | for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) { | |
374 | if (mp->m_flag & MNEW) { | |
375 | mp->m_flag &= ~MNEW; | |
376 | mp->m_flag |= MSTATUS; | |
377 | } | |
378 | if (mp->m_flag & (MODIFY|MDELETED|MSTATUS)) | |
379 | gotcha++; | |
380 | if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { | |
381 | char *id; | |
382 | ||
383 | if ((id = hfield("article-id", mp)) != NOSTR) | |
384 | fprintf(readstat, "%s\n", id); | |
385 | } | |
386 | } | |
387 | if (Tflag != NOSTR) | |
07b0d286 | 388 | Fclose(readstat); |
2ee3bce2 EW |
389 | if (!gotcha || Tflag != NOSTR) |
390 | goto done; | |
391 | ibuf = NULL; | |
392 | if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) { | |
f629a181 | 393 | strcpy(tempname, tmpdir); |
cc28d847 | 394 | strcat(tempname, "mboxXXXXXX"); |
2ee3bce2 | 395 | mktemp(tempname); |
07b0d286 | 396 | if ((obuf = Fopen(tempname, "w")) == NULL) { |
2ee3bce2 EW |
397 | perror(tempname); |
398 | relsesigs(); | |
399 | reset(0); | |
400 | } | |
07b0d286 | 401 | if ((ibuf = Fopen(mailname, "r")) == NULL) { |
2ee3bce2 | 402 | perror(mailname); |
07b0d286 | 403 | Fclose(obuf); |
a7585c01 | 404 | rm(tempname); |
2ee3bce2 EW |
405 | relsesigs(); |
406 | reset(0); | |
407 | } | |
408 | fseek(ibuf, mailsize, 0); | |
409 | while ((c = getc(ibuf)) != EOF) | |
410 | (void) putc(c, obuf); | |
07b0d286 EW |
411 | Fclose(ibuf); |
412 | Fclose(obuf); | |
413 | if ((ibuf = Fopen(tempname, "r")) == NULL) { | |
2ee3bce2 | 414 | perror(tempname); |
a7585c01 | 415 | rm(tempname); |
2ee3bce2 EW |
416 | relsesigs(); |
417 | reset(0); | |
418 | } | |
a7585c01 | 419 | rm(tempname); |
2ee3bce2 EW |
420 | } |
421 | printf("\"%s\" ", mailname); | |
422 | fflush(stdout); | |
07b0d286 | 423 | if ((obuf = Fopen(mailname, "r+")) == NULL) { |
2ee3bce2 EW |
424 | perror(mailname); |
425 | relsesigs(); | |
426 | reset(0); | |
427 | } | |
428 | trunc(obuf); | |
429 | c = 0; | |
430 | for (mp = &message[0]; mp < &message[msgCount]; mp++) { | |
431 | if ((mp->m_flag & MDELETED) != 0) | |
432 | continue; | |
433 | c++; | |
434 | if (send(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) { | |
435 | perror(mailname); | |
436 | relsesigs(); | |
437 | reset(0); | |
438 | } | |
439 | } | |
440 | gotcha = (c == 0 && ibuf == NULL); | |
441 | if (ibuf != NULL) { | |
442 | while ((c = getc(ibuf)) != EOF) | |
443 | (void) putc(c, obuf); | |
07b0d286 | 444 | Fclose(ibuf); |
2ee3bce2 EW |
445 | } |
446 | fflush(obuf); | |
447 | if (ferror(obuf)) { | |
448 | perror(mailname); | |
449 | relsesigs(); | |
450 | reset(0); | |
451 | } | |
07b0d286 | 452 | Fclose(obuf); |
2ee3bce2 | 453 | if (gotcha) { |
a7585c01 | 454 | rm(mailname); |
2ee3bce2 EW |
455 | printf("removed\n"); |
456 | } else | |
457 | printf("complete\n"); | |
458 | fflush(stdout); | |
459 | ||
460 | done: | |
461 | relsesigs(); | |
462 | } |