Merge commit 'b1e7e97d3b60469b243b3b2e22c7d8cbd11c7c90'
[unleashed.git] / usr / src / cmd / mailx / quit.c
blobd418c035d15cbcc8c63c50cd463716dc15a51ede
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
25 * Copyright (c) 2016 by Delphix. All rights reserved.
29 * University Copyright- Copyright (c) 1982, 1986, 1988
30 * The Regents of the University of California
31 * All Rights Reserved
33 * University Acknowledgment- Portions of this document are derived from
34 * software developed by the University of California, Berkeley, and its
35 * contributors.
38 #pragma ident "%Z%%M% %I% %E% SMI"
40 #include "rcv.h"
41 #include <locale.h>
44 * mailx -- a modified version of a University of California at Berkeley
45 * mail program
47 * Rcv -- receive mail rationally.
49 * Termination processing.
52 static void writeback(int noremove);
54 #define PRIV(x) setgid(myegid), (x), setgid(myrgid);
57 * Save all of the undetermined messages at the top of "mbox"
58 * Save all untouched messages back in the system mailbox.
59 * Remove the system mailbox, if none saved there.
62 void
63 quit(
64 int noremove /* don't remove system mailbox, trunc it instead */
67 int mcount, p, modify, autohold, anystat, holdbit, nohold, fd;
68 FILE *ibuf, *obuf, *fbuf, *readstat;
69 register struct message *mp;
70 register int c;
71 char *id;
72 int appending;
73 char *mbox = Getf("MBOX");
76 * If we are read only, we can't do anything,
77 * so just return quickly.
80 mcount = 0;
81 if (readonly)
82 return;
84 * See if there any messages to save in mbox. If no, we
85 * can save copying mbox to /tmp and back.
87 * Check also to see if any files need to be preserved.
88 * Delete all untouched messages to keep them out of mbox.
89 * If all the messages are to be preserved, just exit with
90 * a message.
92 * If the luser has sent mail to himself, refuse to do
93 * anything with the mailbox, unless mail locking works.
96 #ifndef CANLOCK
97 if (selfsent) {
98 printf(gettext("You have new mail.\n"));
99 return;
101 #endif
104 * Adjust the message flags in each message.
107 anystat = 0;
108 autohold = value("hold") != NOSTR;
109 appending = value("append") != NOSTR;
110 holdbit = autohold ? MPRESERVE : MBOX;
111 nohold = MBOXED|MBOX|MSAVED|MDELETED|MPRESERVE;
112 if (value("keepsave") != NOSTR)
113 nohold &= ~MSAVED;
114 for (mp = &message[0]; mp < &message[msgCount]; mp++) {
115 if (mp->m_flag & MNEW) {
116 receipt(mp);
117 mp->m_flag &= ~MNEW;
118 mp->m_flag |= MSTATUS;
120 if (mp->m_flag & MSTATUS)
121 anystat++;
122 if ((mp->m_flag & MTOUCH) == 0)
123 mp->m_flag |= MPRESERVE;
124 if ((mp->m_flag & nohold) == 0)
125 mp->m_flag |= holdbit;
127 modify = 0;
128 if (Tflag != NOSTR) {
129 if ((readstat = fopen(Tflag, "w")) == NULL)
130 Tflag = NOSTR;
132 for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
133 if (mp->m_flag & MBOX)
134 c++;
135 if (mp->m_flag & MPRESERVE)
136 p++;
137 if (mp->m_flag & MODIFY)
138 modify++;
139 if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
140 id = hfield("message-id", mp, addone);
141 if (id != NOSTR)
142 fprintf(readstat, "%s\n", id);
143 else {
144 id = hfield("article-id", mp, addone);
145 if (id != NOSTR)
146 fprintf(readstat, "%s\n", id);
150 if (Tflag != NOSTR)
151 fclose(readstat);
152 if (p == msgCount && !modify && !anystat) {
153 if (p == 1)
154 printf(gettext("Held 1 message in %s\n"), mailname);
155 else
156 printf(gettext("Held %d messages in %s\n"), p,
157 mailname);
158 return;
160 if (c == 0) {
161 writeback(noremove);
162 return;
166 * Create another temporary file and copy user's mbox file
167 * therein. If there is no mbox, copy nothing.
168 * If they have specified "append" don't copy the mailbox,
169 * just copy saveable entries at the end.
172 mcount = c;
173 if (!appending) {
174 if ((fd = open(tempQuit, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 ||
175 (obuf = fdopen(fd, "w")) == NULL) {
176 perror(tempQuit);
177 return;
179 if ((ibuf = fopen(tempQuit, "r")) == NULL) {
180 perror(tempQuit);
181 removefile(tempQuit);
182 fclose(obuf);
183 return;
185 removefile(tempQuit);
186 if ((fbuf = fopen(mbox, "r")) != NULL) {
187 while ((c = getc(fbuf)) != EOF)
188 putc(c, obuf);
189 fclose(fbuf);
191 fflush(obuf);
192 if (fferror(obuf)) {
193 perror(tempQuit);
194 fclose(ibuf);
195 fclose(obuf);
196 return;
198 fclose(obuf);
199 if ((fd = open(mbox, O_RDWR|O_CREAT|O_TRUNC, MBOXPERM)) < 0 ||
200 (obuf = fdopen(fd, "r+")) == NULL) {
201 perror(mbox);
202 fclose(ibuf);
203 return;
205 if (issysmbox)
206 touchlock();
207 } else { /* we are appending */
208 if ((fd = open(mbox, O_RDWR|O_CREAT, MBOXPERM)) < 0 ||
209 (obuf = fdopen(fd, "a")) == NULL) {
210 perror(mbox);
211 return;
214 for (mp = &message[0]; mp < &message[msgCount]; mp++)
215 if (mp->m_flag & MBOX) {
216 if (msend(mp, obuf, (int)value("alwaysignore") ?
217 M_IGNORE|M_SAVING : M_SAVING, fputs) < 0) {
218 perror(mbox);
219 if (!appending)
220 fclose(ibuf);
221 fclose(obuf);
222 return;
224 mp->m_flag &= ~MBOX;
225 mp->m_flag |= MBOXED;
226 if (issysmbox)
227 touchlock();
231 * Copy the user's old mbox contents back
232 * to the end of the stuff we just saved.
233 * If we are appending, this is unnecessary.
236 if (!appending) {
237 rewind(ibuf);
238 c = getc(ibuf);
239 while (c != EOF) {
240 putc(c, obuf);
241 if (ferror(obuf))
242 break;
243 c = getc(ibuf);
245 fclose(ibuf);
246 fflush(obuf);
248 trunc(obuf);
249 if (fferror(obuf)) {
250 perror(mbox);
251 fclose(obuf);
252 return;
254 fclose(obuf);
255 if (mcount == 1)
256 printf(gettext("Saved 1 message in %s\n"), mbox);
257 else
258 printf(gettext("Saved %d messages in %s\n"), mcount, mbox);
261 * Now we are ready to copy back preserved files to
262 * the system mailbox, if any were requested.
264 writeback(noremove);
268 * Preserve all the appropriate messages back in the system
269 * mailbox, and print a nice message indicating how many were
270 * saved. Incorporate any new mail that we found.
272 static void
273 writeback(int noremove)
275 register struct message *mp;
276 register int p, c;
277 struct stat st;
278 FILE *obuf = 0, *fbuf = 0, *rbuf = 0;
279 void (*fhup)(int), (*fint)(int), (*fquit)(int);
280 int fd = -1;
282 fhup = sigset(SIGHUP, SIG_IGN);
283 fint = sigset(SIGINT, SIG_IGN);
284 fquit = sigset(SIGQUIT, SIG_IGN);
286 if (issysmbox)
287 lockmail();
288 if ((fbuf = fopen(mailname, "r+")) == NULL) {
289 perror(mailname);
290 goto die;
292 if (!issysmbox)
293 lock(fbuf, "r+", 1);
294 fstat(fileno(fbuf), &st);
295 if (st.st_size > mailsize) {
296 printf(gettext("New mail has arrived.\n"));
297 snprintf(tempResid, PATHSIZE, "%s/:saved/%s", maildir, myname);
298 PRIV(rbuf = fopen(tempResid, "w+"));
299 if (rbuf == NULL) {
300 snprintf(tempResid, PATHSIZE, "/tmp/Rq%-ld", mypid);
301 fd = open(tempResid,O_RDWR|O_CREAT|O_EXCL, 0600);
302 PRIV(rbuf = fdopen(fd, "w+"));
303 if (rbuf == NULL) {
304 snprintf(tempResid, PATHSIZE,
305 "%s/:saved/%s", maildir,
306 myname);
307 perror(tempResid);
308 fclose(fbuf);
309 goto die;
312 #ifdef APPEND
313 fseek(fbuf, mailsize, 0);
314 while ((c = getc(fbuf)) != EOF)
315 putc(c, rbuf);
316 #else
317 p = st.st_size - mailsize;
318 while (p-- > 0) {
319 c = getc(fbuf);
320 if (c == EOF) {
321 perror(mailname);
322 fclose(fbuf);
323 goto die;
325 putc(c, rbuf);
327 #endif
328 fclose(fbuf);
329 fseek(rbuf, 0L, 0);
330 if (issysmbox)
331 touchlock();
334 if ((obuf = fopen(mailname, "r+")) == NULL) {
335 perror(mailname);
336 goto die;
338 #ifndef APPEND
339 if (rbuf != NULL)
340 while ((c = getc(rbuf)) != EOF)
341 putc(c, obuf);
342 #endif
343 p = 0;
344 for (mp = &message[0]; mp < &message[msgCount]; mp++)
345 if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
346 p++;
347 if (msend(mp, obuf, 0, fputs) < 0) {
348 perror(mailname);
349 goto die;
351 if (issysmbox)
352 touchlock();
354 #ifdef APPEND
355 if (rbuf != NULL)
356 while ((c = getc(rbuf)) != EOF)
357 putc(c, obuf);
358 #endif
359 fflush(obuf);
360 trunc(obuf);
361 if (fferror(obuf)) {
362 perror(mailname);
363 goto die;
365 alter(mailname);
366 if (p) {
367 if (p == 1)
368 printf(gettext("Held 1 message in %s\n"), mailname);
369 else
370 printf(gettext("Held %d messages in %s\n"), p,
371 mailname);
374 if (!noremove && (fsize(obuf) == 0) && (value("keep") == NOSTR)) {
375 if (stat(mailname, &st) >= 0)
376 PRIV(delempty(st.st_mode, mailname));
379 die:
380 if (rbuf) {
381 fclose(rbuf);
382 PRIV(removefile(tempResid));
384 if (obuf)
385 fclose(obuf);
386 if (issysmbox)
387 unlockmail();
388 sigset(SIGHUP, fhup);
389 sigset(SIGINT, fint);
390 sigset(SIGQUIT, fquit);
393 void
394 lockmail(void)
396 PRIV(maillock(lockname,10));
399 void
400 unlockmail(void)
402 PRIV(mailunlock());