check buffer size.
[unix-history] / usr / src / usr.bin / mail / quit.c
CommitLineData
2ae9f53f 1#ifndef lint
4e161d3b 2static char sccsid[] = "@(#)quit.c 2.8 (Berkeley) %G%";
2ae9f53f 3#endif
865dca9a
KS
4
5#include "rcv.h"
6#include <sys/stat.h>
4e161d3b 7#include <sys/file.h>
865dca9a
KS
8
9/*
10 * Rcv -- receive mail rationally.
11 *
12 * Termination processing.
13 */
14
865dca9a
KS
15/*
16 * Save all of the undetermined messages at the top of "mbox"
17 * Save all untouched messages back in the system mailbox.
18 * Remove the system mailbox, if none saved there.
19 */
20
21quit()
22{
c2483c81 23 int mcount, p, modify, autohold, anystat, holdbit, nohold;
4e161d3b 24 FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
865dca9a
KS
25 register struct message *mp;
26 register int c;
27 extern char tempQuit[], tempResid[];
28 struct stat minfo;
f0d15113 29 char *id;
865dca9a 30
3ecebc0f
KS
31 /*
32 * If we are read only, we can't do anything,
33 * so just return quickly.
34 */
35
36 if (readonly)
37 return;
865dca9a
KS
38 /*
39 * See if there any messages to save in mbox. If no, we
40 * can save copying mbox to /tmp and back.
41 *
42 * Check also to see if any files need to be preserved.
43 * Delete all untouched messages to keep them out of mbox.
44 * If all the messages are to be preserved, just exit with
45 * a message.
46 *
47 * If the luser has sent mail to himself, refuse to do
48 * anything with the mailbox, unless mail locking works.
49 */
50
4e161d3b
RC
51 fbuf = fopen(mailname, "r");
52 if (fbuf == NULL)
53 goto newmail;
54 flock(fileno(fbuf), LOCK_EX);
865dca9a
KS
55#ifndef CANLOCK
56 if (selfsent) {
57 printf("You have new mail.\n");
4e161d3b 58 fclose(fbuf);
865dca9a
KS
59 return;
60 }
61#endif
62 rbuf = NULL;
4e161d3b 63 if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
865dca9a
KS
64 printf("New mail has arrived.\n");
65 rbuf = fopen(tempResid, "w");
865dca9a
KS
66 if (rbuf == NULL || fbuf == NULL)
67 goto newmail;
68#ifdef APPEND
69 fseek(fbuf, mailsize, 0);
70 while ((c = getc(fbuf)) != EOF)
71 putc(c, rbuf);
72#else
73 p = minfo.st_size - mailsize;
74 while (p-- > 0) {
75 c = getc(fbuf);
76 if (c == EOF)
77 goto newmail;
78 putc(c, rbuf);
79 }
80#endif
865dca9a
KS
81 fclose(rbuf);
82 if ((rbuf = fopen(tempResid, "r")) == NULL)
83 goto newmail;
84 remove(tempResid);
85 }
63e83a9b
KS
86
87 /*
88 * Adjust the message flags in each message.
89 */
90
91 anystat = 0;
252cba79
KS
92 autohold = value("hold") != NOSTR;
93 holdbit = autohold ? MPRESERVE : MBOX;
c2483c81
KS
94 nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
95 if (value("keepsave") != NOSTR)
96 nohold &= ~MSAVED;
865dca9a 97 for (mp = &message[0]; mp < &message[msgCount]; mp++) {
63e83a9b
KS
98 if (mp->m_flag & MNEW) {
99 mp->m_flag &= ~MNEW;
100 mp->m_flag |= MSTATUS;
101 }
102 if (mp->m_flag & MSTATUS)
103 anystat++;
865dca9a 104 if ((mp->m_flag & MTOUCH) == 0)
252cba79 105 mp->m_flag |= MPRESERVE;
c2483c81 106 if ((mp->m_flag & nohold) == 0)
252cba79 107 mp->m_flag |= holdbit;
865dca9a
KS
108 }
109 modify = 0;
f0d15113
KS
110 if (Tflag != NOSTR) {
111 if ((readstat = fopen(Tflag, "w")) == NULL)
112 Tflag = NOSTR;
113 }
865dca9a 114 for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
252cba79 115 if (mp->m_flag & MBOX)
865dca9a 116 c++;
252cba79 117 if (mp->m_flag & MPRESERVE)
865dca9a
KS
118 p++;
119 if (mp->m_flag & MODIFY)
120 modify++;
f0d15113
KS
121 if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
122 id = hfield("article-id", mp);
123 if (id != NOSTR)
124 fprintf(readstat, "%s\n", id);
125 }
865dca9a 126 }
f0d15113
KS
127 if (Tflag != NOSTR)
128 fclose(readstat);
63e83a9b 129 if (p == msgCount && !modify && !anystat) {
865dca9a
KS
130 if (p == 1)
131 printf("Held 1 message in %s\n", mailname);
132 else
133 printf("Held %2d messages in %s\n", p, mailname);
4e161d3b 134 fclose(fbuf);
865dca9a
KS
135 return;
136 }
137 if (c == 0) {
138 if (p != 0) {
139 writeback(rbuf);
4e161d3b 140 fclose(fbuf);
865dca9a
KS
141 return;
142 }
143 goto cream;
144 }
145
146 /*
147 * Create another temporary file and copy user's mbox file
148 * darin. If there is no mbox, copy nothing.
149 * If he has specified "append" don't copy his mailbox,
150 * just copy saveable entries at the end.
151 */
152
153 mcount = c;
154 if (value("append") == NOSTR) {
155 if ((obuf = fopen(tempQuit, "w")) == NULL) {
156 perror(tempQuit);
4e161d3b 157 fclose(fbuf);
865dca9a
KS
158 return;
159 }
160 if ((ibuf = fopen(tempQuit, "r")) == NULL) {
161 perror(tempQuit);
162 remove(tempQuit);
163 fclose(obuf);
4e161d3b 164 fclose(fbuf);
865dca9a
KS
165 return;
166 }
167 remove(tempQuit);
4e161d3b
RC
168 if ((abuf = fopen(mbox, "r")) != NULL) {
169 while ((c = getc(abuf)) != EOF)
865dca9a 170 putc(c, obuf);
4e161d3b 171 fclose(abuf);
865dca9a
KS
172 }
173 if (ferror(obuf)) {
174 perror(tempQuit);
175 fclose(ibuf);
176 fclose(obuf);
4e161d3b 177 fclose(fbuf);
865dca9a
KS
178 return;
179 }
180 fclose(obuf);
181 close(creat(mbox, 0600));
b1064dda 182 if ((obuf = fopen(mbox, "r+")) == NULL) {
865dca9a
KS
183 perror(mbox);
184 fclose(ibuf);
4e161d3b 185 fclose(fbuf);
865dca9a
KS
186 return;
187 }
188 }
189 if (value("append") != NOSTR)
190 if ((obuf = fopen(mbox, "a")) == NULL) {
191 perror(mbox);
4e161d3b 192 fclose(fbuf);
865dca9a
KS
193 return;
194 }
195 for (mp = &message[0]; mp < &message[msgCount]; mp++)
252cba79 196 if (mp->m_flag & MBOX)
c2146fa9 197 if (send(mp, obuf, 0) < 0) {
865dca9a
KS
198 perror(mbox);
199 fclose(ibuf);
200 fclose(obuf);
4e161d3b 201 fclose(fbuf);
865dca9a
KS
202 return;
203 }
204
205 /*
206 * Copy the user's old mbox contents back
207 * to the end of the stuff we just saved.
208 * If we are appending, this is unnecessary.
209 */
210
211 if (value("append") == NOSTR) {
212 rewind(ibuf);
213 c = getc(ibuf);
214 while (c != EOF) {
215 putc(c, obuf);
216 if (ferror(obuf))
217 break;
218 c = getc(ibuf);
219 }
220 fclose(ibuf);
221 fflush(obuf);
222 }
ed3b895e 223 trunc(obuf);
865dca9a
KS
224 if (ferror(obuf)) {
225 perror(mbox);
226 fclose(obuf);
4e161d3b 227 fclose(fbuf);
865dca9a
KS
228 return;
229 }
230 fclose(obuf);
231 if (mcount == 1)
232 printf("Saved 1 message in mbox\n");
233 else
234 printf("Saved %d messages in mbox\n", mcount);
235
236 /*
237 * Now we are ready to copy back preserved files to
238 * the system mailbox, if any were requested.
239 */
240
241 if (p != 0) {
242 writeback(rbuf);
4e161d3b 243 fclose(fbuf);
865dca9a
KS
244 return;
245 }
246
247 /*
248 * Finally, remove his /usr/mail file.
249 * If new mail has arrived, copy it back.
250 */
251
252cream:
253 if (rbuf != NULL) {
4e161d3b
RC
254 abuf = fopen(mailname, "r+");
255 if (abuf == NULL)
865dca9a
KS
256 goto newmail;
257 while ((c = getc(rbuf)) != EOF)
4e161d3b 258 putc(c, abuf);
865dca9a 259 fclose(rbuf);
4e161d3b
RC
260 trunc(abuf);
261 fclose(abuf);
865dca9a 262 alter(mailname);
4e161d3b 263 fclose(fbuf);
865dca9a
KS
264 return;
265 }
266 demail();
4e161d3b 267 fclose(fbuf);
865dca9a
KS
268 return;
269
270newmail:
271 printf("Thou hast new mail.\n");
4e161d3b 272 fclose(fbuf);
865dca9a
KS
273}
274
275/*
276 * Preserve all the appropriate messages back in the system
277 * mailbox, and print a nice message indicated how many were
278 * saved. On any error, just return -1. Else return 0.
279 * Incorporate the any new mail that we found.
280 */
865dca9a
KS
281writeback(res)
282 register FILE *res;
283{
284 register struct message *mp;
285 register int p, c;
286 FILE *obuf;
287
288 p = 0;
b1064dda 289 if ((obuf = fopen(mailname, "r+")) == NULL) {
865dca9a
KS
290 perror(mailname);
291 return(-1);
292 }
293#ifndef APPEND
294 if (res != NULL)
295 while ((c = getc(res)) != EOF)
296 putc(c, obuf);
297#endif
298 for (mp = &message[0]; mp < &message[msgCount]; mp++)
299 if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
300 p++;
c2146fa9 301 if (send(mp, obuf, 0) < 0) {
865dca9a
KS
302 perror(mailname);
303 fclose(obuf);
304 return(-1);
305 }
306 }
307#ifdef APPEND
308 if (res != NULL)
309 while ((c = getc(res)) != EOF)
310 putc(c, obuf);
311#endif
312 fflush(obuf);
ed3b895e 313 trunc(obuf);
865dca9a
KS
314 if (ferror(obuf)) {
315 perror(mailname);
316 fclose(obuf);
317 return(-1);
318 }
319 if (res != NULL)
320 fclose(res);
321 fclose(obuf);
322 alter(mailname);
323 if (p == 1)
324 printf("Held 1 message in %s\n", mailname);
325 else
326 printf("Held %d messages in %s\n", p, mailname);
327 return(0);
328}