add support for converting to and checking new inode format filesystems;
[unix-history] / usr / src / usr.bin / mail / quit.c
CommitLineData
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 9static 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 */
25quitcmd()
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
42quit()
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
273cream:
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
291newmail:
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
303writeback(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 */
356edstop()
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
460done:
461 relsesigs();
462}