Blame quit.c

Packit 272fb1
/*
Packit 272fb1
 * Heirloom mailx - a mail user agent derived from Berkeley Mail.
Packit 272fb1
 *
Packit 272fb1
 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
Packit 272fb1
 */
Packit 272fb1
/*
Packit 272fb1
 * Copyright (c) 1980, 1993
Packit 272fb1
 *	The Regents of the University of California.  All rights reserved.
Packit 272fb1
 *
Packit 272fb1
 * Redistribution and use in source and binary forms, with or without
Packit 272fb1
 * modification, are permitted provided that the following conditions
Packit 272fb1
 * are met:
Packit 272fb1
 * 1. Redistributions of source code must retain the above copyright
Packit 272fb1
 *    notice, this list of conditions and the following disclaimer.
Packit 272fb1
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 272fb1
 *    notice, this list of conditions and the following disclaimer in the
Packit 272fb1
 *    documentation and/or other materials provided with the distribution.
Packit 272fb1
 * 3. All advertising materials mentioning features or use of this software
Packit 272fb1
 *    must display the following acknowledgement:
Packit 272fb1
 *	This product includes software developed by the University of
Packit 272fb1
 *	California, Berkeley and its contributors.
Packit 272fb1
 * 4. Neither the name of the University nor the names of its contributors
Packit 272fb1
 *    may be used to endorse or promote products derived from this software
Packit 272fb1
 *    without specific prior written permission.
Packit 272fb1
 *
Packit 272fb1
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
Packit 272fb1
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 272fb1
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 272fb1
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit 272fb1
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 272fb1
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit 272fb1
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit 272fb1
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit 272fb1
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit 272fb1
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit 272fb1
 * SUCH DAMAGE.
Packit 272fb1
 */
Packit 272fb1
Packit 272fb1
#ifndef lint
Packit 272fb1
#ifdef	DOSCCS
Packit 272fb1
static char sccsid[] = "@(#)quit.c	2.30 (gritter) 11/11/08";
Packit 272fb1
#endif
Packit 272fb1
#endif /* not lint */
Packit 272fb1
Packit 272fb1
#include "rcv.h"
Packit 272fb1
#include "extern.h"
Packit 272fb1
#include <stdio.h>
Packit 272fb1
#include <errno.h>
Packit 272fb1
#include <sys/file.h>
Packit 272fb1
#include <sys/stat.h>
Packit 272fb1
#include <unistd.h>
Packit 272fb1
#include <fcntl.h>
Packit 272fb1
Packit 272fb1
/*
Packit 272fb1
 * Rcv -- receive mail rationally.
Packit 272fb1
 *
Packit 272fb1
 * Termination processing.
Packit 272fb1
 */
Packit 272fb1
Packit 272fb1
static int writeback(FILE *res, FILE *obuf);
Packit 272fb1
static void edstop(void);
Packit 272fb1
Packit 272fb1
/*
Packit 272fb1
 * The "quit" command.
Packit 272fb1
 */
Packit 272fb1
/*ARGSUSED*/
Packit 272fb1
int 
Packit 272fb1
quitcmd(void *v)
Packit 272fb1
{
Packit 272fb1
	/*
Packit 272fb1
	 * If we are sourcing, then return 1 so execute() can handle it.
Packit 272fb1
	 * Otherwise, return -1 to abort command loop.
Packit 272fb1
	 */
Packit 272fb1
	if (sourcing)
Packit 272fb1
		return 1;
Packit 272fb1
	return -1;
Packit 272fb1
}
Packit 272fb1
Packit 272fb1
/*
Packit 272fb1
 * Preserve all the appropriate messages back in the system
Packit 272fb1
 * mailbox, and print a nice message indicated how many were
Packit 272fb1
 * saved.  On any error, just return -1.  Else return 0.
Packit 272fb1
 * Incorporate the any new mail that we found.
Packit 272fb1
 */
Packit 272fb1
static int
Packit 272fb1
writeback(FILE *res, FILE *obuf)
Packit 272fb1
{
Packit 272fb1
	struct message *mp;
Packit 272fb1
	int p, c;
Packit 272fb1
Packit 272fb1
	p = 0;
Packit 272fb1
	fseek(obuf, 0L, SEEK_SET);
Packit 272fb1
#ifndef APPEND
Packit 272fb1
	if (res != NULL)
Packit 272fb1
		while ((c = getc(res)) != EOF)
Packit 272fb1
			putc(c, obuf);
Packit 272fb1
#endif
Packit 272fb1
	for (mp = &message[0]; mp < &message[msgCount]; mp++)
Packit 272fb1
		if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
Packit 272fb1
			p++;
Packit 272fb1
			if (send(mp, obuf, NULL, NULL, SEND_MBOX, NULL) < 0) {
Packit 272fb1
				perror(mailname);
Packit 272fb1
				fseek(obuf, 0L, SEEK_SET);
Packit 272fb1
				return(-1);
Packit 272fb1
			}
Packit 272fb1
		}
Packit 272fb1
#ifdef APPEND
Packit 272fb1
	if (res != NULL)
Packit 272fb1
		while ((c = getc(res)) != EOF)
Packit 272fb1
			putc(c, obuf);
Packit 272fb1
#endif
Packit 272fb1
	fflush(obuf);
Packit 272fb1
	trunc(obuf);
Packit 272fb1
	if (ferror(obuf)) {
Packit 272fb1
		perror(mailname);
Packit 272fb1
		fseek(obuf, 0L, SEEK_SET);
Packit 272fb1
		return(-1);
Packit 272fb1
	}
Packit 272fb1
	if (res != NULL)
Packit 272fb1
		Fclose(res);
Packit 272fb1
	fseek(obuf, 0L, SEEK_SET);
Packit 272fb1
	alter(mailname);
Packit 272fb1
	if (p == 1)
Packit 272fb1
		printf(catgets(catd, CATSET, 155,
Packit 272fb1
				"Held 1 message in %s\n"), mailname);
Packit 272fb1
	else
Packit 272fb1
		printf(catgets(catd, CATSET, 156,
Packit 272fb1
				"Held %d messages in %s\n"), p, mailname);
Packit 272fb1
	return(0);
Packit 272fb1
}
Packit 272fb1
Packit 272fb1
/*
Packit 272fb1
 * Save all of the undetermined messages at the top of "mbox"
Packit 272fb1
 * Save all untouched messages back in the system mailbox.
Packit 272fb1
 * Remove the system mailbox, if none saved there.
Packit 272fb1
 */
Packit 272fb1
void 
Packit 272fb1
quit(void)
Packit 272fb1
{
Packit 272fb1
	int p, modify, anystat;
Packit 272fb1
	FILE *fbuf, *rbuf, *readstat = NULL, *abuf;
Packit 272fb1
	struct message *mp;
Packit 272fb1
	int c;
Packit Service b65dad
	char *tempResid;
Packit 272fb1
	struct stat minfo;
Packit 272fb1
Packit 272fb1
	/*
Packit 272fb1
	 * If we are read only, we can't do anything,
Packit 272fb1
	 * so just return quickly. IMAP can set some
Packit 272fb1
	 * flags (e.g. "\\Seen") so imap_quit must be
Packit 272fb1
	 * called even then.
Packit 272fb1
	 */
Packit 272fb1
	if (mb.mb_perm == 0 && mb.mb_type != MB_IMAP)
Packit 272fb1
		return;
Packit 272fb1
	switch (mb.mb_type) {
Packit 272fb1
	case MB_FILE:
Packit 272fb1
		break;
Packit 272fb1
	case MB_MAILDIR:
Packit 272fb1
		maildir_quit();
Packit 272fb1
		return;
Packit 272fb1
	case MB_POP3:
Packit 272fb1
		pop3_quit();
Packit 272fb1
		return;
Packit 272fb1
	case MB_IMAP:
Packit 272fb1
	case MB_CACHE:
Packit 272fb1
		imap_quit();
Packit 272fb1
		return;
Packit 272fb1
	case MB_VOID:
Packit 272fb1
		return;
Packit 272fb1
	}
Packit 272fb1
	/*
Packit 272fb1
	 * If editing (not reading system mail box), then do the work
Packit 272fb1
	 * in edstop()
Packit 272fb1
	 */
Packit 272fb1
	if (edit) {
Packit 272fb1
		edstop();
Packit 272fb1
		return;
Packit 272fb1
	}
Packit 272fb1
Packit 272fb1
	/*
Packit 272fb1
	 * See if there any messages to save in mbox.  If no, we
Packit 272fb1
	 * can save copying mbox to /tmp and back.
Packit 272fb1
	 *
Packit 272fb1
	 * Check also to see if any files need to be preserved.
Packit 272fb1
	 * Delete all untouched messages to keep them out of mbox.
Packit 272fb1
	 * If all the messages are to be preserved, just exit with
Packit 272fb1
	 * a message.
Packit 272fb1
	 */
Packit 272fb1
Packit 272fb1
	fbuf = Zopen(mailname, "r+", &mb.mb_compressed);
Packit 272fb1
	if (fbuf == NULL) {
Packit 272fb1
		if (errno == ENOENT)
Packit 272fb1
			return;
Packit 272fb1
		goto newmail;
Packit 272fb1
	}
Packit 272fb1
	if (fcntl_lock(fileno(fbuf), F_WRLCK) == -1) {
Packit 272fb1
nolock:
Packit 272fb1
		perror(catgets(catd, CATSET, 157, "Unable to lock mailbox"));
Packit 272fb1
		Fclose(fbuf);
Packit 272fb1
		return;
Packit 272fb1
	}
Packit 272fb1
	if (dot_lock(mailname, fileno(fbuf), 1, stdout, ".") == -1)
Packit 272fb1
		goto nolock;
Packit 272fb1
	rbuf = NULL;
Packit 272fb1
	if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
Packit 272fb1
		printf(catgets(catd, CATSET, 158, "New mail has arrived.\n"));
Packit 272fb1
		rbuf = Ftemp(&tempResid, "Rq", "w", 0600, 1);
Packit 272fb1
		if (rbuf == NULL || fbuf == NULL)
Packit 272fb1
			goto newmail;
Packit 272fb1
#ifdef APPEND
Packit 272fb1
		fseek(fbuf, (long)mailsize, SEEK_SET);
Packit 272fb1
		while ((c = getc(fbuf)) != EOF)
Packit 272fb1
			putc(c, rbuf);
Packit 272fb1
#else
Packit 272fb1
		p = minfo.st_size - mailsize;
Packit 272fb1
		while (p-- > 0) {
Packit 272fb1
			c = getc(fbuf);
Packit 272fb1
			if (c == EOF)
Packit 272fb1
				goto newmail;
Packit 272fb1
			putc(c, rbuf);
Packit 272fb1
		}
Packit 272fb1
#endif
Packit 272fb1
		Fclose(rbuf);
Packit 272fb1
		if ((rbuf = Fopen(tempResid, "r")) == NULL)
Packit 272fb1
			goto newmail;
Packit 272fb1
		rm(tempResid);
Packit 272fb1
		Ftfree(&tempResid);
Packit 272fb1
	}
Packit 272fb1
Packit 272fb1
	anystat = holdbits();
Packit 272fb1
	modify = 0;
Packit 272fb1
	if (Tflag != NULL) {
Packit 272fb1
		if ((readstat = Zopen(Tflag, "w", NULL)) == NULL)
Packit 272fb1
			Tflag = NULL;
Packit 272fb1
	}
Packit 272fb1
	for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
Packit 272fb1
		if (mp->m_flag & MBOX)
Packit 272fb1
			c++;
Packit 272fb1
		if (mp->m_flag & MPRESERVE)
Packit 272fb1
			p++;
Packit 272fb1
		if (mp->m_flag & MODIFY)
Packit 272fb1
			modify++;
Packit 272fb1
		if (readstat != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
Packit 272fb1
			char *id;
Packit 272fb1
Packit 272fb1
			if ((id = hfield("message-id", mp)) != NULL ||
Packit 272fb1
					(id = hfield("article-id", mp)) != NULL)
Packit 272fb1
				fprintf(readstat, "%s\n", id);
Packit 272fb1
		}
Packit 272fb1
	}
Packit 272fb1
	if (readstat != NULL)
Packit 272fb1
		Fclose(readstat);
Packit 272fb1
	if (p == msgCount && !modify && !anystat) {
Packit 272fb1
		if (p == 1)
Packit 272fb1
			printf(catgets(catd, CATSET, 155,
Packit 272fb1
				"Held 1 message in %s\n"), mailname);
Packit 272fb1
		else if (p > 1)
Packit 272fb1
			printf(catgets(catd, CATSET, 156,
Packit 272fb1
				"Held %d messages in %s\n"), p, mailname);
Packit 272fb1
		Fclose(fbuf);
Packit 272fb1
		dot_unlock(mailname);
Packit 272fb1
		return;
Packit 272fb1
	}
Packit 272fb1
	if (c == 0) {
Packit 272fb1
		if (p != 0) {
Packit 272fb1
			writeback(rbuf, fbuf);
Packit 272fb1
			Fclose(fbuf);
Packit 272fb1
			dot_unlock(mailname);
Packit 272fb1
			return;
Packit 272fb1
		}
Packit 272fb1
		goto cream;
Packit 272fb1
	}
Packit 272fb1
Packit 272fb1
	if (makembox() == STOP) {
Packit 272fb1
		Fclose(fbuf);
Packit 272fb1
		dot_unlock(mailname);
Packit 272fb1
		return;
Packit 272fb1
	}
Packit 272fb1
	/*
Packit 272fb1
	 * Now we are ready to copy back preserved files to
Packit 272fb1
	 * the system mailbox, if any were requested.
Packit 272fb1
	 */
Packit 272fb1
Packit 272fb1
	if (p != 0) {
Packit 272fb1
		writeback(rbuf, fbuf);
Packit 272fb1
		Fclose(fbuf);
Packit 272fb1
		dot_unlock(mailname);
Packit 272fb1
		return;
Packit 272fb1
	}
Packit 272fb1
Packit 272fb1
	/*
Packit 272fb1
	 * Finally, remove his /usr/mail file.
Packit 272fb1
	 * If new mail has arrived, copy it back.
Packit 272fb1
	 */
Packit 272fb1
Packit 272fb1
cream:
Packit 272fb1
	if (rbuf != NULL) {
Packit 272fb1
		abuf = fbuf;
Packit 272fb1
		fseek(abuf, 0L, SEEK_SET);
Packit 272fb1
		while ((c = getc(rbuf)) != EOF)
Packit 272fb1
			putc(c, abuf);
Packit 272fb1
		Fclose(rbuf);
Packit 272fb1
		trunc(abuf);
Packit 272fb1
		alter(mailname);
Packit 272fb1
		Fclose(fbuf);
Packit 272fb1
		dot_unlock(mailname);
Packit 272fb1
		return;
Packit 272fb1
	}
Packit 272fb1
	demail();
Packit 272fb1
	Fclose(fbuf);
Packit 272fb1
	dot_unlock(mailname);
Packit 272fb1
	return;
Packit 272fb1
Packit 272fb1
newmail:
Packit 272fb1
	printf(catgets(catd, CATSET, 166, "Thou hast new mail.\n"));
Packit 272fb1
	if (fbuf != NULL) {
Packit 272fb1
		Fclose(fbuf);
Packit 272fb1
		dot_unlock(mailname);
Packit 272fb1
	}
Packit 272fb1
}
Packit 272fb1
Packit 272fb1
/*
Packit 272fb1
 * Adjust the message flags in each message.
Packit 272fb1
 */
Packit 272fb1
int 
Packit 272fb1
holdbits(void)
Packit 272fb1
{
Packit 272fb1
	struct message *mp;
Packit 272fb1
	int anystat, autohold, holdbit, nohold;
Packit 272fb1
Packit 272fb1
	anystat = 0;
Packit 272fb1
	autohold = value("hold") != NULL;
Packit 272fb1
	holdbit = autohold ? MPRESERVE : MBOX;
Packit 272fb1
	nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
Packit 272fb1
	if (value("keepsave") != NULL)
Packit 272fb1
		nohold &= ~MSAVED;
Packit 272fb1
	for (mp = &message[0]; mp < &message[msgCount]; mp++) {
Packit 272fb1
		if (mp->m_flag & MNEW) {
Packit 272fb1
			mp->m_flag &= ~MNEW;
Packit 272fb1
			mp->m_flag |= MSTATUS;
Packit 272fb1
		}
Packit 272fb1
		if (mp->m_flag & (MSTATUS|MFLAG|MUNFLAG|MANSWER|MUNANSWER|
Packit 272fb1
					MDRAFT|MUNDRAFT))
Packit 272fb1
			anystat++;
Packit 272fb1
		if ((mp->m_flag & MTOUCH) == 0)
Packit 272fb1
			mp->m_flag |= MPRESERVE;
Packit 272fb1
		if ((mp->m_flag & nohold) == 0)
Packit 272fb1
			mp->m_flag |= holdbit;
Packit 272fb1
	}
Packit 272fb1
	return anystat;
Packit 272fb1
}
Packit 272fb1
Packit 272fb1
/*
Packit 272fb1
 * Create another temporary file and copy user's mbox file
Packit 272fb1
 * darin.  If there is no mbox, copy nothing.
Packit 272fb1
 * If he has specified "append" don't copy his mailbox,
Packit 272fb1
 * just copy saveable entries at the end.
Packit 272fb1
 */
Packit 272fb1
Packit 272fb1
enum okay 
Packit 272fb1
makembox(void)
Packit 272fb1
{
Packit 272fb1
	struct message *mp;
Packit 272fb1
	char *mbox, *tempQuit;
Packit 272fb1
	int mcount, c;
Packit 272fb1
	FILE *ibuf = NULL, *obuf, *abuf;
Packit 272fb1
	enum protocol	prot;
Packit 272fb1
Packit 272fb1
	mbox = mboxname;
Packit 272fb1
	mcount = 0;
Packit 272fb1
	if (value("append") == NULL) {
Packit 272fb1
		if ((obuf = Ftemp(&tempQuit, "Rm", "w", 0600, 1)) == NULL) {
Packit 272fb1
			perror(catgets(catd, CATSET, 162,
Packit 272fb1
					"temporary mail quit file"));
Packit 272fb1
			return STOP;
Packit 272fb1
		}
Packit 272fb1
		if ((ibuf = Fopen(tempQuit, "r")) == NULL) {
Packit 272fb1
			perror(tempQuit);
Packit 272fb1
			rm(tempQuit);
Packit 272fb1
			Ftfree(&tempQuit);
Packit 272fb1
			Fclose(obuf);
Packit 272fb1
			return STOP;
Packit 272fb1
		}
Packit 272fb1
		rm(tempQuit);
Packit 272fb1
		Ftfree(&tempQuit);
Packit 272fb1
		if ((abuf = Zopen(mbox, "r", NULL)) != NULL) {
Packit 272fb1
			while ((c = getc(abuf)) != EOF)
Packit 272fb1
				putc(c, obuf);
Packit 272fb1
			Fclose(abuf);
Packit 272fb1
		}
Packit 272fb1
		if (ferror(obuf)) {
Packit 272fb1
			perror(catgets(catd, CATSET, 163,
Packit 272fb1
					"temporary mail quit file"));
Packit 272fb1
			Fclose(ibuf);
Packit 272fb1
			Fclose(obuf);
Packit 272fb1
			return STOP;
Packit 272fb1
		}
Packit 272fb1
		Fclose(obuf);
Packit 272fb1
		close(creat(mbox, 0600));
Packit 272fb1
		if ((obuf = Zopen(mbox, "r+", NULL)) == NULL) {
Packit 272fb1
			perror(mbox);
Packit 272fb1
			Fclose(ibuf);
Packit 272fb1
			return STOP;
Packit 272fb1
		}
Packit 272fb1
	}
Packit 272fb1
	else {
Packit 272fb1
		if ((obuf = Zopen(mbox, "a", NULL)) == NULL) {
Packit 272fb1
			perror(mbox);
Packit 272fb1
			return STOP;
Packit 272fb1
		}
Packit 272fb1
		fchmod(fileno(obuf), 0600);
Packit 272fb1
	}
Packit 272fb1
	prot = which_protocol(mbox);
Packit 272fb1
	for (mp = &message[0]; mp < &message[msgCount]; mp++)
Packit 272fb1
		if (mp->m_flag & MBOX) {
Packit 272fb1
			mcount++;
Packit 272fb1
			if (prot == PROTO_IMAP &&
Packit 272fb1
					saveignore[0].i_count == 0 &&
Packit 272fb1
					saveignore[1].i_count == 0 &&
Packit 272fb1
					imap_thisaccount(mbox)) {
Packit 272fb1
				if (imap_copy(mp, mp-message+1, mbox) == STOP)
Packit 272fb1
					goto err;
Packit 272fb1
			} else if (send(mp, obuf, saveignore,
Packit 272fb1
						NULL, SEND_MBOX, NULL) < 0) {
Packit 272fb1
				perror(mbox);
Packit 272fb1
			err:	if (ibuf)
Packit 272fb1
					Fclose(ibuf);
Packit 272fb1
				Fclose(obuf);
Packit 272fb1
				return STOP;
Packit 272fb1
			}
Packit 272fb1
			mp->m_flag |= MBOXED;
Packit 272fb1
		}
Packit 272fb1
Packit 272fb1
	/*
Packit 272fb1
	 * Copy the user's old mbox contents back
Packit 272fb1
	 * to the end of the stuff we just saved.
Packit 272fb1
	 * If we are appending, this is unnecessary.
Packit 272fb1
	 */
Packit 272fb1
Packit 272fb1
	if (value("append") == NULL) {
Packit 272fb1
		rewind(ibuf);
Packit 272fb1
		c = getc(ibuf);
Packit 272fb1
		while (c != EOF) {
Packit 272fb1
			putc(c, obuf);
Packit 272fb1
			if (ferror(obuf))
Packit 272fb1
				break;
Packit 272fb1
			c = getc(ibuf);
Packit 272fb1
		}
Packit 272fb1
		Fclose(ibuf);
Packit 272fb1
		fflush(obuf);
Packit 272fb1
	}
Packit 272fb1
	trunc(obuf);
Packit 272fb1
	if (ferror(obuf)) {
Packit 272fb1
		perror(mbox);
Packit 272fb1
		Fclose(obuf);
Packit 272fb1
		return STOP;
Packit 272fb1
	}
Packit 272fb1
	if (Fclose(obuf) != 0) {
Packit 272fb1
		if (prot != PROTO_IMAP)
Packit 272fb1
			perror(mbox);
Packit 272fb1
		return STOP;
Packit 272fb1
	}
Packit 272fb1
	if (mcount == 1)
Packit 272fb1
		printf(catgets(catd, CATSET, 164, "Saved 1 message in mbox\n"));
Packit 272fb1
	else
Packit 272fb1
		printf(catgets(catd, CATSET, 165,
Packit 272fb1
				"Saved %d messages in mbox\n"), mcount);
Packit 272fb1
	return OKAY;
Packit 272fb1
}
Packit 272fb1
Packit 272fb1
/*
Packit 272fb1
 * Terminate an editing session by attempting to write out the user's
Packit 272fb1
 * file from the temporary.  Save any new stuff appended to the file.
Packit 272fb1
 */
Packit 272fb1
static void 
Packit 272fb1
edstop(void)
Packit 272fb1
{
Packit 272fb1
	int gotcha, c;
Packit 272fb1
	struct message *mp;
Packit 272fb1
	FILE *obuf, *ibuf = NULL, *readstat = NULL;
Packit 272fb1
	struct stat statb;
Packit 272fb1
Packit 272fb1
	if (mb.mb_perm == 0)
Packit 272fb1
		return;
Packit 272fb1
	holdsigs();
Packit 272fb1
	if (Tflag != NULL) {
Packit 272fb1
		if ((readstat = Zopen(Tflag, "w", NULL)) == NULL)
Packit 272fb1
			Tflag = NULL;
Packit 272fb1
	}
Packit 272fb1
	for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
Packit 272fb1
		if (mp->m_flag & MNEW) {
Packit 272fb1
			mp->m_flag &= ~MNEW;
Packit 272fb1
			mp->m_flag |= MSTATUS;
Packit 272fb1
		}
Packit 272fb1
		if (mp->m_flag & (MODIFY|MDELETED|MSTATUS|MFLAG|MUNFLAG|
Packit 272fb1
					MANSWER|MUNANSWER|MDRAFT|MUNDRAFT))
Packit 272fb1
			gotcha++;
Packit 272fb1
		if (readstat != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
Packit 272fb1
			char *id;
Packit 272fb1
Packit 272fb1
			if ((id = hfield("message-id", mp)) != NULL ||
Packit 272fb1
					(id = hfield("article-id", mp)) != NULL)
Packit 272fb1
				fprintf(readstat, "%s\n", id);
Packit 272fb1
		}
Packit 272fb1
	}
Packit 272fb1
	if (readstat != NULL)
Packit 272fb1
		Fclose(readstat);
Packit 272fb1
	if (!gotcha || Tflag != NULL)
Packit 272fb1
		goto done;
Packit 272fb1
	ibuf = NULL;
Packit 272fb1
	if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
Packit 272fb1
		char *tempname;
Packit 272fb1
Packit 272fb1
		if ((obuf = Ftemp(&tempname, "mbox.", "w", 0600, 1)) == NULL) {
Packit 272fb1
			perror(catgets(catd, CATSET, 167, "tmpfile"));
Packit 272fb1
			relsesigs();
Packit 272fb1
			reset(0);
Packit 272fb1
		}
Packit 272fb1
		if ((ibuf = Zopen(mailname, "r", &mb.mb_compressed)) == NULL) {
Packit 272fb1
			perror(mailname);
Packit 272fb1
			Fclose(obuf);
Packit 272fb1
			rm(tempname);
Packit 272fb1
			Ftfree(&tempname);
Packit 272fb1
			relsesigs();
Packit 272fb1
			reset(0);
Packit 272fb1
		}
Packit 272fb1
		fseek(ibuf, (long)mailsize, SEEK_SET);
Packit 272fb1
		while ((c = getc(ibuf)) != EOF)
Packit 272fb1
			putc(c, obuf);
Packit 272fb1
		Fclose(ibuf);
Packit 272fb1
		Fclose(obuf);
Packit 272fb1
		if ((ibuf = Fopen(tempname, "r")) == NULL) {
Packit 272fb1
			perror(tempname);
Packit 272fb1
			rm(tempname);
Packit 272fb1
			Ftfree(&tempname);
Packit 272fb1
			relsesigs();
Packit 272fb1
			reset(0);
Packit 272fb1
		}
Packit 272fb1
		rm(tempname);
Packit 272fb1
		Ftfree(&tempname);
Packit 272fb1
	}
Packit 272fb1
	printf(catgets(catd, CATSET, 168, "\"%s\" "), mailname);
Packit 272fb1
	fflush(stdout);
Packit 272fb1
	if ((obuf = Zopen(mailname, "r+", &mb.mb_compressed)) == NULL) {
Packit 272fb1
		perror(mailname);
Packit 272fb1
		relsesigs();
Packit 272fb1
		reset(0);
Packit 272fb1
	}
Packit 272fb1
	trunc(obuf);
Packit 272fb1
	c = 0;
Packit 272fb1
	for (mp = &message[0]; mp < &message[msgCount]; mp++) {
Packit 272fb1
		if ((mp->m_flag & MDELETED) != 0)
Packit 272fb1
			continue;
Packit 272fb1
		c++;
Packit 272fb1
		if (send(mp, obuf, NULL, NULL, SEND_MBOX, NULL) < 0) {
Packit 272fb1
			perror(mailname);
Packit 272fb1
			relsesigs();
Packit 272fb1
			reset(0);
Packit 272fb1
		}
Packit 272fb1
	}
Packit 272fb1
	gotcha = (c == 0 && ibuf == NULL);
Packit 272fb1
	if (ibuf != NULL) {
Packit 272fb1
		while ((c = getc(ibuf)) != EOF)
Packit 272fb1
			putc(c, obuf);
Packit 272fb1
		Fclose(ibuf);
Packit 272fb1
	}
Packit 272fb1
	fflush(obuf);
Packit 272fb1
	if (ferror(obuf)) {
Packit 272fb1
		perror(mailname);
Packit 272fb1
		relsesigs();
Packit 272fb1
		reset(0);
Packit 272fb1
	}
Packit 272fb1
	Fclose(obuf);
Packit 272fb1
	if (gotcha && value("emptybox") == NULL) {
Packit 272fb1
		rm(mailname);
Packit 272fb1
		printf(value("bsdcompat") || value("bsdmsgs") ?
Packit 272fb1
				catgets(catd, CATSET, 169, "removed\n") :
Packit 272fb1
				catgets(catd, CATSET, 211, "removed.\n"));
Packit 272fb1
	} else
Packit 272fb1
		printf(value("bsdcompat") || value("bsdmsgs") ?
Packit 272fb1
				catgets(catd, CATSET, 170, "complete\n") :
Packit 272fb1
				catgets(catd, CATSET, 212, "updated.\n"));
Packit 272fb1
	fflush(stdout);
Packit 272fb1
Packit 272fb1
done:
Packit 272fb1
	relsesigs();
Packit 272fb1
}
Packit 272fb1
Packit 272fb1
enum quitflags {
Packit 272fb1
	QUITFLAG_HOLD      = 001,
Packit 272fb1
	QUITFLAG_KEEPSAVE  = 002,
Packit 272fb1
	QUITFLAG_APPEND    = 004,
Packit 272fb1
	QUITFLAG_EMPTYBOX  = 010
Packit 272fb1
};
Packit 272fb1
Packit 272fb1
static const struct quitnames {
Packit 272fb1
	enum quitflags	flag;
Packit 272fb1
	const char	*name;
Packit 272fb1
} quitnames[] = {
Packit 272fb1
	{ QUITFLAG_HOLD,	"hold" },
Packit 272fb1
	{ QUITFLAG_KEEPSAVE,	"keepsave" },
Packit 272fb1
	{ QUITFLAG_APPEND,	"append" },
Packit 272fb1
	{ QUITFLAG_EMPTYBOX,	"emptybox" },
Packit 272fb1
	{ 0,			NULL }
Packit 272fb1
};
Packit 272fb1
Packit 272fb1
int
Packit 272fb1
savequitflags(void)
Packit 272fb1
{
Packit 272fb1
	enum quitflags	qf = 0;
Packit 272fb1
	int	i;
Packit 272fb1
Packit 272fb1
	for (i = 0; quitnames[i].name; i++)
Packit 272fb1
		if (value(quitnames[i].name))
Packit 272fb1
			qf |= quitnames[i].flag;
Packit 272fb1
	return qf;
Packit 272fb1
}
Packit 272fb1
Packit 272fb1
void
Packit 272fb1
restorequitflags(int qf)
Packit 272fb1
{
Packit 272fb1
	int	i;
Packit 272fb1
Packit 272fb1
	for (i = 0; quitnames[i].name; i++)
Packit 272fb1
		if (qf & quitnames[i].flag) {
Packit 272fb1
			if (value(quitnames[i].name) == NULL)
Packit 272fb1
				assign(quitnames[i].name, "");
Packit 272fb1
		} else if (value(quitnames[i].name))
Packit 272fb1
			unset_internal(quitnames[i].name);
Packit 272fb1
}