1 /* $NetBSD: quit.c,v 1.26 2006/11/28 18:45:32 christos Exp $ */
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)quit.c 8.2 (Berkeley) 4/28/95";
37 __RCSID("$NetBSD: quit.c,v 1.26 2006/11/28 18:45:32 christos Exp $");
47 * Rcv -- receive mail rationally.
49 * Termination processing.
57 quitcmd(void *v __unused
)
60 * If we are sourcing, then return 1 so execute() can handle it.
61 * Otherwise, return -1 to abort command loop.
69 * Preserve all the appropriate messages back in the system
70 * mailbox, and print a nice message indicated how many were
71 * saved. On any error, just return -1. Else return 0.
72 * Incorporate the any new mail that we found.
82 if ((obuf
= Fopen(mailname
, "r+")) == NULL
) {
88 while ((c
= getc(res
)) != EOF
)
98 for (mp
= get_message(1); mp
; mp
= next_message(mp
))
99 if ((mp
->m_flag
& MPRESERVE
) || (mp
->m_flag
& MTOUCH
)==0) {
101 if (sendmessage(mp
, obuf
, NULL
, NULL
, NULL
) < 0) {
102 warn("%s", mailname
);
109 while ((c
= getc(res
)) != EOF
)
114 trunc(obuf
); /* XXX or should we truncate? */
116 warn("%s", mailname
);
125 (void)printf("Held 1 message in %s\n", mailname
);
127 (void)printf("Held %d messages in %s\n", p
, mailname
);
132 * Terminate an editing session by attempting to write out the user's
133 * file from the temporary. Save any new stuff appended to the file.
136 edstop(jmp_buf jmpbuf
)
144 char tempname
[PATHSIZE
];
153 if ((readstat
= Fopen(Tflag
, "w")) == NULL
)
156 for (mp
= get_message(1), gotcha
= 0; mp
; mp
= next_message(mp
)) {
157 if (mp
->m_flag
& MNEW
) {
159 mp
->m_flag
|= MSTATUS
;
161 if (mp
->m_flag
& (MMODIFY
|MDELETED
|MSTATUS
))
163 if (Tflag
!= NULL
&& (mp
->m_flag
& (MREAD
|MDELETED
)) != 0) {
166 if ((id
= hfield("article-id", mp
)) != NULL
)
167 (void)fprintf(readstat
, "%s\n", id
);
171 (void)Fclose(readstat
);
172 if (!gotcha
|| Tflag
!= NULL
)
175 if (stat(mailname
, &statb
) >= 0 && statb
.st_size
> mailsize
) {
176 (void)snprintf(tempname
, sizeof(tempname
),
177 "%s/mbox.XXXXXXXXXX", tmpdir
);
178 if ((fd
= mkstemp(tempname
)) == -1 ||
179 (obuf
= Fdopen(fd
, "w")) == NULL
) {
180 warn("%s", tempname
);
184 longjmp(jmpbuf
, -11);
186 if ((ibuf
= Fopen(mailname
, "r")) == NULL
) {
187 warn("%s", mailname
);
193 (void)fseek(ibuf
, (long)mailsize
, 0);
194 while ((c
= getc(ibuf
)) != EOF
)
198 warn("%s", tempname
);
207 if ((ibuf
= Fopen(tempname
, "r")) == NULL
) {
208 warn("%s", tempname
);
215 (void)printf("\"%s\" ", mailname
);
216 (void)fflush(stdout
);
217 if ((obuf
= Fopen(mailname
, "r+")) == NULL
) {
218 warn("%s", mailname
);
224 for (mp
= get_message(1); mp
; mp
= next_message(mp
)) {
225 if ((mp
->m_flag
& MDELETED
) != 0)
228 if (sendmessage(mp
, obuf
, NULL
, NULL
, NULL
) < 0) {
229 warn("%s", mailname
);
234 gotcha
= (c
== 0 && ibuf
== NULL
);
236 while ((c
= getc(ibuf
)) != EOF
)
242 warn("%s", mailname
);
249 (void)printf("removed\n");
251 (void)printf("complete\n");
252 (void)fflush(stdout
);
260 * Save all of the undetermined messages at the top of "mbox"
261 * Save all untouched messages back in the system mailbox.
262 * Remove the system mailbox, if none saved there.
267 int mcount
, p
, modify
, autohold
, anystat
, holdbit
, nohold
;
269 FILE *ibuf
, *obuf
, *fbuf
, *rbuf
, *readstat
, *abuf
;
274 char tempname
[PATHSIZE
];
276 #ifdef __GNUC__ /* XXX gcc -Wuninitialized */
281 * If we are read only, we can't do anything,
282 * so just return quickly.
287 #ifdef THREAD_SUPPORT
288 (void)showtagscmd(NULL
); /* make sure we see tagged messages */
289 (void)unthreadcmd(NULL
);
292 * If editing (not reading system mail box), then do the work
301 * See if there any messages to save in mbox. If no, we
302 * can save copying mbox to /tmp and back.
304 * Check also to see if any files need to be preserved.
305 * Delete all untouched messages to keep them out of mbox.
306 * If all the messages are to be preserved, just exit with
310 fbuf
= Fopen(mailname
, "r");
313 if (flock(fileno(fbuf
), LOCK_EX
) == -1) {
315 warn("Unable to lock mailbox");
319 if (dot_lock(mailname
, 1, stdout
, ".") == -1)
322 if (fstat(fileno(fbuf
), &minfo
) >= 0 && minfo
.st_size
> mailsize
) {
323 (void)printf("New mail has arrived.\n");
324 (void)snprintf(tempname
, sizeof(tempname
),
325 "%s/mail.RqXXXXXXXXXX", tmpdir
);
326 if ((fd
= mkstemp(tempname
)) == -1 ||
327 (rbuf
= Fdopen(fd
, "w")) == NULL
) {
333 (void)fseek(fbuf
, (long)mailsize
, 0);
334 while ((c
= getc(fbuf
)) != EOF
)
337 p
= minfo
.st_size
- mailsize
;
347 warn("%s", tempname
);
350 dot_unlock(mailname
);
354 if ((rbuf
= Fopen(tempname
, "r")) == NULL
)
360 * Adjust the message flags in each message.
364 autohold
= value(ENAME_HOLD
) != NULL
;
365 holdbit
= autohold
? MPRESERVE
: MBOX
;
366 nohold
= MBOX
|MSAVED
|MDELETED
|MPRESERVE
;
367 if (value(ENAME_KEEPSAVE
) != NULL
)
369 for (mp
= get_message(1); mp
; mp
= next_message(mp
)) {
370 if (mp
->m_flag
& MNEW
) {
372 mp
->m_flag
|= MSTATUS
;
374 if (mp
->m_flag
& MSTATUS
)
376 if ((mp
->m_flag
& MTOUCH
) == 0)
377 mp
->m_flag
|= MPRESERVE
;
378 if ((mp
->m_flag
& nohold
) == 0)
379 mp
->m_flag
|= holdbit
;
383 if ((readstat
= Fopen(Tflag
, "w")) == NULL
)
386 for (c
= 0, p
= 0, mp
= get_message(1); mp
; mp
= next_message(mp
)) {
387 if (mp
->m_flag
& MBOX
)
389 if (mp
->m_flag
& MPRESERVE
)
391 if (mp
->m_flag
& MMODIFY
)
393 if (Tflag
!= NULL
&& (mp
->m_flag
& (MREAD
|MDELETED
)) != 0) {
396 if ((id
= hfield("article-id", mp
)) != NULL
)
397 (void)fprintf(readstat
, "%s\n", id
);
401 (void)Fclose(readstat
);
402 if (p
== get_msgCount() && !modify
&& !anystat
) {
403 (void)printf("Held %d message%s in %s\n",
404 p
, p
== 1 ? "" : "s", mailname
);
406 dot_unlock(mailname
);
411 (void)writeback(rbuf
);
413 dot_unlock(mailname
);
420 * Create another temporary file and copy user's mbox file
421 * darin. If there is no mbox, copy nothing.
422 * If he has specified "append" don't copy his mailbox,
423 * just copy saveable entries at the end.
428 append
= value(ENAME_APPEND
) != NULL
;
430 (void)snprintf(tempname
, sizeof(tempname
),
431 "%s/mail.RmXXXXXXXXXX", tmpdir
);
432 if ((fd
= mkstemp(tempname
)) == -1 ||
433 (obuf
= Fdopen(fd
, "w")) == NULL
) {
434 warn("%s", tempname
);
438 dot_unlock(mailname
);
441 if ((ibuf
= Fopen(tempname
, "r")) == NULL
) {
442 warn("%s", tempname
);
446 dot_unlock(mailname
);
450 if ((abuf
= Fopen(mbox
, "r")) != NULL
) {
451 while ((c
= getc(abuf
)) != EOF
)
456 warn("%s", tempname
);
460 dot_unlock(mailname
);
464 if ((fd
= creat(mbox
, 0600)) != -1)
466 if ((obuf
= Fopen(mbox
, "r+")) == NULL
) {
470 dot_unlock(mailname
);
475 if ((obuf
= Fopen(mbox
, "a")) == NULL
) {
478 dot_unlock(mailname
);
481 (void)fchmod(fileno(obuf
), 0600);
483 for (mp
= get_message(1); mp
; mp
= next_message(mp
))
484 if (mp
->m_flag
& MBOX
)
485 if (sendmessage(mp
, obuf
, saveignore
, NULL
, NULL
) < 0) {
491 dot_unlock(mailname
);
496 * Copy the user's old mbox contents back
497 * to the end of the stuff we just saved.
498 * If we are appending, this is unnecessary.
514 trunc(obuf
); /* XXX or should we truncate? */
519 dot_unlock(mailname
);
524 (void)printf("Saved 1 message in mbox\n");
526 (void)printf("Saved %d messages in mbox\n", mcount
);
529 * Now we are ready to copy back preserved files to
530 * the system mailbox, if any were requested.
534 (void)writeback(rbuf
);
536 dot_unlock(mailname
);
541 * Finally, remove his /var/mail file.
542 * If new mail has arrived, copy it back.
547 abuf
= Fopen(mailname
, "r+");
550 while ((c
= getc(rbuf
)) != EOF
)
554 warn("%s", mailname
);
557 dot_unlock(mailname
);
565 dot_unlock(mailname
);
570 dot_unlock(mailname
);
574 (void)printf("Thou hast new mail.\n");
577 dot_unlock(mailname
);