Mercurial > illumos > onarm
diff usr/src/cmd/mailx/quit.c @ 0:c9caec207d52 b86
Initial porting based on b86
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Tue, 02 Jun 2009 18:56:50 +0900 |
parents | |
children | 1a15d5aaf794 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/mailx/quit.c Tue Jun 02 18:56:50 2009 +0900 @@ -0,0 +1,401 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +#pragma ident "@(#)quit.c 1.26 05/06/08 SMI" + +#include "rcv.h" +#include <locale.h> + +/* + * mailx -- a modified version of a University of California at Berkeley + * mail program + * + * Rcv -- receive mail rationally. + * + * Termination processing. + */ + +static void writeback(int noremove); + +#define PRIV(x) setgid(myegid), (x), setgid(myrgid); + +/* + * Save all of the undetermined messages at the top of "mbox" + * Save all untouched messages back in the system mailbox. + * Remove the system mailbox, if none saved there. + */ + +void +quit( + int noremove /* don't remove system mailbox, trunc it instead */ +) +{ + int mcount, p, modify, autohold, anystat, holdbit, nohold, fd; + FILE *ibuf, *obuf, *fbuf, *readstat; + register struct message *mp; + register int c; + char *id; + int appending; + char *mbox = Getf("MBOX"); + + /* + * If we are read only, we can't do anything, + * so just return quickly. + */ + + mcount = 0; + if (readonly) + return; + /* + * See if there any messages to save in mbox. If no, we + * can save copying mbox to /tmp and back. + * + * Check also to see if any files need to be preserved. + * Delete all untouched messages to keep them out of mbox. + * If all the messages are to be preserved, just exit with + * a message. + * + * If the luser has sent mail to himself, refuse to do + * anything with the mailbox, unless mail locking works. + */ + +#ifndef CANLOCK + if (selfsent) { + printf(gettext("You have new mail.\n")); + return; + } +#endif + + /* + * Adjust the message flags in each message. + */ + + anystat = 0; + autohold = value("hold") != NOSTR; + appending = value("append") != NOSTR; + holdbit = autohold ? MPRESERVE : MBOX; + nohold = MBOXED|MBOX|MSAVED|MDELETED|MPRESERVE; + if (value("keepsave") != NOSTR) + nohold &= ~MSAVED; + for (mp = &message[0]; mp < &message[msgCount]; mp++) { + if (mp->m_flag & MNEW) { + receipt(mp); + mp->m_flag &= ~MNEW; + mp->m_flag |= MSTATUS; + } + if (mp->m_flag & MSTATUS) + anystat++; + if ((mp->m_flag & MTOUCH) == 0) + mp->m_flag |= MPRESERVE; + if ((mp->m_flag & nohold) == 0) + mp->m_flag |= holdbit; + } + modify = 0; + if (Tflag != NOSTR) { + if ((readstat = fopen(Tflag, "w")) == NULL) + Tflag = NOSTR; + } + for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) { + if (mp->m_flag & MBOX) + c++; + if (mp->m_flag & MPRESERVE) + p++; + if (mp->m_flag & MODIFY) + modify++; + if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { + id = hfield("message-id", mp, addone); + if (id != NOSTR) + fprintf(readstat, "%s\n", id); + else { + id = hfield("article-id", mp, addone); + if (id != NOSTR) + fprintf(readstat, "%s\n", id); + } + } + } + if (Tflag != NOSTR) + fclose(readstat); + if (p == msgCount && !modify && !anystat) { + if (p == 1) + printf(gettext("Held 1 message in %s\n"), mailname); + else + printf(gettext("Held %d messages in %s\n"), p, + mailname); + return; + } + if (c == 0) { + writeback(noremove); + return; + } + + /* + * Create another temporary file and copy user's mbox file + * therein. If there is no mbox, copy nothing. + * If s/he has specified "append" don't copy the mailbox, + * just copy saveable entries at the end. + */ + + mcount = c; + if (!appending) { + if ((fd = open(tempQuit, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || + (obuf = fdopen(fd, "w")) == NULL) { + perror(tempQuit); + return; + } + if ((ibuf = fopen(tempQuit, "r")) == NULL) { + perror(tempQuit); + removefile(tempQuit); + fclose(obuf); + return; + } + removefile(tempQuit); + if ((fbuf = fopen(mbox, "r")) != NULL) { + while ((c = getc(fbuf)) != EOF) + putc(c, obuf); + fclose(fbuf); + } + fflush(obuf); + if (fferror(obuf)) { + perror(tempQuit); + fclose(ibuf); + fclose(obuf); + return; + } + fclose(obuf); + if ((fd = open(mbox, O_RDWR|O_CREAT|O_TRUNC, MBOXPERM)) < 0 || + (obuf = fdopen(fd, "r+")) == NULL) { + perror(mbox); + fclose(ibuf); + return; + } + if (issysmbox) + touchlock(); + } else { /* we are appending */ + if ((fd = open(mbox, O_RDWR|O_CREAT, MBOXPERM)) < 0 || + (obuf = fdopen(fd, "a")) == NULL) { + perror(mbox); + return; + } + } + for (mp = &message[0]; mp < &message[msgCount]; mp++) + if (mp->m_flag & MBOX) { + if (msend(mp, obuf, (int)value("alwaysignore") ? + M_IGNORE|M_SAVING : M_SAVING, fputs) < 0) { + perror(mbox); + if (!appending) + fclose(ibuf); + fclose(obuf); + return; + } + mp->m_flag &= ~MBOX; + mp->m_flag |= MBOXED; + if (issysmbox) + touchlock(); + } + + /* + * Copy the user's old mbox contents back + * to the end of the stuff we just saved. + * If we are appending, this is unnecessary. + */ + + if (!appending) { + rewind(ibuf); + c = getc(ibuf); + while (c != EOF) { + putc(c, obuf); + if (ferror(obuf)) + break; + c = getc(ibuf); + } + fclose(ibuf); + fflush(obuf); + } + trunc(obuf); + if (fferror(obuf)) { + perror(mbox); + fclose(obuf); + return; + } + fclose(obuf); + if (mcount == 1) + printf(gettext("Saved 1 message in %s\n"), mbox); + else + printf(gettext("Saved %d messages in %s\n"), mcount, mbox); + + /* + * Now we are ready to copy back preserved files to + * the system mailbox, if any were requested. + */ + writeback(noremove); +} + +/* + * Preserve all the appropriate messages back in the system + * mailbox, and print a nice message indicating how many were + * saved. Incorporate any new mail that we found. + */ +static void +writeback(int noremove) +{ + register struct message *mp; + register int p, c; + struct stat st; + FILE *obuf = 0, *fbuf = 0, *rbuf = 0; + void (*fhup)(int), (*fint)(int), (*fquit)(int); + int fd = -1; + + fhup = sigset(SIGHUP, SIG_IGN); + fint = sigset(SIGINT, SIG_IGN); + fquit = sigset(SIGQUIT, SIG_IGN); + + if (issysmbox) + lockmail(); + if ((fbuf = fopen(mailname, "r+")) == NULL) { + perror(mailname); + goto die; + } + if (!issysmbox) + lock(fbuf, "r+", 1); + fstat(fileno(fbuf), &st); + if (st.st_size > mailsize) { + printf(gettext("New mail has arrived.\n")); + snprintf(tempResid, PATHSIZE, "%s/:saved/%s", maildir, myname); + PRIV(rbuf = fopen(tempResid, "w+")); + if (rbuf == NULL) { + snprintf(tempResid, PATHSIZE, "/tmp/Rq%-ld", mypid); + fd = open(tempResid,O_RDWR|O_CREAT|O_EXCL, 0600); + PRIV(rbuf = fdopen(fd, "w+")); + if (rbuf == NULL) { + snprintf(tempResid, PATHSIZE, + "%s/:saved/%s", maildir, + myname); + perror(tempResid); + fclose(fbuf); + goto die; + } + } +#ifdef APPEND + fseek(fbuf, mailsize, 0); + while ((c = getc(fbuf)) != EOF) + putc(c, rbuf); +#else + p = st.st_size - mailsize; + while (p-- > 0) { + c = getc(fbuf); + if (c == EOF) { + perror(mailname); + fclose(fbuf); + goto die; + } + putc(c, rbuf); + } +#endif + fclose(fbuf); + fseek(rbuf, 0L, 0); + if (issysmbox) + touchlock(); + } + + if ((obuf = fopen(mailname, "r+")) == NULL) { + perror(mailname); + goto die; + } +#ifndef APPEND + if (rbuf != NULL) + while ((c = getc(rbuf)) != EOF) + putc(c, obuf); +#endif + p = 0; + for (mp = &message[0]; mp < &message[msgCount]; mp++) + if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) { + p++; + if (msend(mp, obuf, 0, fputs) < 0) { + perror(mailname); + goto die; + } + if (issysmbox) + touchlock(); + } +#ifdef APPEND + if (rbuf != NULL) + while ((c = getc(rbuf)) != EOF) + putc(c, obuf); +#endif + fflush(obuf); + trunc(obuf); + if (fferror(obuf)) { + perror(mailname); + goto die; + } + alter(mailname); + if (p) { + if (p == 1) + printf(gettext("Held 1 message in %s\n"), mailname); + else + printf(gettext("Held %d messages in %s\n"), p, + mailname); + } + + if (!noremove && (fsize(obuf) == 0) && (value("keep") == NOSTR)) { + if (stat(mailname, &st) >= 0) + PRIV(delempty(st.st_mode, mailname)); + } + +die: + if (rbuf) { + fclose(rbuf); + PRIV(removefile(tempResid)); + } + if (obuf) + fclose(obuf); + if (issysmbox) + unlockmail(); + sigset(SIGHUP, fhup); + sigset(SIGINT, fint); + sigset(SIGQUIT, fquit); +} + +void +lockmail(void) +{ + PRIV(maillock(lockname,10)); +} + +void +unlockmail(void) +{ + PRIV(mailunlock()); +}