1*4fe1ef32Schristos /* $NetBSD: quit.c,v 1.29 2017/11/09 20:27:50 christos Exp $ */
288b833a7Schristos
361f28255Scgd /*
42cb5542fSderaadt * Copyright (c) 1980, 1993
52cb5542fSderaadt * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
1589aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
327c81c8f3Slukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3488b833a7Schristos #if 0
3519d35cbcStls static char sccsid[] = "@(#)quit.c 8.2 (Berkeley) 4/28/95";
3688b833a7Schristos #else
37*4fe1ef32Schristos __RCSID("$NetBSD: quit.c,v 1.29 2017/11/09 20:27:50 christos Exp $");
3888b833a7Schristos #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
4161f28255Scgd #include "rcv.h"
422cb5542fSderaadt #include "extern.h"
43f3098750Schristos #include "thread.h"
44ca13337dSchristos #include "sig.h"
4561f28255Scgd
4661f28255Scgd /*
4761f28255Scgd * Rcv -- receive mail rationally.
4861f28255Scgd *
4961f28255Scgd * Termination processing.
5061f28255Scgd */
5161f28255Scgd
5261f28255Scgd /*
5361f28255Scgd * The "quit" command.
5461f28255Scgd */
55ca286310Schristos /*ARGSUSED*/
56f3098750Schristos PUBLIC int
quitcmd(void * v __unused)578207b28aSchristos quitcmd(void *v __unused)
5861f28255Scgd {
5961f28255Scgd /*
6061f28255Scgd * If we are sourcing, then return 1 so execute() can handle it.
6161f28255Scgd * Otherwise, return -1 to abort command loop.
6261f28255Scgd */
6361f28255Scgd if (sourcing)
6461f28255Scgd return 1;
6561f28255Scgd return -1;
6661f28255Scgd }
6761f28255Scgd
6861f28255Scgd /*
69f3098750Schristos * Preserve all the appropriate messages back in the system
70f3098750Schristos * mailbox, and print a nice message indicated how many were
71f3098750Schristos * saved. On any error, just return -1. Else return 0.
72f3098750Schristos * Incorporate the any new mail that we found.
73f3098750Schristos */
74f3098750Schristos static int
writeback(FILE * res)75f3098750Schristos writeback(FILE *res)
76f3098750Schristos {
77f3098750Schristos struct message *mp;
78f3098750Schristos int p, c;
79f3098750Schristos FILE *obuf;
80f3098750Schristos
81f3098750Schristos p = 0;
82*4fe1ef32Schristos if ((obuf = Fopen(mailname, "ref+")) == NULL) {
83f3098750Schristos warn("%s", mailname);
84f3098750Schristos return -1;
85f3098750Schristos }
86f3098750Schristos #ifndef APPEND
87f3098750Schristos if (res != NULL) {
88f3098750Schristos while ((c = getc(res)) != EOF)
89f3098750Schristos (void)putc(c, obuf);
90f3098750Schristos (void)fflush(obuf);
91f3098750Schristos if (ferror(obuf)) {
92f3098750Schristos warn("%s", mailname);
93f3098750Schristos (void)Fclose(obuf);
94f3098750Schristos return -1;
95f3098750Schristos }
96f3098750Schristos }
97f3098750Schristos #endif
98f3098750Schristos for (mp = get_message(1); mp; mp = next_message(mp))
99f3098750Schristos if ((mp->m_flag & MPRESERVE) || (mp->m_flag & MTOUCH)==0) {
100f3098750Schristos p++;
101f3098750Schristos if (sendmessage(mp, obuf, NULL, NULL, NULL) < 0) {
102f3098750Schristos warn("%s", mailname);
103f3098750Schristos (void)Fclose(obuf);
104f3098750Schristos return -1;
105f3098750Schristos }
106f3098750Schristos }
107f3098750Schristos #ifdef APPEND
108f3098750Schristos if (res != NULL)
109f3098750Schristos while ((c = getc(res)) != EOF)
110f3098750Schristos (void)putc(c, obuf);
111f3098750Schristos #endif
112f3098750Schristos (void)fflush(obuf);
113f3098750Schristos if (!ferror(obuf))
114f3098750Schristos trunc(obuf); /* XXX or should we truncate? */
115f3098750Schristos if (ferror(obuf)) {
116f3098750Schristos warn("%s", mailname);
117f3098750Schristos (void)Fclose(obuf);
118f3098750Schristos return -1;
119f3098750Schristos }
120f3098750Schristos if (res != NULL)
121f3098750Schristos (void)Fclose(res);
122f3098750Schristos (void)Fclose(obuf);
123f3098750Schristos alter(mailname);
124f3098750Schristos if (p == 1)
125f3098750Schristos (void)printf("Held 1 message in %s\n", mailname);
126f3098750Schristos else
127f3098750Schristos (void)printf("Held %d messages in %s\n", p, mailname);
128f3098750Schristos return 0;
129f3098750Schristos }
130f3098750Schristos
131f3098750Schristos /*
132f3098750Schristos * Terminate an editing session by attempting to write out the user's
133f3098750Schristos * file from the temporary. Save any new stuff appended to the file.
134f3098750Schristos */
135f3098750Schristos static void
edstop(jmp_buf jmpbuf)136ca13337dSchristos edstop(jmp_buf jmpbuf)
137f3098750Schristos {
138f3098750Schristos int gotcha, c;
139f3098750Schristos struct message *mp;
140ca13337dSchristos FILE *obuf;
141ca13337dSchristos FILE *ibuf;
142ca13337dSchristos FILE *readstat;
143f3098750Schristos struct stat statb;
144f3098750Schristos char tempname[PATHSIZE];
145f3098750Schristos int fd;
146f3098750Schristos
147ca13337dSchristos sig_check();
148f3098750Schristos if (readonly)
149f3098750Schristos return;
150ca13337dSchristos
151ca13337dSchristos readstat = NULL;
152f3098750Schristos if (Tflag != NULL) {
153*4fe1ef32Schristos if ((readstat = Fopen(Tflag, "wef")) == NULL)
154f3098750Schristos Tflag = NULL;
155f3098750Schristos }
156f3098750Schristos for (mp = get_message(1), gotcha = 0; mp; mp = next_message(mp)) {
157f3098750Schristos if (mp->m_flag & MNEW) {
158f3098750Schristos mp->m_flag &= ~MNEW;
159f3098750Schristos mp->m_flag |= MSTATUS;
160f3098750Schristos }
161f3098750Schristos if (mp->m_flag & (MMODIFY|MDELETED|MSTATUS))
162f3098750Schristos gotcha++;
163f3098750Schristos if (Tflag != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
164f3098750Schristos char *id;
165f3098750Schristos
166f3098750Schristos if ((id = hfield("article-id", mp)) != NULL)
167f3098750Schristos (void)fprintf(readstat, "%s\n", id);
168f3098750Schristos }
169f3098750Schristos }
170f3098750Schristos if (Tflag != NULL)
171f3098750Schristos (void)Fclose(readstat);
172f3098750Schristos if (!gotcha || Tflag != NULL)
173f3098750Schristos goto done;
174f3098750Schristos ibuf = NULL;
175f3098750Schristos if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
176f3098750Schristos (void)snprintf(tempname, sizeof(tempname),
177f3098750Schristos "%s/mbox.XXXXXXXXXX", tmpdir);
178f3098750Schristos if ((fd = mkstemp(tempname)) == -1 ||
179*4fe1ef32Schristos (obuf = Fdopen(fd, "wef")) == NULL) {
180f3098750Schristos warn("%s", tempname);
181f3098750Schristos if (fd != -1)
182f3098750Schristos (void)close(fd);
183ca13337dSchristos sig_release();
184ca13337dSchristos longjmp(jmpbuf, -11);
185f3098750Schristos }
186*4fe1ef32Schristos if ((ibuf = Fopen(mailname, "ref")) == NULL) {
187f3098750Schristos warn("%s", mailname);
188f3098750Schristos (void)Fclose(obuf);
189f3098750Schristos (void)rm(tempname);
190ca13337dSchristos sig_release();
191ca13337dSchristos longjmp(jmpbuf, -1);
192f3098750Schristos }
193f3098750Schristos (void)fseek(ibuf, (long)mailsize, 0);
194f3098750Schristos while ((c = getc(ibuf)) != EOF)
195f3098750Schristos (void)putc(c, obuf);
196f3098750Schristos (void)fflush(obuf);
197f3098750Schristos if (ferror(obuf)) {
198f3098750Schristos warn("%s", tempname);
199f3098750Schristos (void)Fclose(obuf);
200f3098750Schristos (void)Fclose(ibuf);
201f3098750Schristos (void)rm(tempname);
202ca13337dSchristos sig_release();
203ca13337dSchristos longjmp(jmpbuf, -1);
204f3098750Schristos }
205f3098750Schristos (void)Fclose(ibuf);
206f3098750Schristos (void)Fclose(obuf);
207*4fe1ef32Schristos if ((ibuf = Fopen(tempname, "ref")) == NULL) {
208f3098750Schristos warn("%s", tempname);
209f3098750Schristos (void)rm(tempname);
210ca13337dSchristos sig_release();
211ca13337dSchristos longjmp(jmpbuf, -1);
212f3098750Schristos }
213f3098750Schristos (void)rm(tempname);
214f3098750Schristos }
215f3098750Schristos (void)printf("\"%s\" ", mailname);
216f3098750Schristos (void)fflush(stdout);
217*4fe1ef32Schristos if ((obuf = Fopen(mailname, "ref+")) == NULL) {
218f3098750Schristos warn("%s", mailname);
219ca13337dSchristos sig_release();
220ca13337dSchristos longjmp(jmpbuf, -1);
221f3098750Schristos }
222f3098750Schristos trunc(obuf);
223f3098750Schristos c = 0;
224f3098750Schristos for (mp = get_message(1); mp; mp = next_message(mp)) {
225f3098750Schristos if ((mp->m_flag & MDELETED) != 0)
226f3098750Schristos continue;
227f3098750Schristos c++;
228f3098750Schristos if (sendmessage(mp, obuf, NULL, NULL, NULL) < 0) {
229f3098750Schristos warn("%s", mailname);
230ca13337dSchristos sig_release();
231ca13337dSchristos longjmp(jmpbuf, -1);
232f3098750Schristos }
233f3098750Schristos }
234f3098750Schristos gotcha = (c == 0 && ibuf == NULL);
235f3098750Schristos if (ibuf != NULL) {
236f3098750Schristos while ((c = getc(ibuf)) != EOF)
237f3098750Schristos (void)putc(c, obuf);
238f3098750Schristos (void)Fclose(ibuf);
239f3098750Schristos }
240f3098750Schristos (void)fflush(obuf);
241f3098750Schristos if (ferror(obuf)) {
242f3098750Schristos warn("%s", mailname);
243ca13337dSchristos sig_release();
244ca13337dSchristos longjmp(jmpbuf, -1);
245f3098750Schristos }
246f3098750Schristos (void)Fclose(obuf);
247f3098750Schristos if (gotcha) {
248f3098750Schristos (void)rm(mailname);
249f3098750Schristos (void)printf("removed\n");
250f3098750Schristos } else
251f3098750Schristos (void)printf("complete\n");
252f3098750Schristos (void)fflush(stdout);
253f3098750Schristos
254f3098750Schristos done:
255ca13337dSchristos sig_release();
256ca13337dSchristos sig_check();
257f3098750Schristos }
258f3098750Schristos
259f3098750Schristos /*
26061f28255Scgd * Save all of the undetermined messages at the top of "mbox"
26161f28255Scgd * Save all untouched messages back in the system mailbox.
26261f28255Scgd * Remove the system mailbox, if none saved there.
26361f28255Scgd */
264f3098750Schristos PUBLIC void
quit(jmp_buf jmpbuf)265ca13337dSchristos quit(jmp_buf jmpbuf)
26661f28255Scgd {
26761f28255Scgd int mcount, p, modify, autohold, anystat, holdbit, nohold;
268ca13337dSchristos _Bool append;
269ca13337dSchristos FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
2707c81c8f3Slukem struct message *mp;
27169047878Swiz int c, fd;
27261f28255Scgd struct stat minfo;
273ece0fd5cSchristos const char *mbox;
2744361c515Swiz char tempname[PATHSIZE];
27561f28255Scgd
276ca13337dSchristos #ifdef __GNUC__ /* XXX gcc -Wuninitialized */
277ca13337dSchristos ibuf = NULL;
278ca13337dSchristos readstat = NULL;
279a444ae60Sbad #endif
28061f28255Scgd /*
28161f28255Scgd * If we are read only, we can't do anything,
28261f28255Scgd * so just return quickly.
28361f28255Scgd */
28461f28255Scgd if (readonly)
28561f28255Scgd return;
286f3098750Schristos
287f3098750Schristos #ifdef THREAD_SUPPORT
288f3098750Schristos (void)showtagscmd(NULL); /* make sure we see tagged messages */
289f3098750Schristos (void)unthreadcmd(NULL);
290f3098750Schristos #endif
29161f28255Scgd /*
29261f28255Scgd * If editing (not reading system mail box), then do the work
29361f28255Scgd * in edstop()
29461f28255Scgd */
29561f28255Scgd if (edit) {
296ca13337dSchristos edstop(jmpbuf);
29761f28255Scgd return;
29861f28255Scgd }
29961f28255Scgd
30061f28255Scgd /*
30161f28255Scgd * See if there any messages to save in mbox. If no, we
30261f28255Scgd * can save copying mbox to /tmp and back.
30361f28255Scgd *
30461f28255Scgd * Check also to see if any files need to be preserved.
30561f28255Scgd * Delete all untouched messages to keep them out of mbox.
30661f28255Scgd * If all the messages are to be preserved, just exit with
30761f28255Scgd * a message.
30861f28255Scgd */
30961f28255Scgd
310*4fe1ef32Schristos fbuf = Fopen(mailname, "ref");
31161f28255Scgd if (fbuf == NULL)
31261f28255Scgd goto newmail;
31388b833a7Schristos if (flock(fileno(fbuf), LOCK_EX) == -1) {
31488b833a7Schristos nolock:
31569047878Swiz warn("Unable to lock mailbox");
316ca286310Schristos (void)Fclose(fbuf);
31788b833a7Schristos return;
31888b833a7Schristos }
31988b833a7Schristos if (dot_lock(mailname, 1, stdout, ".") == -1)
32088b833a7Schristos goto nolock;
32161f28255Scgd rbuf = NULL;
32261f28255Scgd if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
323ca286310Schristos (void)printf("New mail has arrived.\n");
3249c3d74c3Swiz (void)snprintf(tempname, sizeof(tempname),
3259c3d74c3Swiz "%s/mail.RqXXXXXXXXXX", tmpdir);
3269c3d74c3Swiz if ((fd = mkstemp(tempname)) == -1 ||
327*4fe1ef32Schristos (rbuf = Fdopen(fd, "wef")) == NULL) {
3289c3d74c3Swiz if (fd != -1)
329ca286310Schristos (void)close(fd);
33061f28255Scgd goto newmail;
3319c3d74c3Swiz }
33261f28255Scgd #ifdef APPEND
333ca286310Schristos (void)fseek(fbuf, (long)mailsize, 0);
33461f28255Scgd while ((c = getc(fbuf)) != EOF)
33561f28255Scgd (void)putc(c, rbuf);
33661f28255Scgd #else
33761f28255Scgd p = minfo.st_size - mailsize;
33861f28255Scgd while (p-- > 0) {
33961f28255Scgd c = getc(fbuf);
34061f28255Scgd if (c == EOF)
34161f28255Scgd goto newmail;
34261f28255Scgd (void)putc(c, rbuf);
34361f28255Scgd }
34461f28255Scgd #endif
3452f2497e5Sbad (void)fflush(rbuf);
3462f2497e5Sbad if (ferror(rbuf)) {
3479c3d74c3Swiz warn("%s", tempname);
348ca286310Schristos (void)Fclose(rbuf);
349ca286310Schristos (void)Fclose(fbuf);
3502f2497e5Sbad dot_unlock(mailname);
3512f2497e5Sbad return;
3522f2497e5Sbad }
353ca286310Schristos (void)Fclose(rbuf);
354*4fe1ef32Schristos if ((rbuf = Fopen(tempname, "ref")) == NULL)
35561f28255Scgd goto newmail;
356ca286310Schristos (void)rm(tempname);
35761f28255Scgd }
35861f28255Scgd
35961f28255Scgd /*
36061f28255Scgd * Adjust the message flags in each message.
36161f28255Scgd */
36261f28255Scgd
36361f28255Scgd anystat = 0;
364f3098750Schristos autohold = value(ENAME_HOLD) != NULL;
36561f28255Scgd holdbit = autohold ? MPRESERVE : MBOX;
36661f28255Scgd nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
367f3098750Schristos if (value(ENAME_KEEPSAVE) != NULL)
36861f28255Scgd nohold &= ~MSAVED;
369f3098750Schristos for (mp = get_message(1); mp; mp = next_message(mp)) {
37061f28255Scgd if (mp->m_flag & MNEW) {
37161f28255Scgd mp->m_flag &= ~MNEW;
37261f28255Scgd mp->m_flag |= MSTATUS;
37361f28255Scgd }
37461f28255Scgd if (mp->m_flag & MSTATUS)
37561f28255Scgd anystat++;
37661f28255Scgd if ((mp->m_flag & MTOUCH) == 0)
37761f28255Scgd mp->m_flag |= MPRESERVE;
37861f28255Scgd if ((mp->m_flag & nohold) == 0)
37961f28255Scgd mp->m_flag |= holdbit;
38061f28255Scgd }
38161f28255Scgd modify = 0;
382ab850155Swiz if (Tflag != NULL) {
383*4fe1ef32Schristos if ((readstat = Fopen(Tflag, "wef")) == NULL)
384ab850155Swiz Tflag = NULL;
38561f28255Scgd }
386f3098750Schristos for (c = 0, p = 0, mp = get_message(1); mp; mp = next_message(mp)) {
38761f28255Scgd if (mp->m_flag & MBOX)
38861f28255Scgd c++;
38961f28255Scgd if (mp->m_flag & MPRESERVE)
39061f28255Scgd p++;
391f3098750Schristos if (mp->m_flag & MMODIFY)
39261f28255Scgd modify++;
393ab850155Swiz if (Tflag != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
39461f28255Scgd char *id;
39561f28255Scgd
396ab850155Swiz if ((id = hfield("article-id", mp)) != NULL)
397ca286310Schristos (void)fprintf(readstat, "%s\n", id);
39861f28255Scgd }
39961f28255Scgd }
400ab850155Swiz if (Tflag != NULL)
401ca286310Schristos (void)Fclose(readstat);
402f3098750Schristos if (p == get_msgCount() && !modify && !anystat) {
403ca286310Schristos (void)printf("Held %d message%s in %s\n",
40461f28255Scgd p, p == 1 ? "" : "s", mailname);
405ca286310Schristos (void)Fclose(fbuf);
40688b833a7Schristos dot_unlock(mailname);
40761f28255Scgd return;
40861f28255Scgd }
40961f28255Scgd if (c == 0) {
41061f28255Scgd if (p != 0) {
411ca286310Schristos (void)writeback(rbuf);
412ca286310Schristos (void)Fclose(fbuf);
41388b833a7Schristos dot_unlock(mailname);
41461f28255Scgd return;
41561f28255Scgd }
41661f28255Scgd goto cream;
41761f28255Scgd }
41861f28255Scgd
41961f28255Scgd /*
42061f28255Scgd * Create another temporary file and copy user's mbox file
42161f28255Scgd * darin. If there is no mbox, copy nothing.
42261f28255Scgd * If he has specified "append" don't copy his mailbox,
42361f28255Scgd * just copy saveable entries at the end.
42461f28255Scgd */
42561f28255Scgd
42661f28255Scgd mbox = expand("&");
42761f28255Scgd mcount = c;
428ca13337dSchristos append = value(ENAME_APPEND) != NULL;
429ca13337dSchristos if (!append) {
4304361c515Swiz (void)snprintf(tempname, sizeof(tempname),
4314361c515Swiz "%s/mail.RmXXXXXXXXXX", tmpdir);
4324361c515Swiz if ((fd = mkstemp(tempname)) == -1 ||
433*4fe1ef32Schristos (obuf = Fdopen(fd, "wef")) == NULL) {
4344361c515Swiz warn("%s", tempname);
43569047878Swiz if (fd != -1)
436ca286310Schristos (void)close(fd);
437ca286310Schristos (void)Fclose(fbuf);
43888b833a7Schristos dot_unlock(mailname);
43961f28255Scgd return;
44061f28255Scgd }
441*4fe1ef32Schristos if ((ibuf = Fopen(tempname, "ref")) == NULL) {
4424361c515Swiz warn("%s", tempname);
443ca286310Schristos (void)rm(tempname);
444ca286310Schristos (void)Fclose(obuf);
445ca286310Schristos (void)Fclose(fbuf);
44688b833a7Schristos dot_unlock(mailname);
44761f28255Scgd return;
44861f28255Scgd }
449ca286310Schristos (void)rm(tempname);
450*4fe1ef32Schristos if ((abuf = Fopen(mbox, "ref")) != NULL) {
45161f28255Scgd while ((c = getc(abuf)) != EOF)
45261f28255Scgd (void)putc(c, obuf);
453ca286310Schristos (void)Fclose(abuf);
45461f28255Scgd }
45561f28255Scgd if (ferror(obuf)) {
4564361c515Swiz warn("%s", tempname);
457ca286310Schristos (void)Fclose(ibuf);
458ca286310Schristos (void)Fclose(obuf);
459ca286310Schristos (void)Fclose(fbuf);
46088b833a7Schristos dot_unlock(mailname);
46161f28255Scgd return;
46261f28255Scgd }
463ca286310Schristos (void)Fclose(obuf);
4644871d79cSchristos if ((fd = creat(mbox, 0600)) != -1)
46585576ae0Schristos (void)close(fd);
466*4fe1ef32Schristos if ((obuf = Fopen(mbox, "ref+")) == NULL) {
46769047878Swiz warn("%s", mbox);
468ca286310Schristos (void)Fclose(ibuf);
469ca286310Schristos (void)Fclose(fbuf);
47088b833a7Schristos dot_unlock(mailname);
47161f28255Scgd return;
47261f28255Scgd }
47361f28255Scgd }
47488b833a7Schristos else {
475*4fe1ef32Schristos if ((obuf = Fopen(mbox, "aef")) == NULL) {
47669047878Swiz warn("%s", mbox);
477ca286310Schristos (void)Fclose(fbuf);
47888b833a7Schristos dot_unlock(mailname);
47961f28255Scgd return;
48061f28255Scgd }
481ca286310Schristos (void)fchmod(fileno(obuf), 0600);
48261f28255Scgd }
483f3098750Schristos for (mp = get_message(1); mp; mp = next_message(mp))
48461f28255Scgd if (mp->m_flag & MBOX)
4858207b28aSchristos if (sendmessage(mp, obuf, saveignore, NULL, NULL) < 0) {
48669047878Swiz warn("%s", mbox);
487ca13337dSchristos if (!append)
488ca286310Schristos (void)Fclose(ibuf);
489ca286310Schristos (void)Fclose(obuf);
490ca286310Schristos (void)Fclose(fbuf);
49188b833a7Schristos dot_unlock(mailname);
49261f28255Scgd return;
49361f28255Scgd }
49461f28255Scgd
49561f28255Scgd /*
49661f28255Scgd * Copy the user's old mbox contents back
49761f28255Scgd * to the end of the stuff we just saved.
49861f28255Scgd * If we are appending, this is unnecessary.
49961f28255Scgd */
50061f28255Scgd
501ca13337dSchristos if (!append) {
50261f28255Scgd rewind(ibuf);
50361f28255Scgd c = getc(ibuf);
50461f28255Scgd while (c != EOF) {
50561f28255Scgd (void)putc(c, obuf);
50661f28255Scgd if (ferror(obuf))
50761f28255Scgd break;
50861f28255Scgd c = getc(ibuf);
50961f28255Scgd }
510ca286310Schristos (void)Fclose(ibuf);
51161f28255Scgd }
512ca286310Schristos (void)fflush(obuf);
5132f2497e5Sbad if (!ferror(obuf))
5142f2497e5Sbad trunc(obuf); /* XXX or should we truncate? */
51561f28255Scgd if (ferror(obuf)) {
51669047878Swiz warn("%s", mbox);
517ca286310Schristos (void)Fclose(obuf);
518ca286310Schristos (void)Fclose(fbuf);
51988b833a7Schristos dot_unlock(mailname);
52061f28255Scgd return;
52161f28255Scgd }
522ca286310Schristos (void)Fclose(obuf);
52361f28255Scgd if (mcount == 1)
524ca286310Schristos (void)printf("Saved 1 message in mbox\n");
52561f28255Scgd else
526ca286310Schristos (void)printf("Saved %d messages in mbox\n", mcount);
52761f28255Scgd
52861f28255Scgd /*
52961f28255Scgd * Now we are ready to copy back preserved files to
53061f28255Scgd * the system mailbox, if any were requested.
53161f28255Scgd */
53261f28255Scgd
53361f28255Scgd if (p != 0) {
534ca286310Schristos (void)writeback(rbuf);
535ca286310Schristos (void)Fclose(fbuf);
53688b833a7Schristos dot_unlock(mailname);
53761f28255Scgd return;
53861f28255Scgd }
53961f28255Scgd
54061f28255Scgd /*
54169047878Swiz * Finally, remove his /var/mail file.
54261f28255Scgd * If new mail has arrived, copy it back.
54361f28255Scgd */
54461f28255Scgd
54561f28255Scgd cream:
54661f28255Scgd if (rbuf != NULL) {
547*4fe1ef32Schristos abuf = Fopen(mailname, "ref+");
54861f28255Scgd if (abuf == NULL)
54961f28255Scgd goto newmail;
55061f28255Scgd while ((c = getc(rbuf)) != EOF)
55161f28255Scgd (void)putc(c, abuf);
5522f2497e5Sbad (void)fflush(abuf);
553d78ba354Sbad if (ferror(abuf)) {
55469047878Swiz warn("%s", mailname);
555ca286310Schristos (void)Fclose(abuf);
556ca286310Schristos (void)Fclose(fbuf);
5572f2497e5Sbad dot_unlock(mailname);
5582f2497e5Sbad return;
5592f2497e5Sbad }
560ca286310Schristos (void)Fclose(rbuf);
56161f28255Scgd trunc(abuf);
562ca286310Schristos (void)Fclose(abuf);
56361f28255Scgd alter(mailname);
564ca286310Schristos (void)Fclose(fbuf);
56588b833a7Schristos dot_unlock(mailname);
56661f28255Scgd return;
56761f28255Scgd }
56861f28255Scgd demail();
569ca286310Schristos (void)Fclose(fbuf);
57088b833a7Schristos dot_unlock(mailname);
57161f28255Scgd return;
57261f28255Scgd
57361f28255Scgd newmail:
574ca286310Schristos (void)printf("Thou hast new mail.\n");
57588b833a7Schristos if (fbuf != NULL) {
576ca286310Schristos (void)Fclose(fbuf);
57788b833a7Schristos dot_unlock(mailname);
57888b833a7Schristos }
57961f28255Scgd }
580