off by one error in limit for general sockaddr.
[unix-history] / usr / src / usr.bin / mail / quit.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
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.
16 */
17
18#ifndef lint
19static char sccsid[] = "@(#)quit.c 5.13 (Berkeley) %G%";
20#endif /* not lint */
21
22#include "rcv.h"
23#include <sys/stat.h>
24#include <sys/file.h>
25
26/*
27 * Rcv -- receive mail rationally.
28 *
29 * Termination processing.
30 */
31
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
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{
54 int mcount, p, modify, autohold, anystat, holdbit, nohold;
55 FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
56 register struct message *mp;
57 register int c;
58 extern char tempQuit[], tempResid[];
59 struct stat minfo;
60 char *mbox;
61
62 /*
63 * If we are read only, we can't do anything,
64 * so just return quickly.
65 */
66 if (readonly)
67 return;
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
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.
85 */
86
87 fbuf = fopen(mailname, "r");
88 if (fbuf == NULL)
89 goto newmail;
90 flock(fileno(fbuf), LOCK_EX);
91 rbuf = NULL;
92 if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
93 printf("New mail has arrived.\n");
94 rbuf = fopen(tempResid, "w");
95 if (rbuf == NULL || fbuf == NULL)
96 goto newmail;
97#ifdef APPEND
98 fseek(fbuf, mailsize, 0);
99 while ((c = getc(fbuf)) != EOF)
100 (void) putc(c, rbuf);
101#else
102 p = minfo.st_size - mailsize;
103 while (p-- > 0) {
104 c = getc(fbuf);
105 if (c == EOF)
106 goto newmail;
107 (void) putc(c, rbuf);
108 }
109#endif
110 fclose(rbuf);
111 if ((rbuf = fopen(tempResid, "r")) == NULL)
112 goto newmail;
113 remove(tempResid);
114 }
115
116 /*
117 * Adjust the message flags in each message.
118 */
119
120 anystat = 0;
121 autohold = value("hold") != NOSTR;
122 holdbit = autohold ? MPRESERVE : MBOX;
123 nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
124 if (value("keepsave") != NOSTR)
125 nohold &= ~MSAVED;
126 for (mp = &message[0]; mp < &message[msgCount]; mp++) {
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++;
133 if ((mp->m_flag & MTOUCH) == 0)
134 mp->m_flag |= MPRESERVE;
135 if ((mp->m_flag & nohold) == 0)
136 mp->m_flag |= holdbit;
137 }
138 modify = 0;
139 if (Tflag != NOSTR) {
140 if ((readstat = fopen(Tflag, "w")) == NULL)
141 Tflag = NOSTR;
142 }
143 for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
144 if (mp->m_flag & MBOX)
145 c++;
146 if (mp->m_flag & MPRESERVE)
147 p++;
148 if (mp->m_flag & MODIFY)
149 modify++;
150 if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
151 char *id;
152
153 if ((id = hfield("article-id", mp)) != NOSTR)
154 fprintf(readstat, "%s\n", id);
155 }
156 }
157 if (Tflag != NOSTR)
158 fclose(readstat);
159 if (p == msgCount && !modify && !anystat) {
160 printf("Held %d message%s in %s\n",
161 p, p == 1 ? "" : "s", mailname);
162 fclose(fbuf);
163 return;
164 }
165 if (c == 0) {
166 if (p != 0) {
167 writeback(rbuf);
168 fclose(fbuf);
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
181 mbox = expand("&");
182 mcount = c;
183 if (value("append") == NOSTR) {
184 if ((obuf = fopen(tempQuit, "w")) == NULL) {
185 perror(tempQuit);
186 fclose(fbuf);
187 return;
188 }
189 if ((ibuf = fopen(tempQuit, "r")) == NULL) {
190 perror(tempQuit);
191 remove(tempQuit);
192 fclose(obuf);
193 fclose(fbuf);
194 return;
195 }
196 remove(tempQuit);
197 if ((abuf = fopen(mbox, "r")) != NULL) {
198 while ((c = getc(abuf)) != EOF)
199 (void) putc(c, obuf);
200 fclose(abuf);
201 }
202 if (ferror(obuf)) {
203 perror(tempQuit);
204 fclose(ibuf);
205 fclose(obuf);
206 fclose(fbuf);
207 return;
208 }
209 fclose(obuf);
210 close(creat(mbox, 0600));
211 if ((obuf = fopen(mbox, "r+")) == NULL) {
212 perror(mbox);
213 fclose(ibuf);
214 fclose(fbuf);
215 return;
216 }
217 }
218 if (value("append") != NOSTR) {
219 if ((obuf = fopen(mbox, "a")) == NULL) {
220 perror(mbox);
221 fclose(fbuf);
222 return;
223 }
224 fchmod(fileno(obuf), 0600);
225 }
226 for (mp = &message[0]; mp < &message[msgCount]; mp++)
227 if (mp->m_flag & MBOX)
228 if (send(mp, obuf, saveignore, NOSTR) < 0) {
229 perror(mbox);
230 fclose(ibuf);
231 fclose(obuf);
232 fclose(fbuf);
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) {
246 (void) putc(c, obuf);
247 if (ferror(obuf))
248 break;
249 c = getc(ibuf);
250 }
251 fclose(ibuf);
252 fflush(obuf);
253 }
254 trunc(obuf);
255 if (ferror(obuf)) {
256 perror(mbox);
257 fclose(obuf);
258 fclose(fbuf);
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);
274 fclose(fbuf);
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) {
285 abuf = fopen(mailname, "r+");
286 if (abuf == NULL)
287 goto newmail;
288 while ((c = getc(rbuf)) != EOF)
289 (void) putc(c, abuf);
290 fclose(rbuf);
291 trunc(abuf);
292 fclose(abuf);
293 alter(mailname);
294 fclose(fbuf);
295 return;
296 }
297 demail();
298 fclose(fbuf);
299 return;
300
301newmail:
302 printf("Thou hast new mail.\n");
303 if (fbuf != NULL)
304 fclose(fbuf);
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 */
313writeback(res)
314 register FILE *res;
315{
316 register struct message *mp;
317 register int p, c;
318 FILE *obuf;
319
320 p = 0;
321 if ((obuf = fopen(mailname, "r+")) == NULL) {
322 perror(mailname);
323 return(-1);
324 }
325#ifndef APPEND
326 if (res != NULL)
327 while ((c = getc(res)) != EOF)
328 (void) putc(c, obuf);
329#endif
330 for (mp = &message[0]; mp < &message[msgCount]; mp++)
331 if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
332 p++;
333 if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) {
334 perror(mailname);
335 fclose(obuf);
336 return(-1);
337 }
338 }
339#ifdef APPEND
340 if (res != NULL)
341 while ((c = getc(res)) != EOF)
342 (void) putc(c, obuf);
343#endif
344 fflush(obuf);
345 trunc(obuf);
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}
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) {
402 strcpy(tempname, _PATH_TMP);
403 strcat(tempname, "mboxXXXXXX");
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}