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