xref: /illumos-gate/usr/src/cmd/mail/printmail.c (revision 2a8bcb4e)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include "mail.h"
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate  *	Print mail entries
34*7c478bd9Sstevel@tonic-gate  */
35*7c478bd9Sstevel@tonic-gate void
printmail()36*7c478bd9Sstevel@tonic-gate printmail()
37*7c478bd9Sstevel@tonic-gate {
38*7c478bd9Sstevel@tonic-gate 	static char pn[] = "printmail";
39*7c478bd9Sstevel@tonic-gate 	int	flg, curlet, showlet, k, print, aret, stret, rc;
40*7c478bd9Sstevel@tonic-gate 	int	nsmbox = 0;	/* 1 ==> mailbox is in non-standard place */
41*7c478bd9Sstevel@tonic-gate 	int	sav_j = -1;
42*7c478bd9Sstevel@tonic-gate 	char	*p, *getarg();
43*7c478bd9Sstevel@tonic-gate 	struct	stat stbuf;
44*7c478bd9Sstevel@tonic-gate 	struct	stat *stbufp;
45*7c478bd9Sstevel@tonic-gate 	int ttyf = isatty(1) ? TTY : ORDINARY;
46*7c478bd9Sstevel@tonic-gate 	char	readbuf[LSIZE];	/* holds user's response in interactive mode */
47*7c478bd9Sstevel@tonic-gate 	char	*resp;
48*7c478bd9Sstevel@tonic-gate 	gid_t	savedegid;
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate 	stbufp = &stbuf;
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate 	/*
53*7c478bd9Sstevel@tonic-gate 	 *	create working directory mbox name
54*7c478bd9Sstevel@tonic-gate 	 */
55*7c478bd9Sstevel@tonic-gate 	if ((hmbox = malloc(strlen(home) + strlen(mbox) + 1)) == NULL) {
56*7c478bd9Sstevel@tonic-gate 		errmsg(E_MBOX, "");
57*7c478bd9Sstevel@tonic-gate 		return;
58*7c478bd9Sstevel@tonic-gate 	}
59*7c478bd9Sstevel@tonic-gate 	cat(hmbox, home, mbox);
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 	/*
62*7c478bd9Sstevel@tonic-gate 	 *	If we are not using an alternate mailfile, then get
63*7c478bd9Sstevel@tonic-gate 	 *	the $MAIL value and build the filename for the mailfile.
64*7c478bd9Sstevel@tonic-gate 	 *	If $MAIL is set, but is NOT the 'standard' place, then
65*7c478bd9Sstevel@tonic-gate 	 *	use it but set flgf to circumvent :saved processing.
66*7c478bd9Sstevel@tonic-gate 	 */
67*7c478bd9Sstevel@tonic-gate 	if (!flgf) {
68*7c478bd9Sstevel@tonic-gate 		if ((p = malloc(strlen(maildir) + strlen(my_name) + 1))
69*7c478bd9Sstevel@tonic-gate 								== NULL) {
70*7c478bd9Sstevel@tonic-gate 			errmsg(E_MEM, "");
71*7c478bd9Sstevel@tonic-gate 			return;
72*7c478bd9Sstevel@tonic-gate 		}
73*7c478bd9Sstevel@tonic-gate 		cat(p, maildir, my_name);
74*7c478bd9Sstevel@tonic-gate 		if (((mailfile = getenv("MAIL")) == NULL) ||
75*7c478bd9Sstevel@tonic-gate 		    (strlen(mailfile) == 0)) {
76*7c478bd9Sstevel@tonic-gate 			/* $MAIL not set, use standard path to mailfile */
77*7c478bd9Sstevel@tonic-gate 			mailfile = p;
78*7c478bd9Sstevel@tonic-gate 		} else {
79*7c478bd9Sstevel@tonic-gate 			if (strcmp(mailfile, p) != 0) {
80*7c478bd9Sstevel@tonic-gate 			    flgf = 1;
81*7c478bd9Sstevel@tonic-gate 			    nsmbox = 1;
82*7c478bd9Sstevel@tonic-gate 			    Dout(pn, 0, "$MAIL ('%s') != standard path\n",
83*7c478bd9Sstevel@tonic-gate 				mailfile);
84*7c478bd9Sstevel@tonic-gate 			    Dout("", 0, "\tSetting flgf to 1.\n");
85*7c478bd9Sstevel@tonic-gate 			}
86*7c478bd9Sstevel@tonic-gate 			free(p);
87*7c478bd9Sstevel@tonic-gate 		}
88*7c478bd9Sstevel@tonic-gate 	}
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	/*
91*7c478bd9Sstevel@tonic-gate 	 *	Get ACCESS and MODIFICATION times of mailfile BEFORE we
92*7c478bd9Sstevel@tonic-gate 	 *	use it. This allows us to put them back when we are
93*7c478bd9Sstevel@tonic-gate 	 *	done. If we didn't, the shell would think NEW mail had
94*7c478bd9Sstevel@tonic-gate 	 *	arrived since the file times would have changed.
95*7c478bd9Sstevel@tonic-gate 	 */
96*7c478bd9Sstevel@tonic-gate 	stret = CERROR;
97*7c478bd9Sstevel@tonic-gate 	if (access(mailfile, A_EXIST) == A_OK) {
98*7c478bd9Sstevel@tonic-gate 		if ((stret = stat(mailfile, stbufp)) != A_OK) {
99*7c478bd9Sstevel@tonic-gate 			errmsg(E_FILE, "Cannot stat mailfile");
100*7c478bd9Sstevel@tonic-gate 			return;
101*7c478bd9Sstevel@tonic-gate 		}
102*7c478bd9Sstevel@tonic-gate 		mf_gid = stbufp->st_gid;
103*7c478bd9Sstevel@tonic-gate 		mf_uid = stbufp->st_uid;
104*7c478bd9Sstevel@tonic-gate 		utimep->actime = stbufp->st_atime;
105*7c478bd9Sstevel@tonic-gate 		utimep->modtime = stbufp->st_mtime;
106*7c478bd9Sstevel@tonic-gate 		file_size = stbufp->st_size;
107*7c478bd9Sstevel@tonic-gate 	}
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	/* Open the file as the real gid */
110*7c478bd9Sstevel@tonic-gate 	savedegid = getegid();
111*7c478bd9Sstevel@tonic-gate 	(void) setegid(getgid());
112*7c478bd9Sstevel@tonic-gate 	malf = fopen(mailfile, "r");
113*7c478bd9Sstevel@tonic-gate 	(void) setegid(savedegid);
114*7c478bd9Sstevel@tonic-gate 	/*
115*7c478bd9Sstevel@tonic-gate 	 *	stat succeeded, but we cannot access the mailfile
116*7c478bd9Sstevel@tonic-gate 	 */
117*7c478bd9Sstevel@tonic-gate 	if (stret == CSUCCESS && malf == NULL) {
118*7c478bd9Sstevel@tonic-gate 		char buf[MAXFILENAME+50];
119*7c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, sizeof (buf),
120*7c478bd9Sstevel@tonic-gate 		    "Invalid permissions on %s", mailfile);
121*7c478bd9Sstevel@tonic-gate 		errmsg(E_PERM, buf);
122*7c478bd9Sstevel@tonic-gate 		return;
123*7c478bd9Sstevel@tonic-gate 	} else
124*7c478bd9Sstevel@tonic-gate 	/*
125*7c478bd9Sstevel@tonic-gate 	 *	using an alternate mailfile, but we failed on access
126*7c478bd9Sstevel@tonic-gate 	 */
127*7c478bd9Sstevel@tonic-gate 	if (!nsmbox && flgf && (malf == NULL)) {
128*7c478bd9Sstevel@tonic-gate 		errmsg(E_FILE, "Cannot open mailfile");
129*7c478bd9Sstevel@tonic-gate 		return;
130*7c478bd9Sstevel@tonic-gate 	}
131*7c478bd9Sstevel@tonic-gate 	/*
132*7c478bd9Sstevel@tonic-gate 	 *	we failed to access OR the file is empty
133*7c478bd9Sstevel@tonic-gate 	 */
134*7c478bd9Sstevel@tonic-gate 	else if ((malf == NULL) || (stbuf.st_size == 0)) {
135*7c478bd9Sstevel@tonic-gate 		if (!flge && !flgE) {
136*7c478bd9Sstevel@tonic-gate 			printf("No mail.\n");
137*7c478bd9Sstevel@tonic-gate 		}
138*7c478bd9Sstevel@tonic-gate 		error = E_FLGE;
139*7c478bd9Sstevel@tonic-gate 		Dout(pn, 0, "error set to %d\n", error);
140*7c478bd9Sstevel@tonic-gate 		return;
141*7c478bd9Sstevel@tonic-gate 	}
142*7c478bd9Sstevel@tonic-gate 	if (flge)
143*7c478bd9Sstevel@tonic-gate 		return;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	if (flgE) {
146*7c478bd9Sstevel@tonic-gate 		if (utimep->modtime < utimep->actime) {
147*7c478bd9Sstevel@tonic-gate 			error = E_FLGE_OM;
148*7c478bd9Sstevel@tonic-gate 			Dout(pn, 0, "error set to %d\n", error);
149*7c478bd9Sstevel@tonic-gate 		}
150*7c478bd9Sstevel@tonic-gate 		return;
151*7c478bd9Sstevel@tonic-gate 	}
152*7c478bd9Sstevel@tonic-gate 	/*
153*7c478bd9Sstevel@tonic-gate 	 *	Secure the mailfile to guarantee integrity
154*7c478bd9Sstevel@tonic-gate 	 */
155*7c478bd9Sstevel@tonic-gate 	lock(my_name);
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	/*
158*7c478bd9Sstevel@tonic-gate 	 *	copy mail to temp file and mark each letter in the
159*7c478bd9Sstevel@tonic-gate 	 *	let array --- mailfile is still locked !!!
160*7c478bd9Sstevel@tonic-gate 	 */
161*7c478bd9Sstevel@tonic-gate 	mktmp();
162*7c478bd9Sstevel@tonic-gate 	copymt(malf, tmpf);
163*7c478bd9Sstevel@tonic-gate 	onlet = nlet;
164*7c478bd9Sstevel@tonic-gate 	fclose(malf);
165*7c478bd9Sstevel@tonic-gate 	fclose(tmpf);
166*7c478bd9Sstevel@tonic-gate 	unlock();	/* All done, OK to unlock now */
167*7c478bd9Sstevel@tonic-gate 	tmpf = doopen(lettmp, "r+", E_TMP);
168*7c478bd9Sstevel@tonic-gate 	changed = 0;
169*7c478bd9Sstevel@tonic-gate 	print = 1;
170*7c478bd9Sstevel@tonic-gate 	curlet = 0;
171*7c478bd9Sstevel@tonic-gate 	while (curlet < nlet) {
172*7c478bd9Sstevel@tonic-gate 		/*
173*7c478bd9Sstevel@tonic-gate 		 *	reverse order ?
174*7c478bd9Sstevel@tonic-gate 		 */
175*7c478bd9Sstevel@tonic-gate 		showlet = flgr ? curlet : nlet - curlet - 1;
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 		if (setjmp(sjbuf) == 0 && print != 0) {
178*7c478bd9Sstevel@tonic-gate 				/* -h says to print the headers first */
179*7c478bd9Sstevel@tonic-gate 				if (flgh) {
180*7c478bd9Sstevel@tonic-gate 					gethead(showlet, 0);
181*7c478bd9Sstevel@tonic-gate 					flgh = 0;	/* Only once */
182*7c478bd9Sstevel@tonic-gate 					/* set letter # to invalid # */
183*7c478bd9Sstevel@tonic-gate 					curlet--;
184*7c478bd9Sstevel@tonic-gate 					showlet =
185*7c478bd9Sstevel@tonic-gate 					    flgr ? curlet : nlet - curlet - 1;
186*7c478bd9Sstevel@tonic-gate 				} else {
187*7c478bd9Sstevel@tonic-gate 					if (showlet != sav_j) {
188*7c478bd9Sstevel@tonic-gate 						/* Looking at new message. */
189*7c478bd9Sstevel@tonic-gate 						/* Reset flag to override */
190*7c478bd9Sstevel@tonic-gate 						/* non-display of binary */
191*7c478bd9Sstevel@tonic-gate 						/* contents */
192*7c478bd9Sstevel@tonic-gate 						sav_j = showlet;
193*7c478bd9Sstevel@tonic-gate 						pflg = 0;
194*7c478bd9Sstevel@tonic-gate 						Pflg = flgP;
195*7c478bd9Sstevel@tonic-gate 					}
196*7c478bd9Sstevel@tonic-gate 					copylet(showlet, stdout, ttyf);
197*7c478bd9Sstevel@tonic-gate 				}
198*7c478bd9Sstevel@tonic-gate 		}
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 		/*
201*7c478bd9Sstevel@tonic-gate 		 *	print only
202*7c478bd9Sstevel@tonic-gate 		 */
203*7c478bd9Sstevel@tonic-gate 		if (flgp) {
204*7c478bd9Sstevel@tonic-gate 			curlet++;
205*7c478bd9Sstevel@tonic-gate 			continue;
206*7c478bd9Sstevel@tonic-gate 		}
207*7c478bd9Sstevel@tonic-gate 		/*
208*7c478bd9Sstevel@tonic-gate 		 *	Interactive
209*7c478bd9Sstevel@tonic-gate 		 */
210*7c478bd9Sstevel@tonic-gate 		interactive = 1;
211*7c478bd9Sstevel@tonic-gate 		setjmp(sjbuf);
212*7c478bd9Sstevel@tonic-gate 		stat(mailfile, stbufp);
213*7c478bd9Sstevel@tonic-gate 		if (stbufp->st_size != file_size) {
214*7c478bd9Sstevel@tonic-gate 			/*
215*7c478bd9Sstevel@tonic-gate 			 *	New mail has arrived, load it
216*7c478bd9Sstevel@tonic-gate 			 */
217*7c478bd9Sstevel@tonic-gate 			k = nlet;
218*7c478bd9Sstevel@tonic-gate 			lock(my_name);
219*7c478bd9Sstevel@tonic-gate 			malf = doopen(mailfile, "r", E_FILE);
220*7c478bd9Sstevel@tonic-gate 			fclose(tmpf);
221*7c478bd9Sstevel@tonic-gate 			tmpf = doopen(lettmp, "a", E_TMP);
222*7c478bd9Sstevel@tonic-gate 			fseek(malf, let[nlet].adr, 0);
223*7c478bd9Sstevel@tonic-gate 			copymt(malf, tmpf);
224*7c478bd9Sstevel@tonic-gate 			file_size = stbufp->st_size;
225*7c478bd9Sstevel@tonic-gate 			fclose(malf);
226*7c478bd9Sstevel@tonic-gate 			fclose(tmpf);
227*7c478bd9Sstevel@tonic-gate 			unlock();
228*7c478bd9Sstevel@tonic-gate 			tmpf = doopen(lettmp, "r+", E_TMP);
229*7c478bd9Sstevel@tonic-gate 			if (++k < nlet)
230*7c478bd9Sstevel@tonic-gate 				printf("New mail loaded into letters %d - %d\n",
231*7c478bd9Sstevel@tonic-gate 				    k, nlet);
232*7c478bd9Sstevel@tonic-gate 			else
233*7c478bd9Sstevel@tonic-gate 				printf("New mail loaded into letter %d\n",
234*7c478bd9Sstevel@tonic-gate 				    nlet);
235*7c478bd9Sstevel@tonic-gate 		}
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 		/* read the command */
238*7c478bd9Sstevel@tonic-gate 		printf("? ");
239*7c478bd9Sstevel@tonic-gate 		fflush(stdout);
240*7c478bd9Sstevel@tonic-gate 		fflush(stderr);
241*7c478bd9Sstevel@tonic-gate 		if (fgets(readbuf, sizeof (readbuf), stdin) == NULL) break;
242*7c478bd9Sstevel@tonic-gate 		resp = readbuf;
243*7c478bd9Sstevel@tonic-gate 		while (*resp == ' ' || *resp == '\t') resp++;
244*7c478bd9Sstevel@tonic-gate 		print = 1;
245*7c478bd9Sstevel@tonic-gate 		Dout(pn, 0, "resp = '%s'\n", resp);
246*7c478bd9Sstevel@tonic-gate 		if ((rc = atoi(resp)) != 0) {
247*7c478bd9Sstevel@tonic-gate 			if (!validmsg(rc)) print = 0;
248*7c478bd9Sstevel@tonic-gate 			else curlet = flgr ? rc - 1 : nlet - rc;
249*7c478bd9Sstevel@tonic-gate 		} else switch (resp[0]) {
250*7c478bd9Sstevel@tonic-gate 			default:
251*7c478bd9Sstevel@tonic-gate 				printf("Usage:\n");
252*7c478bd9Sstevel@tonic-gate 			/*
253*7c478bd9Sstevel@tonic-gate 			 *	help
254*7c478bd9Sstevel@tonic-gate 			 */
255*7c478bd9Sstevel@tonic-gate 			case '?':
256*7c478bd9Sstevel@tonic-gate 				print = 0;
257*7c478bd9Sstevel@tonic-gate 				for (rc = 0; help[rc]; rc++)
258*7c478bd9Sstevel@tonic-gate 					printf("%s", help[rc]);
259*7c478bd9Sstevel@tonic-gate 				break;
260*7c478bd9Sstevel@tonic-gate 			/*
261*7c478bd9Sstevel@tonic-gate 			 *	print message number of current message
262*7c478bd9Sstevel@tonic-gate 			 */
263*7c478bd9Sstevel@tonic-gate 			case '#':
264*7c478bd9Sstevel@tonic-gate 				print = 0;
265*7c478bd9Sstevel@tonic-gate 				if ((showlet == nlet) || (showlet < 0)) {
266*7c478bd9Sstevel@tonic-gate 					printf("No message selected yet.\n");
267*7c478bd9Sstevel@tonic-gate 				} else {
268*7c478bd9Sstevel@tonic-gate 					printf("Current message number is %d\n",
269*7c478bd9Sstevel@tonic-gate 					    showlet+1);
270*7c478bd9Sstevel@tonic-gate 				}
271*7c478bd9Sstevel@tonic-gate 				break;
272*7c478bd9Sstevel@tonic-gate 			/*
273*7c478bd9Sstevel@tonic-gate 			 *	headers
274*7c478bd9Sstevel@tonic-gate 			 */
275*7c478bd9Sstevel@tonic-gate 			case 'h':
276*7c478bd9Sstevel@tonic-gate 				print = 0;
277*7c478bd9Sstevel@tonic-gate 				if (resp[2] != 'd' &&
278*7c478bd9Sstevel@tonic-gate 				    resp[2] != 'a' &&
279*7c478bd9Sstevel@tonic-gate 				    (rc = getnumbr(resp+1)) > 0) {
280*7c478bd9Sstevel@tonic-gate 					showlet = rc - 1;
281*7c478bd9Sstevel@tonic-gate 					curlet = flgr ? rc - 1 : nlet - rc- 1;
282*7c478bd9Sstevel@tonic-gate 				}
283*7c478bd9Sstevel@tonic-gate 				if (rc == -1 && resp[2] != 'a' &&
284*7c478bd9Sstevel@tonic-gate 				    resp[2] != 'd')
285*7c478bd9Sstevel@tonic-gate 					break;
286*7c478bd9Sstevel@tonic-gate 				if (resp[2] == 'a') rc = 1;
287*7c478bd9Sstevel@tonic-gate 				else if (resp[2] == 'd') rc = 2;
288*7c478bd9Sstevel@tonic-gate 					else rc = 0;
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate /*
291*7c478bd9Sstevel@tonic-gate  *				if (!validmsg(showlet)) break;
292*7c478bd9Sstevel@tonic-gate  */
293*7c478bd9Sstevel@tonic-gate 				gethead(showlet, rc);
294*7c478bd9Sstevel@tonic-gate 				break;
295*7c478bd9Sstevel@tonic-gate 			/*
296*7c478bd9Sstevel@tonic-gate 			 *	skip entry
297*7c478bd9Sstevel@tonic-gate 			 */
298*7c478bd9Sstevel@tonic-gate 			case '+':
299*7c478bd9Sstevel@tonic-gate 			case 'n':
300*7c478bd9Sstevel@tonic-gate 			case '\n':
301*7c478bd9Sstevel@tonic-gate 				curlet++;
302*7c478bd9Sstevel@tonic-gate 				break;
303*7c478bd9Sstevel@tonic-gate 			case 'P':
304*7c478bd9Sstevel@tonic-gate 				Pflg++;
305*7c478bd9Sstevel@tonic-gate 				break;
306*7c478bd9Sstevel@tonic-gate 			case 'p':
307*7c478bd9Sstevel@tonic-gate 				pflg++;
308*7c478bd9Sstevel@tonic-gate 				break;
309*7c478bd9Sstevel@tonic-gate 			case 'x':
310*7c478bd9Sstevel@tonic-gate 				changed = 0;
311*7c478bd9Sstevel@tonic-gate 			case 'q':
312*7c478bd9Sstevel@tonic-gate 				goto donep;
313*7c478bd9Sstevel@tonic-gate 			/*
314*7c478bd9Sstevel@tonic-gate 			 *	Previous entry
315*7c478bd9Sstevel@tonic-gate 			 */
316*7c478bd9Sstevel@tonic-gate 			case '^':
317*7c478bd9Sstevel@tonic-gate 			case '-':
318*7c478bd9Sstevel@tonic-gate 				if (--curlet < 0) curlet = 0;
319*7c478bd9Sstevel@tonic-gate 				break;
320*7c478bd9Sstevel@tonic-gate 			/*
321*7c478bd9Sstevel@tonic-gate 			 *	Save in file without header
322*7c478bd9Sstevel@tonic-gate 			 */
323*7c478bd9Sstevel@tonic-gate 			case 'y':
324*7c478bd9Sstevel@tonic-gate 			case 'w':
325*7c478bd9Sstevel@tonic-gate 			/*
326*7c478bd9Sstevel@tonic-gate 			 *	Save mail with header
327*7c478bd9Sstevel@tonic-gate 			 */
328*7c478bd9Sstevel@tonic-gate 			case 's':
329*7c478bd9Sstevel@tonic-gate 				print = 0;
330*7c478bd9Sstevel@tonic-gate 				if (!validmsg(curlet)) break;
331*7c478bd9Sstevel@tonic-gate 				if (resp[1] == '\n' || resp[1] == '\0') {
332*7c478bd9Sstevel@tonic-gate 					cat(resp+1, hmbox, "");
333*7c478bd9Sstevel@tonic-gate 				} else if (resp[1] != ' ') {
334*7c478bd9Sstevel@tonic-gate 					printf("Invalid command\n");
335*7c478bd9Sstevel@tonic-gate 					break;
336*7c478bd9Sstevel@tonic-gate 				}
337*7c478bd9Sstevel@tonic-gate 				umask(umsave);
338*7c478bd9Sstevel@tonic-gate 				flg = 0;
339*7c478bd9Sstevel@tonic-gate 				if (getarg(lfil, resp + 1) == NULL) {
340*7c478bd9Sstevel@tonic-gate 					cat(resp + 1, hmbox, "");
341*7c478bd9Sstevel@tonic-gate 				}
342*7c478bd9Sstevel@tonic-gate 				malf = (FILE *)NULL;
343*7c478bd9Sstevel@tonic-gate 				p = resp + 1;
344*7c478bd9Sstevel@tonic-gate 				while ((p = getarg(lfil, p)) != NULL) {
345*7c478bd9Sstevel@tonic-gate 					if (flg) {
346*7c478bd9Sstevel@tonic-gate 					    fprintf(stderr,
347*7c478bd9Sstevel@tonic-gate 						"%s: File '%s' skipped\n",
348*7c478bd9Sstevel@tonic-gate 						program, lfil);
349*7c478bd9Sstevel@tonic-gate 					    continue;
350*7c478bd9Sstevel@tonic-gate 					}
351*7c478bd9Sstevel@tonic-gate 					malf = NULL;
352*7c478bd9Sstevel@tonic-gate 					if ((aret = legal(lfil))) {
353*7c478bd9Sstevel@tonic-gate 						malf = fopen(lfil, "a");
354*7c478bd9Sstevel@tonic-gate 					}
355*7c478bd9Sstevel@tonic-gate 					if ((malf == NULL) || (aret == 0)) {
356*7c478bd9Sstevel@tonic-gate 					    fprintf(stderr,
357*7c478bd9Sstevel@tonic-gate 						"%s: Cannot append to %s\n",
358*7c478bd9Sstevel@tonic-gate 						program, lfil);
359*7c478bd9Sstevel@tonic-gate 					    flg++;
360*7c478bd9Sstevel@tonic-gate 					} else if (aret == 2) {
361*7c478bd9Sstevel@tonic-gate 						chown(lfil, my_euid, my_gid);
362*7c478bd9Sstevel@tonic-gate 					}
363*7c478bd9Sstevel@tonic-gate 					if (!flg &&
364*7c478bd9Sstevel@tonic-gate 					    copylet(showlet, malf, resp[0] ==
365*7c478bd9Sstevel@tonic-gate 					    's'? ORDINARY: ZAP) == FALSE) {
366*7c478bd9Sstevel@tonic-gate 						fprintf(stderr,
367*7c478bd9Sstevel@tonic-gate 					    "%s: Cannot save mail to '%s'\n",
368*7c478bd9Sstevel@tonic-gate 						    program, lfil);
369*7c478bd9Sstevel@tonic-gate 						flg++;
370*7c478bd9Sstevel@tonic-gate 					} else
371*7c478bd9Sstevel@tonic-gate 						Dout(pn, 0, "!saved\n");
372*7c478bd9Sstevel@tonic-gate 					if (malf != (FILE *)NULL) {
373*7c478bd9Sstevel@tonic-gate 						fclose(malf);
374*7c478bd9Sstevel@tonic-gate 					}
375*7c478bd9Sstevel@tonic-gate 				}
376*7c478bd9Sstevel@tonic-gate 				umask(7);
377*7c478bd9Sstevel@tonic-gate 				if (!flg) {
378*7c478bd9Sstevel@tonic-gate 					setletr(showlet, resp[0]);
379*7c478bd9Sstevel@tonic-gate 					print = 1;
380*7c478bd9Sstevel@tonic-gate 					curlet++;
381*7c478bd9Sstevel@tonic-gate 				}
382*7c478bd9Sstevel@tonic-gate 				break;
383*7c478bd9Sstevel@tonic-gate 			/*
384*7c478bd9Sstevel@tonic-gate 			 *	Reply to a letter
385*7c478bd9Sstevel@tonic-gate 			 */
386*7c478bd9Sstevel@tonic-gate 			case 'r':
387*7c478bd9Sstevel@tonic-gate 				print = 0;
388*7c478bd9Sstevel@tonic-gate 				if (!validmsg(curlet)) break;
389*7c478bd9Sstevel@tonic-gate 				replying = 1;
390*7c478bd9Sstevel@tonic-gate 				for (k = 1; resp[k] == ' ' || resp[k] == '\t';
391*7c478bd9Sstevel@tonic-gate 				    ++k);
392*7c478bd9Sstevel@tonic-gate 				resp[strlen(resp)-1] = '\0';
393*7c478bd9Sstevel@tonic-gate 				(void) strlcpy(m_sendto, resp+k,
394*7c478bd9Sstevel@tonic-gate 				    sizeof (m_sendto));
395*7c478bd9Sstevel@tonic-gate 				goback(showlet);
396*7c478bd9Sstevel@tonic-gate 				replying = 0;
397*7c478bd9Sstevel@tonic-gate 				setletr(showlet, resp[0]);
398*7c478bd9Sstevel@tonic-gate 				break;
399*7c478bd9Sstevel@tonic-gate 			/*
400*7c478bd9Sstevel@tonic-gate 			 *	Undelete
401*7c478bd9Sstevel@tonic-gate 			 */
402*7c478bd9Sstevel@tonic-gate 			case 'u':
403*7c478bd9Sstevel@tonic-gate 				print = 0;
404*7c478bd9Sstevel@tonic-gate 				if ((k = getnumbr(resp+1)) <= 0) k = showlet;
405*7c478bd9Sstevel@tonic-gate 				else k--;
406*7c478bd9Sstevel@tonic-gate 				if (!validmsg(k)) break;
407*7c478bd9Sstevel@tonic-gate 				setletr(k, ' ');
408*7c478bd9Sstevel@tonic-gate 				break;
409*7c478bd9Sstevel@tonic-gate 			/*
410*7c478bd9Sstevel@tonic-gate 			 *	Mail letter to someone else
411*7c478bd9Sstevel@tonic-gate 			 */
412*7c478bd9Sstevel@tonic-gate 			case 'm':
413*7c478bd9Sstevel@tonic-gate 				{
414*7c478bd9Sstevel@tonic-gate 				reciplist list;
415*7c478bd9Sstevel@tonic-gate 				print = 0;
416*7c478bd9Sstevel@tonic-gate 				if (!validmsg(curlet)) break;
417*7c478bd9Sstevel@tonic-gate 				new_reciplist(&list);
418*7c478bd9Sstevel@tonic-gate 				flg = 0;
419*7c478bd9Sstevel@tonic-gate 				k = 0;
420*7c478bd9Sstevel@tonic-gate 				if (substr(resp, " -") != -1 ||
421*7c478bd9Sstevel@tonic-gate 					substr(resp, "\t-") != -1) {
422*7c478bd9Sstevel@tonic-gate 					printf("Only users may be specified\n");
423*7c478bd9Sstevel@tonic-gate 					break;
424*7c478bd9Sstevel@tonic-gate 				}
425*7c478bd9Sstevel@tonic-gate 				p = resp + 1;
426*7c478bd9Sstevel@tonic-gate 				while ((p = getarg(lfil, p)) != NULL) {
427*7c478bd9Sstevel@tonic-gate 					char *env;
428*7c478bd9Sstevel@tonic-gate 					if (lfil[0] == '$') {
429*7c478bd9Sstevel@tonic-gate 						if (!(env = getenv(&lfil[1]))) {
430*7c478bd9Sstevel@tonic-gate 							fprintf(stderr,
431*7c478bd9Sstevel@tonic-gate 				"%s: %s has no value or is not exported.\n",
432*7c478bd9Sstevel@tonic-gate 							    program, lfil);
433*7c478bd9Sstevel@tonic-gate 							flg++;
434*7c478bd9Sstevel@tonic-gate 						} else
435*7c478bd9Sstevel@tonic-gate 							add_recip(&list, env,
436*7c478bd9Sstevel@tonic-gate 							    FALSE);
437*7c478bd9Sstevel@tonic-gate 						k++;
438*7c478bd9Sstevel@tonic-gate 					} else if (lfil[0] != '\0') {
439*7c478bd9Sstevel@tonic-gate 						add_recip(&list, lfil, FALSE);
440*7c478bd9Sstevel@tonic-gate 						k++;
441*7c478bd9Sstevel@tonic-gate 					}
442*7c478bd9Sstevel@tonic-gate 				}
443*7c478bd9Sstevel@tonic-gate 				(void) strlcpy(Rpath, my_name, sizeof (Rpath));
444*7c478bd9Sstevel@tonic-gate 				sending = TRUE;
445*7c478bd9Sstevel@tonic-gate 				flg += sendlist(&list, showlet, 0);
446*7c478bd9Sstevel@tonic-gate 				sending = FALSE;
447*7c478bd9Sstevel@tonic-gate 				if (k) {
448*7c478bd9Sstevel@tonic-gate 					if (!flg) {
449*7c478bd9Sstevel@tonic-gate 						setletr(showlet, 'm');
450*7c478bd9Sstevel@tonic-gate 						print = 1;
451*7c478bd9Sstevel@tonic-gate 						curlet++;
452*7c478bd9Sstevel@tonic-gate 					}
453*7c478bd9Sstevel@tonic-gate 				} else
454*7c478bd9Sstevel@tonic-gate 					printf("Invalid command\n");
455*7c478bd9Sstevel@tonic-gate 				del_reciplist(&list);
456*7c478bd9Sstevel@tonic-gate 				break;
457*7c478bd9Sstevel@tonic-gate 				}
458*7c478bd9Sstevel@tonic-gate 			/*
459*7c478bd9Sstevel@tonic-gate 			 *	Read new letters
460*7c478bd9Sstevel@tonic-gate 			 */
461*7c478bd9Sstevel@tonic-gate 			case 'a':
462*7c478bd9Sstevel@tonic-gate 				if (onlet == nlet) {
463*7c478bd9Sstevel@tonic-gate 					printf("No new mail\n");
464*7c478bd9Sstevel@tonic-gate 					print = 0;
465*7c478bd9Sstevel@tonic-gate 					break;
466*7c478bd9Sstevel@tonic-gate 				}
467*7c478bd9Sstevel@tonic-gate 				curlet = 0;
468*7c478bd9Sstevel@tonic-gate 				print = 1;
469*7c478bd9Sstevel@tonic-gate 				break;
470*7c478bd9Sstevel@tonic-gate 			/*
471*7c478bd9Sstevel@tonic-gate 			 *	Escape to shell
472*7c478bd9Sstevel@tonic-gate 			 */
473*7c478bd9Sstevel@tonic-gate 			case '!':
474*7c478bd9Sstevel@tonic-gate 				systm(resp + 1);
475*7c478bd9Sstevel@tonic-gate 				printf("!\n");
476*7c478bd9Sstevel@tonic-gate 				print = 0;
477*7c478bd9Sstevel@tonic-gate 				break;
478*7c478bd9Sstevel@tonic-gate 			/*
479*7c478bd9Sstevel@tonic-gate 			 *	Delete an entry
480*7c478bd9Sstevel@tonic-gate 			 */
481*7c478bd9Sstevel@tonic-gate 			case 'd':
482*7c478bd9Sstevel@tonic-gate 				print = 0;
483*7c478bd9Sstevel@tonic-gate 				k = 0;
484*7c478bd9Sstevel@tonic-gate 				if (strncmp("dq", resp, 2) != SAME &&
485*7c478bd9Sstevel@tonic-gate 					strncmp("dp", resp, 2) != SAME)
486*7c478bd9Sstevel@tonic-gate 					if ((k = getnumbr(resp+1)) == -1) break;
487*7c478bd9Sstevel@tonic-gate 				if (k == 0) {
488*7c478bd9Sstevel@tonic-gate 					k = showlet;
489*7c478bd9Sstevel@tonic-gate 					if (!validmsg(curlet)) break;
490*7c478bd9Sstevel@tonic-gate 					print = 1;
491*7c478bd9Sstevel@tonic-gate 					curlet++;
492*7c478bd9Sstevel@tonic-gate 				} else	k--;
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 				setletr(k, 'd');
495*7c478bd9Sstevel@tonic-gate 				if (resp[1] == 'p') print = 1;
496*7c478bd9Sstevel@tonic-gate 				else if (resp[1] == 'q') goto donep;
497*7c478bd9Sstevel@tonic-gate 				break;
498*7c478bd9Sstevel@tonic-gate 		}
499*7c478bd9Sstevel@tonic-gate 	}
500*7c478bd9Sstevel@tonic-gate 	/*
501*7c478bd9Sstevel@tonic-gate 	 *	Copy updated mailfile back
502*7c478bd9Sstevel@tonic-gate 	 */
503*7c478bd9Sstevel@tonic-gate donep:
504*7c478bd9Sstevel@tonic-gate 	if (changed) {
505*7c478bd9Sstevel@tonic-gate 		copyback();
506*7c478bd9Sstevel@tonic-gate 		stamp();
507*7c478bd9Sstevel@tonic-gate 	}
508*7c478bd9Sstevel@tonic-gate }
509