1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 /*	from OpenSolaris "copyback.c	1.10	05/06/11 SMI"	*/
26 
27 /*
28  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
29  *
30  * Sccsid @(#)copyback.c	1.8 (gritter) 6/22/05
31  */
32 
33 /*
34  *  NAME
35  *	copyback - copy temp or whatever back to /var/mail
36  *
37  *  SYNOPSIS
38  *	void copyback()
39  *
40  *  DESCRIPTION
41  *	Copy the reduced contents of lettmp back to
42  *	the mail file. First copy any new mail from
43  *	the mail file to the end of lettmp.
44  */
45 
46 #include "mail.h"
47 void
copyback(void)48 copyback(void)
49 {
50 	register int	i, n;
51 	int		new = 0;
52 	mode_t		mailmode, omask;
53 	struct stat	stbuf;
54 	void		(*istat)(int), (*qstat)(int), (*hstat)(int);
55 
56 	istat = sigset(SIGINT, SIG_IGN);
57 	qstat = sigset(SIGQUIT, SIG_IGN);
58 	hstat = sigset(SIGHUP, SIG_IGN);
59 	lock(my_name);
60 	stat(mailfile, &stbuf);
61 	mailmode = stbuf.st_mode;
62 
63 	/*
64 	 *	Has new mail arrived?
65 	 */
66 	if (stbuf.st_size != let[nlet].adr) {
67 		malf = doopen(mailfile, "r", E_FILE);
68 		fseek(malf, let[nlet].adr, 0);
69 		fclose(tmpf);
70 		tmpf = doopen(lettmp, "a", E_TMP);
71 		/*
72 		 *	Append new mail assume only one new letter
73 		 */
74 		if (!copystream(malf, tmpf)) {
75 			fclose(malf);
76 			tmperr();
77 			done(0);
78 		}
79 		fclose(malf);
80 		fclose(tmpf);
81 		tmpf = doopen(lettmp, "r+", E_TMP);
82 		if (nlet == (MAXLET-2)) {
83 			errmsg(E_SPACE, "");
84 			done(0);
85 		}
86 		let[++nlet].adr = stbuf.st_size;
87 		new = 1;
88 	}
89 
90 	/*
91 	 *	Copy mail back to mail file
92 	 */
93 	omask = umask(0117);
94 
95 	/*
96 	 *	The invoker must own the mailfile being copied to
97 	 */
98 	if ((stbuf.st_uid != my_euid) && (stbuf.st_uid != my_uid)) {
99 		errmsg(E_OWNR, "");
100 		done(0);
101 	}
102 
103 	/*
104 	 *	If user specified the '-f' option we dont do
105 	 *	the routines to handle :saved files.
106 	 *	As we would(incorrectly) restore to the user's
107 	 *	mailfile upon next execution!
108 	 */
109 	if (flgf) {
110 		cpy(&savefile, &savefilesize, mailfile);
111 	} else {
112 		cat(&savefile, &savefilesize, mailsave, my_name);
113 	}
114 
115 	if ((malf = fopen(savefile, "w")) == NULL) {
116 		if (!flgf) {
117 			cat(&savefile, &savefilesize, mailfile, "XXXXXX");
118 			close(mkstemp(savefile));
119 			if ((malf = fopen(savefile, "w")) != NULL)
120 				goto success;
121 			errmsg(E_FILE, "Cannot open savefile");
122 		} else {
123 			errmsg(E_FILE, "Cannot re-write the alternate file");
124 		}
125 		done(0);
126 	}
127 success:
128 	if (chown(savefile, mf_uid, mf_gid) == -1) {
129 		/*EMPTY*/;
130 		/*
131 		errmsg(E_FILE, "Cannot chown savefile");
132 		done(0);
133 		*/
134 	}
135 	umask(omask);
136 	n = 0;
137 
138 	for (i = 0; i < nlet; i++) {
139 		/*
140 		 *	Note: any action other than an undelete, or a
141 		 *	plain read causes the letter acted upon to be
142 		 *	deleted
143 		 */
144 		if (let[i].change == ' ') {
145 			if (copylet(i, malf, ORDINARY) == FALSE) {
146 				errmsg(E_FILE, "Cannot copy mail to savefile");
147 				fprintf(stderr, "%s: A copy of your "
148 				    "mailfile is in '%s'\n", program, lettmp);
149 				done(1);	/* keep temp file */
150 			}
151 			n++;
152 		}
153 	}
154 	fclose(malf);
155 
156 	if (!flgf) {
157 		if (unlink(mailfile) != 0) {
158 			errmsg(E_FILE, "Cannot unlink mailfile");
159 			done(0);
160 		}
161 		chmod(savefile, mailmode);
162 		if (rename(savefile, mailfile) != 0) {
163 			errmsg(E_FILE, "Cannot rename savefile to mailfile");
164 			done(0);
165 		}
166 	}
167 
168 	/*
169 	 *	Empty mailbox?
170 	 */
171 	if (n == 0) {
172 		delempty(stbuf.st_mode, mailfile);
173 	}
174 
175 	if (new && !flgf) {
176 		printf("New mail arrived\n");
177 	}
178 
179 	unlock();
180 	sigset(SIGINT, istat);
181 	sigset(SIGQUIT, qstat);
182 	sigset(SIGHUP, hstat);
183 }
184