xref: /illumos-gate/usr/src/cmd/mail/copyback.c (revision f3041bfa)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 /*
28  *  NAME
29  *	copyback - copy temp or whatever back to /var/mail
30  *
31  *  SYNOPSIS
32  *	void copyback()
33  *
34  *  DESCRIPTION
35  *	Copy the reduced contents of lettmp back to
36  *	the mail file. First copy any new mail from
37  *	the mail file to the end of lettmp.
38  */
39 
40 #include "mail.h"
41 void
42 copyback()
43 {
44 	register int	i, n;
45 	int		new = 0;
46 	mode_t		mailmode, omask;
47 	struct stat	stbuf;
48 	void (*hstat)(), (*istat)(), (*qstat)();
49 
50 	istat = signal(SIGINT, SIG_IGN);
51 	qstat = signal(SIGQUIT, SIG_IGN);
52 	hstat = signal(SIGHUP, SIG_IGN);
53 	lock(my_name);
54 	stat(mailfile, &stbuf);
55 	mailmode = stbuf.st_mode;
56 
57 	/*
58 	 *	Has new mail arrived?
59 	 */
60 	if (stbuf.st_size != let[nlet].adr) {
61 		malf = doopen(mailfile, "r", E_FILE);
62 		fseek(malf, let[nlet].adr, 0);
63 		fclose(tmpf);
64 		tmpf = doopen(lettmp, "a", E_TMP);
65 		/*
66 		 *	Append new mail assume only one new letter
67 		 */
68 		if (!copystream(malf, tmpf)) {
69 			fclose(malf);
70 			tmperr();
71 			done(0);
72 		}
73 		fclose(malf);
74 		fclose(tmpf);
75 		tmpf = doopen(lettmp, "r+", E_TMP);
76 		if (nlet == (MAXLET-2)) {
77 			errmsg(E_SPACE, "");
78 			done(0);
79 		}
80 		let[++nlet].adr = stbuf.st_size;
81 		new = 1;
82 	}
83 
84 	/*
85 	 *	Copy mail back to mail file
86 	 */
87 	omask = umask(0117);
88 
89 	/*
90 	 *	The invoker must own the mailfile being copied to
91 	 */
92 	if ((stbuf.st_uid != my_euid) && (stbuf.st_uid != my_uid)) {
93 		errmsg(E_OWNR, "");
94 		done(0);
95 	}
96 
97 	/*
98 	 *	If user specified the '-f' option we dont do
99 	 *	the routines to handle :saved files.
100 	 *	As we would(incorrectly) restore to the user's
101 	 *	mailfile upon next execution!
102 	 */
103 	if (flgf) {
104 		(void) strlcpy(savefile, mailfile, sizeof (savefile));
105 	} else {
106 		cat(savefile, mailsave, my_name);
107 	}
108 
109 	if ((malf = fopen(savefile, "w")) == NULL) {
110 		if (!flgf) {
111 			errmsg(E_FILE, "Cannot open savefile");
112 		} else {
113 			errmsg(E_FILE, "Cannot re-write the alternate file");
114 		}
115 		done(0);
116 	}
117 
118 	if (chown(savefile, mf_uid, mf_gid) == -1) {
119 		errmsg(E_FILE, "Cannot chown savefile");
120 		done(0);
121 	}
122 	umask(omask);
123 	n = 0;
124 
125 	for (i = 0; i < nlet; i++) {
126 		/*
127 		 *	Note: any action other than an undelete, or a
128 		 *	plain read causes the letter acted upon to be
129 		 *	deleted
130 		 */
131 		if (let[i].change == ' ') {
132 			if (copylet(i, malf, ORDINARY) == FALSE) {
133 				errmsg(E_FILE, "Cannot copy mail to savefile");
134 				(void) fprintf(stderr, "%s: A copy of your "
135 				    "mailfile is in '%s'\n", program, lettmp);
136 				done(1);	/* keep temp file */
137 			}
138 			n++;
139 		}
140 	}
141 	fclose(malf);
142 
143 	if (!flgf) {
144 		if (unlink(mailfile) != 0) {
145 			errmsg(E_FILE, "Cannot unlink mailfile");
146 			done(0);
147 		}
148 		chmod(savefile, mailmode);
149 #ifdef SVR4
150 		if (rename(savefile, mailfile) != 0) {
151 			errmsg(E_FILE, "Cannot rename savefile to mailfile");
152 			done(0);
153 		}
154 #else
155 		if (link(savefile, mailfile) != 0) {
156 			errmsg(E_FILE, "Cannot link savefile to mailfile");
157 			done(0);
158 		}
159 		if (unlink(savefile) != 0) {
160 			errmsg(E_FILE, "Cannot unlink save file");
161 			done(0);
162 		}
163 #endif
164 	}
165 
166 	/*
167 	 *	Empty mailbox?
168 	 */
169 	if (n == 0) {
170 		delempty(stbuf.st_mode, mailfile);
171 	}
172 
173 	if (new && !flgf) {
174 		printf("New mail arrived\n");
175 	}
176 
177 	unlock();
178 	(void) signal(SIGINT, istat);
179 	(void) signal(SIGQUIT, qstat);
180 	(void) signal(SIGHUP, hstat);
181 }
182