xref: /titanic_52/usr/src/cmd/mailx/cmd3.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 1985-2002 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 /*
32*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
33*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
34*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
37*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
38*7c478bd9Sstevel@tonic-gate  * contributors.
39*7c478bd9Sstevel@tonic-gate  */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate #include "rcv.h"
44*7c478bd9Sstevel@tonic-gate #include <locale.h>
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /*
47*7c478bd9Sstevel@tonic-gate  * mailx -- a modified version of a University of California at Berkeley
48*7c478bd9Sstevel@tonic-gate  *	mail program
49*7c478bd9Sstevel@tonic-gate  *
50*7c478bd9Sstevel@tonic-gate  * Still more user commands.
51*7c478bd9Sstevel@tonic-gate  */
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate static int	bangexp(char *str);
54*7c478bd9Sstevel@tonic-gate static int	diction(const void *a, const void *b);
55*7c478bd9Sstevel@tonic-gate static char	*getfilename(char *name, int *aedit);
56*7c478bd9Sstevel@tonic-gate static int	resp1(int *msgvec, int useauthor);
57*7c478bd9Sstevel@tonic-gate static int	Resp1(int *msgvec, int useauthor);
58*7c478bd9Sstevel@tonic-gate static char	*reedit(char *subj);
59*7c478bd9Sstevel@tonic-gate static int	shell1(char *str);
60*7c478bd9Sstevel@tonic-gate static void	sort(char **list);
61*7c478bd9Sstevel@tonic-gate static char	*replyto(struct message *mp, char **f);
62*7c478bd9Sstevel@tonic-gate static int	reply2sender(void);
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate static char	prevfile[PATHSIZE];
65*7c478bd9Sstevel@tonic-gate static char	origprevfile[PATHSIZE];
66*7c478bd9Sstevel@tonic-gate static char	lastbang[BUFSIZ];
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * Process a shell escape by saving signals, ignoring signals,
70*7c478bd9Sstevel@tonic-gate  * and forking a sh -c
71*7c478bd9Sstevel@tonic-gate  */
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate int
74*7c478bd9Sstevel@tonic-gate shell(char *str)
75*7c478bd9Sstevel@tonic-gate {
76*7c478bd9Sstevel@tonic-gate 	shell1(str);
77*7c478bd9Sstevel@tonic-gate 	printf("!\n");
78*7c478bd9Sstevel@tonic-gate 	return(0);
79*7c478bd9Sstevel@tonic-gate }
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate static int
82*7c478bd9Sstevel@tonic-gate shell1(char *str)
83*7c478bd9Sstevel@tonic-gate {
84*7c478bd9Sstevel@tonic-gate 	void (*sig[2])(int);
85*7c478bd9Sstevel@tonic-gate 	register int t;
86*7c478bd9Sstevel@tonic-gate 	register pid_t p;
87*7c478bd9Sstevel@tonic-gate 	char *Shell;
88*7c478bd9Sstevel@tonic-gate 	char cmd[BUFSIZ];
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	nstrcpy(cmd, sizeof (cmd), str);
91*7c478bd9Sstevel@tonic-gate 	if (bangexp(cmd) < 0)
92*7c478bd9Sstevel@tonic-gate 		return(-1);
93*7c478bd9Sstevel@tonic-gate 	if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0')
94*7c478bd9Sstevel@tonic-gate 		Shell = SHELL;
95*7c478bd9Sstevel@tonic-gate 	for (t = SIGINT; t <= SIGQUIT; t++)
96*7c478bd9Sstevel@tonic-gate 		sig[t-SIGINT] = sigset(t, SIG_IGN);
97*7c478bd9Sstevel@tonic-gate 	p = vfork();
98*7c478bd9Sstevel@tonic-gate 	if (p == 0) {
99*7c478bd9Sstevel@tonic-gate 		setuid(getuid());
100*7c478bd9Sstevel@tonic-gate 		sigchild();
101*7c478bd9Sstevel@tonic-gate 		for (t = SIGINT; t <= SIGQUIT; t++)
102*7c478bd9Sstevel@tonic-gate 			if (sig[t-SIGINT] != SIG_IGN)
103*7c478bd9Sstevel@tonic-gate 				sigsys(t, SIG_DFL);
104*7c478bd9Sstevel@tonic-gate 		execlp(Shell, Shell, "-c", cmd, (char *)0);
105*7c478bd9Sstevel@tonic-gate 		perror(Shell);
106*7c478bd9Sstevel@tonic-gate 		_exit(1);
107*7c478bd9Sstevel@tonic-gate 	}
108*7c478bd9Sstevel@tonic-gate 	while (wait(0) != p)
109*7c478bd9Sstevel@tonic-gate 		;
110*7c478bd9Sstevel@tonic-gate 	if (p == (pid_t)-1)
111*7c478bd9Sstevel@tonic-gate 		perror("fork");
112*7c478bd9Sstevel@tonic-gate 	for (t = SIGINT; t <= SIGQUIT; t++)
113*7c478bd9Sstevel@tonic-gate 		sigset(t, sig[t-SIGINT]);
114*7c478bd9Sstevel@tonic-gate 	return(0);
115*7c478bd9Sstevel@tonic-gate }
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate /*
118*7c478bd9Sstevel@tonic-gate  * Fork an interactive shell.
119*7c478bd9Sstevel@tonic-gate  */
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate int
122*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
123*7c478bd9Sstevel@tonic-gate dosh(char *)
124*7c478bd9Sstevel@tonic-gate #else
125*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
126*7c478bd9Sstevel@tonic-gate dosh(char *s)
127*7c478bd9Sstevel@tonic-gate #endif
128*7c478bd9Sstevel@tonic-gate {
129*7c478bd9Sstevel@tonic-gate 	void (*sig[2])(int);
130*7c478bd9Sstevel@tonic-gate 	register int t;
131*7c478bd9Sstevel@tonic-gate 	register pid_t p;
132*7c478bd9Sstevel@tonic-gate 	char *Shell;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0')
135*7c478bd9Sstevel@tonic-gate 		Shell = SHELL;
136*7c478bd9Sstevel@tonic-gate 	for (t = SIGINT; t <= SIGQUIT; t++)
137*7c478bd9Sstevel@tonic-gate 		sig[t-SIGINT] = sigset(t, SIG_IGN);
138*7c478bd9Sstevel@tonic-gate 	p = vfork();
139*7c478bd9Sstevel@tonic-gate 	if (p == 0) {
140*7c478bd9Sstevel@tonic-gate 		setuid(getuid());
141*7c478bd9Sstevel@tonic-gate 		sigchild();
142*7c478bd9Sstevel@tonic-gate 		for (t = SIGINT; t <= SIGQUIT; t++)
143*7c478bd9Sstevel@tonic-gate 			if (sig[t-SIGINT] != SIG_IGN)
144*7c478bd9Sstevel@tonic-gate 				sigset(t, SIG_DFL);
145*7c478bd9Sstevel@tonic-gate 		execlp(Shell, Shell, (char *)0);
146*7c478bd9Sstevel@tonic-gate 		perror(Shell);
147*7c478bd9Sstevel@tonic-gate 		_exit(1);
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 	while (wait(0) != p)
150*7c478bd9Sstevel@tonic-gate 		;
151*7c478bd9Sstevel@tonic-gate 	if (p == (pid_t)-1)
152*7c478bd9Sstevel@tonic-gate 		perror("fork");
153*7c478bd9Sstevel@tonic-gate 	for (t = SIGINT; t <= SIGQUIT; t++)
154*7c478bd9Sstevel@tonic-gate 		sigset(t, sig[t-SIGINT]);
155*7c478bd9Sstevel@tonic-gate 	putchar('\n');
156*7c478bd9Sstevel@tonic-gate 	return(0);
157*7c478bd9Sstevel@tonic-gate }
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate /*
160*7c478bd9Sstevel@tonic-gate  * Expand the shell escape by expanding unescaped !'s into the
161*7c478bd9Sstevel@tonic-gate  * last issued command where possible.
162*7c478bd9Sstevel@tonic-gate  */
163*7c478bd9Sstevel@tonic-gate static int
164*7c478bd9Sstevel@tonic-gate bangexp(char *str)
165*7c478bd9Sstevel@tonic-gate {
166*7c478bd9Sstevel@tonic-gate 	char bangbuf[BUFSIZ];
167*7c478bd9Sstevel@tonic-gate 	register char *cp, *cp2;
168*7c478bd9Sstevel@tonic-gate 	register int n;
169*7c478bd9Sstevel@tonic-gate 	int changed = 0;
170*7c478bd9Sstevel@tonic-gate 	int bangit = (value("bang")!=NOSTR);
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	cp = str;
173*7c478bd9Sstevel@tonic-gate 	cp2 = bangbuf;
174*7c478bd9Sstevel@tonic-gate 	n = BUFSIZ;
175*7c478bd9Sstevel@tonic-gate 	while (*cp) {
176*7c478bd9Sstevel@tonic-gate 		if (*cp=='!' && bangit) {
177*7c478bd9Sstevel@tonic-gate 			if (n < (int)strlen(lastbang)) {
178*7c478bd9Sstevel@tonic-gate overf:
179*7c478bd9Sstevel@tonic-gate 				printf(gettext("Command buffer overflow\n"));
180*7c478bd9Sstevel@tonic-gate 				return(-1);
181*7c478bd9Sstevel@tonic-gate 			}
182*7c478bd9Sstevel@tonic-gate 			changed++;
183*7c478bd9Sstevel@tonic-gate 			strcpy(cp2, lastbang);
184*7c478bd9Sstevel@tonic-gate 			cp2 += strlen(lastbang);
185*7c478bd9Sstevel@tonic-gate 			n -= strlen(lastbang);
186*7c478bd9Sstevel@tonic-gate 			cp++;
187*7c478bd9Sstevel@tonic-gate 			continue;
188*7c478bd9Sstevel@tonic-gate 		}
189*7c478bd9Sstevel@tonic-gate 		if (*cp == '\\' && cp[1] == '!') {
190*7c478bd9Sstevel@tonic-gate 			if (--n <= 1)
191*7c478bd9Sstevel@tonic-gate 				goto overf;
192*7c478bd9Sstevel@tonic-gate 			*cp2++ = '!';
193*7c478bd9Sstevel@tonic-gate 			cp += 2;
194*7c478bd9Sstevel@tonic-gate 			changed++;
195*7c478bd9Sstevel@tonic-gate 		}
196*7c478bd9Sstevel@tonic-gate 		if (--n <= 1)
197*7c478bd9Sstevel@tonic-gate 			goto overf;
198*7c478bd9Sstevel@tonic-gate 		*cp2++ = *cp++;
199*7c478bd9Sstevel@tonic-gate 	}
200*7c478bd9Sstevel@tonic-gate 	*cp2 = 0;
201*7c478bd9Sstevel@tonic-gate 	if (changed) {
202*7c478bd9Sstevel@tonic-gate 		printf("!%s\n", bangbuf);
203*7c478bd9Sstevel@tonic-gate 		fflush(stdout);
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate 	nstrcpy(str, BUFSIZ, bangbuf);
206*7c478bd9Sstevel@tonic-gate 	nstrcpy(lastbang, sizeof (lastbang), bangbuf);
207*7c478bd9Sstevel@tonic-gate 	return(0);
208*7c478bd9Sstevel@tonic-gate }
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate /*
211*7c478bd9Sstevel@tonic-gate  * Print out a nice help message from some file or another.
212*7c478bd9Sstevel@tonic-gate  */
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate int
215*7c478bd9Sstevel@tonic-gate help(void)
216*7c478bd9Sstevel@tonic-gate {
217*7c478bd9Sstevel@tonic-gate 	register c;
218*7c478bd9Sstevel@tonic-gate 	register FILE *f;
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	if ((f = fopen(HELPFILE, "r")) == NULL) {
221*7c478bd9Sstevel@tonic-gate 		printf(gettext("No help just now.\n"));
222*7c478bd9Sstevel@tonic-gate 		return(1);
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate 	while ((c = getc(f)) != EOF)
225*7c478bd9Sstevel@tonic-gate 		putchar(c);
226*7c478bd9Sstevel@tonic-gate 	fclose(f);
227*7c478bd9Sstevel@tonic-gate 	return(0);
228*7c478bd9Sstevel@tonic-gate }
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate /*
231*7c478bd9Sstevel@tonic-gate  * Change user's working directory.
232*7c478bd9Sstevel@tonic-gate  */
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate int
235*7c478bd9Sstevel@tonic-gate schdir(char *str)
236*7c478bd9Sstevel@tonic-gate {
237*7c478bd9Sstevel@tonic-gate 	register char *cp;
238*7c478bd9Sstevel@tonic-gate 	char cwd[PATHSIZE], file[PATHSIZE];
239*7c478bd9Sstevel@tonic-gate 	static char efile[PATHSIZE];
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 	for (cp = str; *cp == ' '; cp++)
242*7c478bd9Sstevel@tonic-gate 		;
243*7c478bd9Sstevel@tonic-gate 	if (*cp == '\0')
244*7c478bd9Sstevel@tonic-gate 		cp = homedir;
245*7c478bd9Sstevel@tonic-gate 	else
246*7c478bd9Sstevel@tonic-gate 		if ((cp = expand(cp)) == NOSTR)
247*7c478bd9Sstevel@tonic-gate 			return(1);
248*7c478bd9Sstevel@tonic-gate 	if (editfile != NOSTR && (*editfile != '/' || mailname[0] != '/')) {
249*7c478bd9Sstevel@tonic-gate 		if (getcwd(cwd, (int)sizeof (cwd)) == 0) {
250*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
251*7c478bd9Sstevel@tonic-gate 			    gettext("Can't get current directory: %s\n"), cwd);
252*7c478bd9Sstevel@tonic-gate 			return(1);
253*7c478bd9Sstevel@tonic-gate 		}
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate 	if (chdir(cp) < 0) {
256*7c478bd9Sstevel@tonic-gate 		perror(cp);
257*7c478bd9Sstevel@tonic-gate 		return(1);
258*7c478bd9Sstevel@tonic-gate 	}
259*7c478bd9Sstevel@tonic-gate 	/*
260*7c478bd9Sstevel@tonic-gate 	 * Convert previously relative names to absolute names.
261*7c478bd9Sstevel@tonic-gate 	 */
262*7c478bd9Sstevel@tonic-gate 	if (editfile != NOSTR && *editfile != '/') {
263*7c478bd9Sstevel@tonic-gate 		snprintf(file, sizeof (file), "%s/%s", cwd, editfile);
264*7c478bd9Sstevel@tonic-gate 		nstrcpy(efile, sizeof (efile), file);
265*7c478bd9Sstevel@tonic-gate 		editfile = efile;
266*7c478bd9Sstevel@tonic-gate 	}
267*7c478bd9Sstevel@tonic-gate 	if (mailname[0] != '/') {
268*7c478bd9Sstevel@tonic-gate 		snprintf(file, sizeof (file), "%s/%s", cwd, mailname);
269*7c478bd9Sstevel@tonic-gate 		nstrcpy(mailname, PATHSIZE, file);
270*7c478bd9Sstevel@tonic-gate 	}
271*7c478bd9Sstevel@tonic-gate 	return(0);
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate /*
275*7c478bd9Sstevel@tonic-gate  * Two versions of reply.  Reply to all names in message or reply
276*7c478bd9Sstevel@tonic-gate  * to only sender of message, depending on setting of "replyall".
277*7c478bd9Sstevel@tonic-gate  */
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate int
280*7c478bd9Sstevel@tonic-gate respond(int *msgvec)
281*7c478bd9Sstevel@tonic-gate {
282*7c478bd9Sstevel@tonic-gate 	if (reply2sender())
283*7c478bd9Sstevel@tonic-gate 		return(resp1(msgvec, 0));
284*7c478bd9Sstevel@tonic-gate 	else
285*7c478bd9Sstevel@tonic-gate 		return(Resp1(msgvec, 0));
286*7c478bd9Sstevel@tonic-gate }
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate int
289*7c478bd9Sstevel@tonic-gate followup(int *msgvec)
290*7c478bd9Sstevel@tonic-gate {
291*7c478bd9Sstevel@tonic-gate 	if (reply2sender())
292*7c478bd9Sstevel@tonic-gate 		return(resp1(msgvec, 1));
293*7c478bd9Sstevel@tonic-gate 	else
294*7c478bd9Sstevel@tonic-gate 		return(Resp1(msgvec, 1));
295*7c478bd9Sstevel@tonic-gate }
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate int
298*7c478bd9Sstevel@tonic-gate replyall(int *msgvec)
299*7c478bd9Sstevel@tonic-gate {
300*7c478bd9Sstevel@tonic-gate 	return(resp1(msgvec, 0));
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate static int
304*7c478bd9Sstevel@tonic-gate resp1(int *msgvec, int useauthor)
305*7c478bd9Sstevel@tonic-gate {
306*7c478bd9Sstevel@tonic-gate 	struct message *mp;
307*7c478bd9Sstevel@tonic-gate 	char *cp, *buf, *rcv, *skin_rcv, *reply2, **ap, *returnaddr;
308*7c478bd9Sstevel@tonic-gate 	struct name *np;
309*7c478bd9Sstevel@tonic-gate 	struct header head;
310*7c478bd9Sstevel@tonic-gate 	char mylocalname[BUFSIZ], mydomname[BUFSIZ];
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	if (msgvec[1] != 0) {
313*7c478bd9Sstevel@tonic-gate 		printf(gettext(
314*7c478bd9Sstevel@tonic-gate 		    "Sorry, can't reply to multiple messages at once\n"));
315*7c478bd9Sstevel@tonic-gate 		return(1);
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 	snprintf(mydomname, sizeof (mydomname), "%s@%s", myname, domain);
318*7c478bd9Sstevel@tonic-gate 	snprintf(mylocalname, sizeof (mylocalname), "%s@%s", myname, host);
319*7c478bd9Sstevel@tonic-gate 	returnaddr = value("returnaddr");
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	mp = &message[msgvec[0] - 1];
322*7c478bd9Sstevel@tonic-gate 	dot = mp;
323*7c478bd9Sstevel@tonic-gate 	reply2 = replyto(mp, &rcv);
324*7c478bd9Sstevel@tonic-gate 	cp = skin(hfield("to", mp, addto));
325*7c478bd9Sstevel@tonic-gate 	if (cp != NOSTR) {
326*7c478bd9Sstevel@tonic-gate 		buf = (char *)salloc(strlen(reply2) + strlen(cp) + 2);
327*7c478bd9Sstevel@tonic-gate 		strcpy(buf, reply2);
328*7c478bd9Sstevel@tonic-gate 		strcat(buf, " ");
329*7c478bd9Sstevel@tonic-gate 		strcat(buf, cp);
330*7c478bd9Sstevel@tonic-gate 	} else
331*7c478bd9Sstevel@tonic-gate 		buf = reply2;
332*7c478bd9Sstevel@tonic-gate 	np = elide(extract(buf, GTO));
333*7c478bd9Sstevel@tonic-gate #ifdef	OPTIM
334*7c478bd9Sstevel@tonic-gate 	/* rcv = netrename(rcv); */
335*7c478bd9Sstevel@tonic-gate #endif	/* OPTIM */
336*7c478bd9Sstevel@tonic-gate 	/*
337*7c478bd9Sstevel@tonic-gate 	 * Delete my name from the reply list,
338*7c478bd9Sstevel@tonic-gate 	 * and with it, all my alternate names.
339*7c478bd9Sstevel@tonic-gate 	 */
340*7c478bd9Sstevel@tonic-gate 	skin_rcv = skin(rcv);
341*7c478bd9Sstevel@tonic-gate 	mapf(np, skin_rcv);
342*7c478bd9Sstevel@tonic-gate 	np = delname(np, myname);
343*7c478bd9Sstevel@tonic-gate 	np = delname(np, mylocalname);
344*7c478bd9Sstevel@tonic-gate 	np = delname(np, mydomname);
345*7c478bd9Sstevel@tonic-gate 	if (returnaddr && *returnaddr)
346*7c478bd9Sstevel@tonic-gate 		np = delname(np, returnaddr);
347*7c478bd9Sstevel@tonic-gate 	if (altnames != 0)
348*7c478bd9Sstevel@tonic-gate 		for (ap = altnames; *ap; ap++)
349*7c478bd9Sstevel@tonic-gate 			np = delname(np, *ap);
350*7c478bd9Sstevel@tonic-gate 	head.h_seq = 1;
351*7c478bd9Sstevel@tonic-gate 	cp = detract(np, 0);
352*7c478bd9Sstevel@tonic-gate 	if (cp == NOSTR) {
353*7c478bd9Sstevel@tonic-gate 		if (reply2)
354*7c478bd9Sstevel@tonic-gate 			cp = unuucp(reply2);
355*7c478bd9Sstevel@tonic-gate 		else
356*7c478bd9Sstevel@tonic-gate 			cp = unuucp(rcv);
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate 	head.h_to = cp;
359*7c478bd9Sstevel@tonic-gate 	head.h_subject = hfield("subject", mp, addone);
360*7c478bd9Sstevel@tonic-gate 	if (head.h_subject == NOSTR)
361*7c478bd9Sstevel@tonic-gate 		head.h_subject = hfield("subj", mp, addone);
362*7c478bd9Sstevel@tonic-gate 	head.h_subject = reedit(head.h_subject);
363*7c478bd9Sstevel@tonic-gate 	head.h_cc = NOSTR;
364*7c478bd9Sstevel@tonic-gate 	cp = skin(hfield("cc", mp, addto));
365*7c478bd9Sstevel@tonic-gate 	if (cp != NOSTR) {
366*7c478bd9Sstevel@tonic-gate 		np = elide(extract(cp, GCC));
367*7c478bd9Sstevel@tonic-gate 		mapf(np, skin_rcv);
368*7c478bd9Sstevel@tonic-gate 		np = delname(np, myname);
369*7c478bd9Sstevel@tonic-gate 		np = delname(np, mylocalname);
370*7c478bd9Sstevel@tonic-gate 		np = delname(np, mydomname);
371*7c478bd9Sstevel@tonic-gate 		if (returnaddr && *returnaddr)
372*7c478bd9Sstevel@tonic-gate 			np = delname(np, returnaddr);
373*7c478bd9Sstevel@tonic-gate 		np = delname(np, skin_rcv);
374*7c478bd9Sstevel@tonic-gate 		if (altnames != 0)
375*7c478bd9Sstevel@tonic-gate 			for (ap = altnames; *ap; ap++)
376*7c478bd9Sstevel@tonic-gate 				np = delname(np, *ap);
377*7c478bd9Sstevel@tonic-gate 		head.h_cc = detract(np, 0);
378*7c478bd9Sstevel@tonic-gate 	}
379*7c478bd9Sstevel@tonic-gate 	head.h_bcc = NOSTR;
380*7c478bd9Sstevel@tonic-gate 	head.h_defopt = NOSTR;
381*7c478bd9Sstevel@tonic-gate 	head.h_others = NOSTRPTR;
382*7c478bd9Sstevel@tonic-gate 	mail1(&head, useauthor, useauthor ? rcv : NOSTR);
383*7c478bd9Sstevel@tonic-gate 	return(0);
384*7c478bd9Sstevel@tonic-gate }
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate void
387*7c478bd9Sstevel@tonic-gate getrecf(char *buf, char *recfile, int useauthor, int sz_recfile)
388*7c478bd9Sstevel@tonic-gate {
389*7c478bd9Sstevel@tonic-gate 	register char *bp, *cp;
390*7c478bd9Sstevel@tonic-gate 	register char *recf = recfile;
391*7c478bd9Sstevel@tonic-gate 	register int folderize;
392*7c478bd9Sstevel@tonic-gate 	char fldr[BUFSIZ];
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	folderize = (value("outfolder")!=NOSTR && getfold(fldr) == 0);
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 	if (useauthor) {
397*7c478bd9Sstevel@tonic-gate 		if (folderize)
398*7c478bd9Sstevel@tonic-gate 			*recf++ = '+';
399*7c478bd9Sstevel@tonic-gate 		if (debug) fprintf(stderr, "buf='%s'\n", buf);
400*7c478bd9Sstevel@tonic-gate 		for (bp=skin(buf), cp=recf; *bp && !any(*bp, ", "); bp++) {
401*7c478bd9Sstevel@tonic-gate 			if (*bp=='!')
402*7c478bd9Sstevel@tonic-gate 				cp = recf;
403*7c478bd9Sstevel@tonic-gate 			else
404*7c478bd9Sstevel@tonic-gate 				*cp++ = *bp;
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 			if (cp >= &recfile[sz_recfile - 1]) {
407*7c478bd9Sstevel@tonic-gate 				printf(gettext("File name buffer overflow\n"));
408*7c478bd9Sstevel@tonic-gate 				break;
409*7c478bd9Sstevel@tonic-gate 			}
410*7c478bd9Sstevel@tonic-gate 		}
411*7c478bd9Sstevel@tonic-gate 		*cp = '\0';
412*7c478bd9Sstevel@tonic-gate 		if (cp==recf)
413*7c478bd9Sstevel@tonic-gate 			*recfile = '\0';
414*7c478bd9Sstevel@tonic-gate 		/* now strip off any Internet host names */
415*7c478bd9Sstevel@tonic-gate 		if ((cp = strchr(recf, '%')) == NOSTR)
416*7c478bd9Sstevel@tonic-gate 			cp = strchr(recf, '@');
417*7c478bd9Sstevel@tonic-gate 		if (cp != NOSTR)
418*7c478bd9Sstevel@tonic-gate 			*cp = '\0';
419*7c478bd9Sstevel@tonic-gate 	} else {
420*7c478bd9Sstevel@tonic-gate 		if (cp = value("record")) {
421*7c478bd9Sstevel@tonic-gate 			int sz = PATHSIZE;
422*7c478bd9Sstevel@tonic-gate 			if (folderize && *cp!='+' && *cp!='/'
423*7c478bd9Sstevel@tonic-gate 			 && *safeexpand(cp)!='/') {
424*7c478bd9Sstevel@tonic-gate 				*recf++ = '+';
425*7c478bd9Sstevel@tonic-gate 				sz--;
426*7c478bd9Sstevel@tonic-gate 			}
427*7c478bd9Sstevel@tonic-gate 			nstrcpy(recf, sz, cp);
428*7c478bd9Sstevel@tonic-gate 		} else
429*7c478bd9Sstevel@tonic-gate 			*recf = '\0';
430*7c478bd9Sstevel@tonic-gate 	}
431*7c478bd9Sstevel@tonic-gate 	if (debug) fprintf(stderr, "recfile='%s'\n", recfile);
432*7c478bd9Sstevel@tonic-gate }
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate /*
435*7c478bd9Sstevel@tonic-gate  * Modify the subject we are replying to to begin with Re: if
436*7c478bd9Sstevel@tonic-gate  * it does not already.
437*7c478bd9Sstevel@tonic-gate  */
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate static char *
440*7c478bd9Sstevel@tonic-gate reedit(char *subj)
441*7c478bd9Sstevel@tonic-gate {
442*7c478bd9Sstevel@tonic-gate 	char sbuf[10];
443*7c478bd9Sstevel@tonic-gate 	register char *newsubj;
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 	if (subj == NOSTR)
446*7c478bd9Sstevel@tonic-gate 		return(NOSTR);
447*7c478bd9Sstevel@tonic-gate 	strncpy(sbuf, subj, 3);
448*7c478bd9Sstevel@tonic-gate 	sbuf[3] = 0;
449*7c478bd9Sstevel@tonic-gate 	if (icequal(sbuf, "re:"))
450*7c478bd9Sstevel@tonic-gate 		return(subj);
451*7c478bd9Sstevel@tonic-gate 	newsubj = (char *)salloc((unsigned)(strlen(subj) + 5));
452*7c478bd9Sstevel@tonic-gate 	sprintf(newsubj, "Re: %s", subj);
453*7c478bd9Sstevel@tonic-gate 	return(newsubj);
454*7c478bd9Sstevel@tonic-gate }
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate /*
457*7c478bd9Sstevel@tonic-gate  * Preserve the named messages, so that they will be sent
458*7c478bd9Sstevel@tonic-gate  * back to the system mailbox.
459*7c478bd9Sstevel@tonic-gate  */
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate int
462*7c478bd9Sstevel@tonic-gate preserve(int *msgvec)
463*7c478bd9Sstevel@tonic-gate {
464*7c478bd9Sstevel@tonic-gate 	register struct message *mp;
465*7c478bd9Sstevel@tonic-gate 	register int *ip, mesg;
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	if (edit) {
468*7c478bd9Sstevel@tonic-gate 		printf(gettext("Cannot \"preserve\" in edit mode\n"));
469*7c478bd9Sstevel@tonic-gate 		return(1);
470*7c478bd9Sstevel@tonic-gate 	}
471*7c478bd9Sstevel@tonic-gate 	for (ip = msgvec; *ip != NULL; ip++) {
472*7c478bd9Sstevel@tonic-gate 		mesg = *ip;
473*7c478bd9Sstevel@tonic-gate 		mp = &message[mesg-1];
474*7c478bd9Sstevel@tonic-gate 		mp->m_flag |= MPRESERVE;
475*7c478bd9Sstevel@tonic-gate 		mp->m_flag &= ~MBOX;
476*7c478bd9Sstevel@tonic-gate 		dot = mp;
477*7c478bd9Sstevel@tonic-gate 	}
478*7c478bd9Sstevel@tonic-gate 	return(0);
479*7c478bd9Sstevel@tonic-gate }
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate /*
482*7c478bd9Sstevel@tonic-gate  * Mark all given messages as unread.
483*7c478bd9Sstevel@tonic-gate  */
484*7c478bd9Sstevel@tonic-gate int
485*7c478bd9Sstevel@tonic-gate unread(int msgvec[])
486*7c478bd9Sstevel@tonic-gate {
487*7c478bd9Sstevel@tonic-gate 	register int *ip;
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	for (ip = msgvec; *ip != NULL; ip++) {
490*7c478bd9Sstevel@tonic-gate 		dot = &message[*ip-1];
491*7c478bd9Sstevel@tonic-gate 		dot->m_flag &= ~(MREAD|MTOUCH);
492*7c478bd9Sstevel@tonic-gate 		dot->m_flag |= MSTATUS;
493*7c478bd9Sstevel@tonic-gate 	}
494*7c478bd9Sstevel@tonic-gate 	return(0);
495*7c478bd9Sstevel@tonic-gate }
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate /*
498*7c478bd9Sstevel@tonic-gate  * Print the size of each message.
499*7c478bd9Sstevel@tonic-gate  */
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate int
502*7c478bd9Sstevel@tonic-gate messize(int *msgvec)
503*7c478bd9Sstevel@tonic-gate {
504*7c478bd9Sstevel@tonic-gate 	register struct message *mp;
505*7c478bd9Sstevel@tonic-gate 	register int *ip, mesg;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	for (ip = msgvec; *ip != NULL; ip++) {
508*7c478bd9Sstevel@tonic-gate 		mesg = *ip;
509*7c478bd9Sstevel@tonic-gate 		mp = &message[mesg-1];
510*7c478bd9Sstevel@tonic-gate 		dot = mp;
511*7c478bd9Sstevel@tonic-gate 		printf("%d: %ld\n", mesg, mp->m_size);
512*7c478bd9Sstevel@tonic-gate 	}
513*7c478bd9Sstevel@tonic-gate 	return(0);
514*7c478bd9Sstevel@tonic-gate }
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate /*
517*7c478bd9Sstevel@tonic-gate  * Quit quickly.  If we are sourcing, just pop the input level
518*7c478bd9Sstevel@tonic-gate  * by returning an error.
519*7c478bd9Sstevel@tonic-gate  */
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate int
522*7c478bd9Sstevel@tonic-gate rexit(int e)
523*7c478bd9Sstevel@tonic-gate {
524*7c478bd9Sstevel@tonic-gate 	if (sourcing)
525*7c478bd9Sstevel@tonic-gate 		return(1);
526*7c478bd9Sstevel@tonic-gate 	if (Tflag != NOSTR)
527*7c478bd9Sstevel@tonic-gate 		close(creat(Tflag, TEMPPERM));
528*7c478bd9Sstevel@tonic-gate 	if (!edit)
529*7c478bd9Sstevel@tonic-gate 		Verhogen();
530*7c478bd9Sstevel@tonic-gate 	exit(e ? e : rpterr);
531*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
532*7c478bd9Sstevel@tonic-gate 	return (0);	/* shut up lint and CC */
533*7c478bd9Sstevel@tonic-gate }
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate /*
536*7c478bd9Sstevel@tonic-gate  * Set or display a variable value.  Syntax is similar to that
537*7c478bd9Sstevel@tonic-gate  * of csh.
538*7c478bd9Sstevel@tonic-gate  */
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate int
541*7c478bd9Sstevel@tonic-gate set(char **arglist)
542*7c478bd9Sstevel@tonic-gate {
543*7c478bd9Sstevel@tonic-gate 	register struct var *vp;
544*7c478bd9Sstevel@tonic-gate 	register char *cp, *cp2;
545*7c478bd9Sstevel@tonic-gate 	char varbuf[BUFSIZ], **ap, **p;
546*7c478bd9Sstevel@tonic-gate 	int errs, h, s;
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate 	if (argcount(arglist) == 0) {
549*7c478bd9Sstevel@tonic-gate 		for (h = 0, s = 1; h < HSHSIZE; h++)
550*7c478bd9Sstevel@tonic-gate 			for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
551*7c478bd9Sstevel@tonic-gate 				s++;
552*7c478bd9Sstevel@tonic-gate 		ap = (char **) salloc(s * sizeof *ap);
553*7c478bd9Sstevel@tonic-gate 		for (h = 0, p = ap; h < HSHSIZE; h++)
554*7c478bd9Sstevel@tonic-gate 			for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
555*7c478bd9Sstevel@tonic-gate 				*p++ = vp->v_name;
556*7c478bd9Sstevel@tonic-gate 		*p = NOSTR;
557*7c478bd9Sstevel@tonic-gate 		sort(ap);
558*7c478bd9Sstevel@tonic-gate 		for (p = ap; *p != NOSTR; p++)
559*7c478bd9Sstevel@tonic-gate 			if (((cp = value(*p)) != 0) && *cp)
560*7c478bd9Sstevel@tonic-gate 				printf("%s=\"%s\"\n", *p, cp);
561*7c478bd9Sstevel@tonic-gate 			else
562*7c478bd9Sstevel@tonic-gate 				printf("%s\n", *p);
563*7c478bd9Sstevel@tonic-gate 		return(0);
564*7c478bd9Sstevel@tonic-gate 	}
565*7c478bd9Sstevel@tonic-gate 	errs = 0;
566*7c478bd9Sstevel@tonic-gate 	for (ap = arglist; *ap != NOSTR; ap++) {
567*7c478bd9Sstevel@tonic-gate 		cp = *ap;
568*7c478bd9Sstevel@tonic-gate 		cp2 = varbuf;
569*7c478bd9Sstevel@tonic-gate 		while (*cp != '=' && *cp != '\0')
570*7c478bd9Sstevel@tonic-gate 			*cp2++ = *cp++;
571*7c478bd9Sstevel@tonic-gate 		*cp2 = '\0';
572*7c478bd9Sstevel@tonic-gate 		if (*cp == '\0')
573*7c478bd9Sstevel@tonic-gate 			cp = "";
574*7c478bd9Sstevel@tonic-gate 		else
575*7c478bd9Sstevel@tonic-gate 			cp++;
576*7c478bd9Sstevel@tonic-gate 		if (equal(varbuf, "")) {
577*7c478bd9Sstevel@tonic-gate 			printf(gettext("Non-null variable name required\n"));
578*7c478bd9Sstevel@tonic-gate 			errs++;
579*7c478bd9Sstevel@tonic-gate 			continue;
580*7c478bd9Sstevel@tonic-gate 		}
581*7c478bd9Sstevel@tonic-gate 		assign(varbuf, cp);
582*7c478bd9Sstevel@tonic-gate 	}
583*7c478bd9Sstevel@tonic-gate 	return(errs);
584*7c478bd9Sstevel@tonic-gate }
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate /*
587*7c478bd9Sstevel@tonic-gate  * Unset a bunch of variable values.
588*7c478bd9Sstevel@tonic-gate  */
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate int
591*7c478bd9Sstevel@tonic-gate unset(char **arglist)
592*7c478bd9Sstevel@tonic-gate {
593*7c478bd9Sstevel@tonic-gate 	register int errs;
594*7c478bd9Sstevel@tonic-gate 	register char **ap;
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 	errs = 0;
597*7c478bd9Sstevel@tonic-gate 	for (ap = arglist; *ap != NOSTR; ap++)
598*7c478bd9Sstevel@tonic-gate 		errs += deassign(*ap);
599*7c478bd9Sstevel@tonic-gate 	return(errs);
600*7c478bd9Sstevel@tonic-gate }
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate /*
603*7c478bd9Sstevel@tonic-gate  * Add users to a group.
604*7c478bd9Sstevel@tonic-gate  */
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate int
607*7c478bd9Sstevel@tonic-gate group(char **argv)
608*7c478bd9Sstevel@tonic-gate {
609*7c478bd9Sstevel@tonic-gate 	register struct grouphead *gh;
610*7c478bd9Sstevel@tonic-gate 	register struct mgroup *gp;
611*7c478bd9Sstevel@tonic-gate 	register int h;
612*7c478bd9Sstevel@tonic-gate 	int s;
613*7c478bd9Sstevel@tonic-gate 	char **ap, *gname, **p;
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 	if (argcount(argv) == 0) {
616*7c478bd9Sstevel@tonic-gate 		for (h = 0, s = 1; h < HSHSIZE; h++)
617*7c478bd9Sstevel@tonic-gate 			for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
618*7c478bd9Sstevel@tonic-gate 				s++;
619*7c478bd9Sstevel@tonic-gate 		ap = (char **) salloc(s * sizeof *ap);
620*7c478bd9Sstevel@tonic-gate 		for (h = 0, p = ap; h < HSHSIZE; h++)
621*7c478bd9Sstevel@tonic-gate 			for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
622*7c478bd9Sstevel@tonic-gate 				*p++ = gh->g_name;
623*7c478bd9Sstevel@tonic-gate 		*p = NOSTR;
624*7c478bd9Sstevel@tonic-gate 		sort(ap);
625*7c478bd9Sstevel@tonic-gate 		for (p = ap; *p != NOSTR; p++)
626*7c478bd9Sstevel@tonic-gate 			printgroup(*p);
627*7c478bd9Sstevel@tonic-gate 		return(0);
628*7c478bd9Sstevel@tonic-gate 	}
629*7c478bd9Sstevel@tonic-gate 	if (argcount(argv) == 1) {
630*7c478bd9Sstevel@tonic-gate 		printgroup(*argv);
631*7c478bd9Sstevel@tonic-gate 		return(0);
632*7c478bd9Sstevel@tonic-gate 	}
633*7c478bd9Sstevel@tonic-gate 	gname = *argv;
634*7c478bd9Sstevel@tonic-gate 	h = hash(gname);
635*7c478bd9Sstevel@tonic-gate 	if ((gh = findgroup(gname)) == NOGRP) {
636*7c478bd9Sstevel@tonic-gate 		if ((gh = (struct grouphead *)
637*7c478bd9Sstevel@tonic-gate 		    calloc(sizeof (*gh), 1)) == NULL) {
638*7c478bd9Sstevel@tonic-gate 			panic("Failed to allocate memory for group");
639*7c478bd9Sstevel@tonic-gate 	}
640*7c478bd9Sstevel@tonic-gate 		gh->g_name = vcopy(gname);
641*7c478bd9Sstevel@tonic-gate 		gh->g_list = NOGE;
642*7c478bd9Sstevel@tonic-gate 		gh->g_link = groups[h];
643*7c478bd9Sstevel@tonic-gate 		groups[h] = gh;
644*7c478bd9Sstevel@tonic-gate 	}
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 	/*
647*7c478bd9Sstevel@tonic-gate 	 * Insert names from the command list into the group.
648*7c478bd9Sstevel@tonic-gate 	 * Who cares if there are duplicates?  They get tossed
649*7c478bd9Sstevel@tonic-gate 	 * later anyway.
650*7c478bd9Sstevel@tonic-gate 	 */
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	for (ap = argv+1; *ap != NOSTR; ap++) {
653*7c478bd9Sstevel@tonic-gate 		if ((gp = (struct mgroup *)
654*7c478bd9Sstevel@tonic-gate 		    calloc(sizeof (*gp), 1)) == NULL) {
655*7c478bd9Sstevel@tonic-gate 			panic("Failed to allocate memory for group");
656*7c478bd9Sstevel@tonic-gate 	}
657*7c478bd9Sstevel@tonic-gate 	gp->ge_name = vcopy(*ap);
658*7c478bd9Sstevel@tonic-gate 		gp->ge_link = gh->g_list;
659*7c478bd9Sstevel@tonic-gate 		gh->g_list = gp;
660*7c478bd9Sstevel@tonic-gate 	}
661*7c478bd9Sstevel@tonic-gate 	return(0);
662*7c478bd9Sstevel@tonic-gate }
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate /*
665*7c478bd9Sstevel@tonic-gate  * Remove users from a group.
666*7c478bd9Sstevel@tonic-gate  */
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate int
669*7c478bd9Sstevel@tonic-gate ungroup(char **argv)
670*7c478bd9Sstevel@tonic-gate {
671*7c478bd9Sstevel@tonic-gate 	register struct grouphead *gh, **ghp;
672*7c478bd9Sstevel@tonic-gate 	register struct mgroup *gp, *gpnext;
673*7c478bd9Sstevel@tonic-gate 	register int h;
674*7c478bd9Sstevel@tonic-gate 	char **ap, *gname;
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 	if (argcount(argv) == 0) {
677*7c478bd9Sstevel@tonic-gate 		printf("Must specify alias or group to remove\n");
678*7c478bd9Sstevel@tonic-gate 		return(1);
679*7c478bd9Sstevel@tonic-gate 	}
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate 	/*
682*7c478bd9Sstevel@tonic-gate 	 * Remove names on the command list from the group list.
683*7c478bd9Sstevel@tonic-gate 	 */
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 	for (ap = argv; *ap != NOSTR; ap++) {
686*7c478bd9Sstevel@tonic-gate 		gname = *ap;
687*7c478bd9Sstevel@tonic-gate 		h = hash(gname);
688*7c478bd9Sstevel@tonic-gate 		for (ghp = &groups[h]; *ghp != NOGRP; ghp = &((*ghp)->g_link)) {
689*7c478bd9Sstevel@tonic-gate 			gh = *ghp;
690*7c478bd9Sstevel@tonic-gate 			if (equal(gh->g_name, gname)) {
691*7c478bd9Sstevel@tonic-gate 				/* remove from list */
692*7c478bd9Sstevel@tonic-gate 				*ghp = gh->g_link;
693*7c478bd9Sstevel@tonic-gate 				/* free each member of gorup */
694*7c478bd9Sstevel@tonic-gate 				for (gp = gh->g_list; gp != NOGE; gp = gpnext) {
695*7c478bd9Sstevel@tonic-gate 					gpnext = gp->ge_link;
696*7c478bd9Sstevel@tonic-gate 					vfree(gp->ge_name);
697*7c478bd9Sstevel@tonic-gate 					free(gp);
698*7c478bd9Sstevel@tonic-gate 				}
699*7c478bd9Sstevel@tonic-gate 				vfree(gh->g_name);
700*7c478bd9Sstevel@tonic-gate 				free(gh);
701*7c478bd9Sstevel@tonic-gate 				break;
702*7c478bd9Sstevel@tonic-gate 			}
703*7c478bd9Sstevel@tonic-gate 		}
704*7c478bd9Sstevel@tonic-gate 	}
705*7c478bd9Sstevel@tonic-gate 	return(0);
706*7c478bd9Sstevel@tonic-gate }
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate /*
709*7c478bd9Sstevel@tonic-gate  * Sort the passed string vecotor into ascending dictionary
710*7c478bd9Sstevel@tonic-gate  * order.
711*7c478bd9Sstevel@tonic-gate  */
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate static void
714*7c478bd9Sstevel@tonic-gate sort(char **list)
715*7c478bd9Sstevel@tonic-gate {
716*7c478bd9Sstevel@tonic-gate 	register char **ap;
717*7c478bd9Sstevel@tonic-gate 
718*7c478bd9Sstevel@tonic-gate 	for (ap = list; *ap != NOSTR; ap++)
719*7c478bd9Sstevel@tonic-gate 		;
720*7c478bd9Sstevel@tonic-gate 	if (ap-list < 2)
721*7c478bd9Sstevel@tonic-gate 		return;
722*7c478bd9Sstevel@tonic-gate 	qsort((char *) list, (unsigned) (ap-list), sizeof *list, diction);
723*7c478bd9Sstevel@tonic-gate }
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate /*
726*7c478bd9Sstevel@tonic-gate  * Do a dictionary order comparison of the arguments from
727*7c478bd9Sstevel@tonic-gate  * qsort.
728*7c478bd9Sstevel@tonic-gate  */
729*7c478bd9Sstevel@tonic-gate static int
730*7c478bd9Sstevel@tonic-gate diction(const void *a, const void *b)
731*7c478bd9Sstevel@tonic-gate {
732*7c478bd9Sstevel@tonic-gate 	return(strcmp(*(char **)a, *(char **)b));
733*7c478bd9Sstevel@tonic-gate }
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate /*
736*7c478bd9Sstevel@tonic-gate  * The do nothing command for comments.
737*7c478bd9Sstevel@tonic-gate  */
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate int
740*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
741*7c478bd9Sstevel@tonic-gate null(char *)
742*7c478bd9Sstevel@tonic-gate #else
743*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
744*7c478bd9Sstevel@tonic-gate null(char *s)
745*7c478bd9Sstevel@tonic-gate #endif
746*7c478bd9Sstevel@tonic-gate {
747*7c478bd9Sstevel@tonic-gate 	return(0);
748*7c478bd9Sstevel@tonic-gate }
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate /*
751*7c478bd9Sstevel@tonic-gate  * Print out the current edit file, if we are editing.
752*7c478bd9Sstevel@tonic-gate  * Otherwise, print the name of the person who's mail
753*7c478bd9Sstevel@tonic-gate  * we are reading.
754*7c478bd9Sstevel@tonic-gate  */
755*7c478bd9Sstevel@tonic-gate int
756*7c478bd9Sstevel@tonic-gate file(char **argv)
757*7c478bd9Sstevel@tonic-gate {
758*7c478bd9Sstevel@tonic-gate 	register char *cp;
759*7c478bd9Sstevel@tonic-gate 	int editing, mdot;
760*7c478bd9Sstevel@tonic-gate 
761*7c478bd9Sstevel@tonic-gate 	if (argv[0] == NOSTR) {
762*7c478bd9Sstevel@tonic-gate 		mdot = newfileinfo(1);
763*7c478bd9Sstevel@tonic-gate 		dot = &message[mdot - 1];
764*7c478bd9Sstevel@tonic-gate 		return(0);
765*7c478bd9Sstevel@tonic-gate 	}
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate 	/*
768*7c478bd9Sstevel@tonic-gate 	 * Acker's!  Must switch to the new file.
769*7c478bd9Sstevel@tonic-gate 	 * We use a funny interpretation --
770*7c478bd9Sstevel@tonic-gate 	 *	# -- gets the previous file
771*7c478bd9Sstevel@tonic-gate 	 *	% -- gets the invoker's post office box
772*7c478bd9Sstevel@tonic-gate 	 *	%user -- gets someone else's post office box
773*7c478bd9Sstevel@tonic-gate 	 *	& -- gets invoker's mbox file
774*7c478bd9Sstevel@tonic-gate 	 *	string -- reads the given file
775*7c478bd9Sstevel@tonic-gate 	 */
776*7c478bd9Sstevel@tonic-gate 
777*7c478bd9Sstevel@tonic-gate 	cp = getfilename(argv[0], &editing);
778*7c478bd9Sstevel@tonic-gate 	if (cp == NOSTR)
779*7c478bd9Sstevel@tonic-gate 		return(-1);
780*7c478bd9Sstevel@tonic-gate 	if (setfile(cp, editing)) {
781*7c478bd9Sstevel@tonic-gate 		nstrcpy(origname, PATHSIZE, origprevfile);
782*7c478bd9Sstevel@tonic-gate 		return(-1);
783*7c478bd9Sstevel@tonic-gate 	}
784*7c478bd9Sstevel@tonic-gate 	mdot = newfileinfo(1);
785*7c478bd9Sstevel@tonic-gate 	dot = &message[mdot - 1];
786*7c478bd9Sstevel@tonic-gate 	return(0);
787*7c478bd9Sstevel@tonic-gate }
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate /*
790*7c478bd9Sstevel@tonic-gate  * Evaluate the string given as a new mailbox name.
791*7c478bd9Sstevel@tonic-gate  * Ultimately, we want this to support a number of meta characters.
792*7c478bd9Sstevel@tonic-gate  * Possibly:
793*7c478bd9Sstevel@tonic-gate  *	% -- for my system mail box
794*7c478bd9Sstevel@tonic-gate  *	%user -- for user's system mail box
795*7c478bd9Sstevel@tonic-gate  *	# -- for previous file
796*7c478bd9Sstevel@tonic-gate  *	& -- get's invoker's mbox file
797*7c478bd9Sstevel@tonic-gate  *	file name -- for any other file
798*7c478bd9Sstevel@tonic-gate  */
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate static char *
801*7c478bd9Sstevel@tonic-gate getfilename(char *name, int *aedit)
802*7c478bd9Sstevel@tonic-gate {
803*7c478bd9Sstevel@tonic-gate 	register char *cp;
804*7c478bd9Sstevel@tonic-gate 	char savename[BUFSIZ];
805*7c478bd9Sstevel@tonic-gate 	char oldmailname[BUFSIZ];
806*7c478bd9Sstevel@tonic-gate 	char tmp[BUFSIZ];
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 	/*
809*7c478bd9Sstevel@tonic-gate 	 * Assume we will be in "edit file" mode, until
810*7c478bd9Sstevel@tonic-gate 	 * proven wrong.
811*7c478bd9Sstevel@tonic-gate 	 */
812*7c478bd9Sstevel@tonic-gate 	*aedit = 1;
813*7c478bd9Sstevel@tonic-gate 	switch (*name) {
814*7c478bd9Sstevel@tonic-gate 	case '%':
815*7c478bd9Sstevel@tonic-gate 		*aedit = 0;
816*7c478bd9Sstevel@tonic-gate 		nstrcpy(prevfile, sizeof (prevfile), editfile);
817*7c478bd9Sstevel@tonic-gate 		nstrcpy(origprevfile, sizeof (origprevfile), origname);
818*7c478bd9Sstevel@tonic-gate 		if (name[1] != 0) {
819*7c478bd9Sstevel@tonic-gate 			nstrcpy(oldmailname, sizeof (oldmailname), mailname);
820*7c478bd9Sstevel@tonic-gate 			findmail(name+1);
821*7c478bd9Sstevel@tonic-gate 			cp = savestr(mailname);
822*7c478bd9Sstevel@tonic-gate 			nstrcpy(origname, PATHSIZE, cp);
823*7c478bd9Sstevel@tonic-gate 			nstrcpy(mailname, PATHSIZE, oldmailname);
824*7c478bd9Sstevel@tonic-gate 			return(cp);
825*7c478bd9Sstevel@tonic-gate 		}
826*7c478bd9Sstevel@tonic-gate 		nstrcpy(oldmailname, sizeof (oldmailname), mailname);
827*7c478bd9Sstevel@tonic-gate 		findmail(NULL);
828*7c478bd9Sstevel@tonic-gate 		cp = savestr(mailname);
829*7c478bd9Sstevel@tonic-gate 		nstrcpy(mailname, PATHSIZE, oldmailname);
830*7c478bd9Sstevel@tonic-gate 		nstrcpy(origname, PATHSIZE, cp);
831*7c478bd9Sstevel@tonic-gate 		return(cp);
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate 	case '#':
834*7c478bd9Sstevel@tonic-gate 		if (name[1] != 0)
835*7c478bd9Sstevel@tonic-gate 			goto regular;
836*7c478bd9Sstevel@tonic-gate 		if (prevfile[0] == 0) {
837*7c478bd9Sstevel@tonic-gate 			printf(gettext("No previous file\n"));
838*7c478bd9Sstevel@tonic-gate 			return(NOSTR);
839*7c478bd9Sstevel@tonic-gate 		}
840*7c478bd9Sstevel@tonic-gate 		cp = savestr(prevfile);
841*7c478bd9Sstevel@tonic-gate 		nstrcpy(prevfile, sizeof (prevfile), editfile);
842*7c478bd9Sstevel@tonic-gate 		nstrcpy(tmp, sizeof (tmp), origname);
843*7c478bd9Sstevel@tonic-gate 		nstrcpy(origname, PATHSIZE, origprevfile);
844*7c478bd9Sstevel@tonic-gate 		nstrcpy(origprevfile, sizeof (origprevfile), tmp);
845*7c478bd9Sstevel@tonic-gate 		return(cp);
846*7c478bd9Sstevel@tonic-gate 
847*7c478bd9Sstevel@tonic-gate 	case '&':
848*7c478bd9Sstevel@tonic-gate 		nstrcpy(prevfile, sizeof (prevfile), editfile);
849*7c478bd9Sstevel@tonic-gate 		nstrcpy(origprevfile, sizeof (origprevfile), origname);
850*7c478bd9Sstevel@tonic-gate 		if (name[1] == 0) {
851*7c478bd9Sstevel@tonic-gate 			cp=Getf("MBOX");
852*7c478bd9Sstevel@tonic-gate 			nstrcpy(origname, PATHSIZE, cp);
853*7c478bd9Sstevel@tonic-gate 			return(cp);
854*7c478bd9Sstevel@tonic-gate 		}
855*7c478bd9Sstevel@tonic-gate 		/* Fall into . . . */
856*7c478bd9Sstevel@tonic-gate 
857*7c478bd9Sstevel@tonic-gate 	default:
858*7c478bd9Sstevel@tonic-gate regular:
859*7c478bd9Sstevel@tonic-gate 		nstrcpy(prevfile, sizeof (prevfile), editfile);
860*7c478bd9Sstevel@tonic-gate 		nstrcpy(origprevfile, sizeof (origprevfile), origname);
861*7c478bd9Sstevel@tonic-gate 		cp = safeexpand(name);
862*7c478bd9Sstevel@tonic-gate 		nstrcpy(origname, PATHSIZE, cp);
863*7c478bd9Sstevel@tonic-gate 		if (cp[0] != '/') {
864*7c478bd9Sstevel@tonic-gate 			name = getcwd(NOSTR, PATHSIZE);
865*7c478bd9Sstevel@tonic-gate 			nstrcat(name, PATHSIZE, "/");
866*7c478bd9Sstevel@tonic-gate 			nstrcat(name, PATHSIZE, cp);
867*7c478bd9Sstevel@tonic-gate 			cp = name;
868*7c478bd9Sstevel@tonic-gate 		}
869*7c478bd9Sstevel@tonic-gate 		return(cp);
870*7c478bd9Sstevel@tonic-gate 	}
871*7c478bd9Sstevel@tonic-gate }
872*7c478bd9Sstevel@tonic-gate 
873*7c478bd9Sstevel@tonic-gate /*
874*7c478bd9Sstevel@tonic-gate  * Expand file names like echo
875*7c478bd9Sstevel@tonic-gate  */
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate int
878*7c478bd9Sstevel@tonic-gate echo(register char **argv)
879*7c478bd9Sstevel@tonic-gate {
880*7c478bd9Sstevel@tonic-gate 	register char *cp;
881*7c478bd9Sstevel@tonic-gate 	int neednl = 0;
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 	while (*argv != NOSTR) {
884*7c478bd9Sstevel@tonic-gate 		cp = *argv++;
885*7c478bd9Sstevel@tonic-gate 		if ((cp = expand(cp)) != NOSTR) {
886*7c478bd9Sstevel@tonic-gate 			neednl++;
887*7c478bd9Sstevel@tonic-gate 			printf("%s", cp);
888*7c478bd9Sstevel@tonic-gate 			if (*argv!=NOSTR)
889*7c478bd9Sstevel@tonic-gate 				putchar(' ');
890*7c478bd9Sstevel@tonic-gate 		}
891*7c478bd9Sstevel@tonic-gate 	}
892*7c478bd9Sstevel@tonic-gate 	if (neednl)
893*7c478bd9Sstevel@tonic-gate 		putchar('\n');
894*7c478bd9Sstevel@tonic-gate 	return(0);
895*7c478bd9Sstevel@tonic-gate }
896*7c478bd9Sstevel@tonic-gate 
897*7c478bd9Sstevel@tonic-gate /*
898*7c478bd9Sstevel@tonic-gate  * Reply to a series of messages by simply mailing to the senders
899*7c478bd9Sstevel@tonic-gate  * and not messing around with the To: and Cc: lists as in normal
900*7c478bd9Sstevel@tonic-gate  * reply.
901*7c478bd9Sstevel@tonic-gate  */
902*7c478bd9Sstevel@tonic-gate 
903*7c478bd9Sstevel@tonic-gate int
904*7c478bd9Sstevel@tonic-gate Respond(int *msgvec)
905*7c478bd9Sstevel@tonic-gate {
906*7c478bd9Sstevel@tonic-gate 	if (reply2sender())
907*7c478bd9Sstevel@tonic-gate 		return(Resp1(msgvec, 0));
908*7c478bd9Sstevel@tonic-gate 	else
909*7c478bd9Sstevel@tonic-gate 		return(resp1(msgvec, 0));
910*7c478bd9Sstevel@tonic-gate }
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate int
913*7c478bd9Sstevel@tonic-gate Followup(int *msgvec)
914*7c478bd9Sstevel@tonic-gate {
915*7c478bd9Sstevel@tonic-gate 	if (reply2sender())
916*7c478bd9Sstevel@tonic-gate 		return(Resp1(msgvec, 1));
917*7c478bd9Sstevel@tonic-gate 	else
918*7c478bd9Sstevel@tonic-gate 		return(resp1(msgvec, 1));
919*7c478bd9Sstevel@tonic-gate }
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate int
922*7c478bd9Sstevel@tonic-gate replysender(int *msgvec)
923*7c478bd9Sstevel@tonic-gate {
924*7c478bd9Sstevel@tonic-gate 	return(Resp1(msgvec, 0));
925*7c478bd9Sstevel@tonic-gate }
926*7c478bd9Sstevel@tonic-gate 
927*7c478bd9Sstevel@tonic-gate static int
928*7c478bd9Sstevel@tonic-gate Resp1(int *msgvec, int useauthor)
929*7c478bd9Sstevel@tonic-gate {
930*7c478bd9Sstevel@tonic-gate 	struct header head;
931*7c478bd9Sstevel@tonic-gate 	struct message *mp;
932*7c478bd9Sstevel@tonic-gate 	register int s, *ap;
933*7c478bd9Sstevel@tonic-gate 	register char *cp, *cp2, *subject;
934*7c478bd9Sstevel@tonic-gate 
935*7c478bd9Sstevel@tonic-gate 	for (s = 0, ap = msgvec; *ap != 0; ap++) {
936*7c478bd9Sstevel@tonic-gate 		mp = &message[*ap - 1];
937*7c478bd9Sstevel@tonic-gate 		dot = mp;
938*7c478bd9Sstevel@tonic-gate 		cp = replyto(mp, NOSTRPTR);
939*7c478bd9Sstevel@tonic-gate 		s += strlen(cp) + 1;
940*7c478bd9Sstevel@tonic-gate 	}
941*7c478bd9Sstevel@tonic-gate 	if (s == 0)
942*7c478bd9Sstevel@tonic-gate 		return(0);
943*7c478bd9Sstevel@tonic-gate 	cp = (char *)salloc(s + 2);
944*7c478bd9Sstevel@tonic-gate 	head.h_to = cp;
945*7c478bd9Sstevel@tonic-gate 	for (ap = msgvec; *ap != 0; ap++) {
946*7c478bd9Sstevel@tonic-gate 		mp = &message[*ap - 1];
947*7c478bd9Sstevel@tonic-gate 		cp2 = replyto(mp, NOSTRPTR);
948*7c478bd9Sstevel@tonic-gate 		cp = copy(cp2, cp);
949*7c478bd9Sstevel@tonic-gate 		*cp++ = ' ';
950*7c478bd9Sstevel@tonic-gate 	}
951*7c478bd9Sstevel@tonic-gate 	*--cp = 0;
952*7c478bd9Sstevel@tonic-gate 	mp = &message[msgvec[0] - 1];
953*7c478bd9Sstevel@tonic-gate 	subject = hfield("subject", mp, addone);
954*7c478bd9Sstevel@tonic-gate 	head.h_seq = 1;
955*7c478bd9Sstevel@tonic-gate 	if (subject == NOSTR)
956*7c478bd9Sstevel@tonic-gate 		subject = hfield("subj", mp, addone);
957*7c478bd9Sstevel@tonic-gate 	head.h_subject = reedit(subject);
958*7c478bd9Sstevel@tonic-gate 	if (subject != NOSTR)
959*7c478bd9Sstevel@tonic-gate 		head.h_seq++;
960*7c478bd9Sstevel@tonic-gate 	head.h_cc = NOSTR;
961*7c478bd9Sstevel@tonic-gate 	head.h_bcc = NOSTR;
962*7c478bd9Sstevel@tonic-gate 	head.h_defopt = NOSTR;
963*7c478bd9Sstevel@tonic-gate 	head.h_others = NOSTRPTR;
964*7c478bd9Sstevel@tonic-gate 	mail1(&head, useauthor, NOSTR);
965*7c478bd9Sstevel@tonic-gate 	return(0);
966*7c478bd9Sstevel@tonic-gate }
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate /*
969*7c478bd9Sstevel@tonic-gate  * Conditional commands.  These allow one to parameterize one's
970*7c478bd9Sstevel@tonic-gate  * .mailrc and do some things if sending, others if receiving.
971*7c478bd9Sstevel@tonic-gate  */
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate int
974*7c478bd9Sstevel@tonic-gate ifcmd(char **argv)
975*7c478bd9Sstevel@tonic-gate {
976*7c478bd9Sstevel@tonic-gate 	register char *cp;
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 	if (cond != CANY) {
979*7c478bd9Sstevel@tonic-gate 		printf(gettext("Illegal nested \"if\"\n"));
980*7c478bd9Sstevel@tonic-gate 		return(1);
981*7c478bd9Sstevel@tonic-gate 	}
982*7c478bd9Sstevel@tonic-gate 	cond = CANY;
983*7c478bd9Sstevel@tonic-gate 	cp = argv[0];
984*7c478bd9Sstevel@tonic-gate 	switch (*cp) {
985*7c478bd9Sstevel@tonic-gate 	case 'r': case 'R':
986*7c478bd9Sstevel@tonic-gate 		cond = CRCV;
987*7c478bd9Sstevel@tonic-gate 		break;
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate 	case 's': case 'S':
990*7c478bd9Sstevel@tonic-gate 		cond = CSEND;
991*7c478bd9Sstevel@tonic-gate 		break;
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate 	case 't': case 'T':
994*7c478bd9Sstevel@tonic-gate 		cond = CTTY;
995*7c478bd9Sstevel@tonic-gate 		break;
996*7c478bd9Sstevel@tonic-gate 
997*7c478bd9Sstevel@tonic-gate 	default:
998*7c478bd9Sstevel@tonic-gate 		printf(gettext("Unrecognized if-keyword: \"%s\"\n"), cp);
999*7c478bd9Sstevel@tonic-gate 		return(1);
1000*7c478bd9Sstevel@tonic-gate 	}
1001*7c478bd9Sstevel@tonic-gate 	return(0);
1002*7c478bd9Sstevel@tonic-gate }
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate /*
1005*7c478bd9Sstevel@tonic-gate  * Implement 'else'.  This is pretty simple -- we just
1006*7c478bd9Sstevel@tonic-gate  * flip over the conditional flag.
1007*7c478bd9Sstevel@tonic-gate  */
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate int
1010*7c478bd9Sstevel@tonic-gate elsecmd(void)
1011*7c478bd9Sstevel@tonic-gate {
1012*7c478bd9Sstevel@tonic-gate 
1013*7c478bd9Sstevel@tonic-gate 	switch (cond) {
1014*7c478bd9Sstevel@tonic-gate 	case CANY:
1015*7c478bd9Sstevel@tonic-gate 		printf(gettext("\"Else\" without matching \"if\"\n"));
1016*7c478bd9Sstevel@tonic-gate 		return(1);
1017*7c478bd9Sstevel@tonic-gate 
1018*7c478bd9Sstevel@tonic-gate 	case CSEND:
1019*7c478bd9Sstevel@tonic-gate 		cond = CRCV;
1020*7c478bd9Sstevel@tonic-gate 		break;
1021*7c478bd9Sstevel@tonic-gate 
1022*7c478bd9Sstevel@tonic-gate 	case CRCV:
1023*7c478bd9Sstevel@tonic-gate 		cond = CSEND;
1024*7c478bd9Sstevel@tonic-gate 		break;
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate 	case CTTY:
1027*7c478bd9Sstevel@tonic-gate 		cond = CNOTTY;
1028*7c478bd9Sstevel@tonic-gate 		break;
1029*7c478bd9Sstevel@tonic-gate 
1030*7c478bd9Sstevel@tonic-gate 	case CNOTTY:
1031*7c478bd9Sstevel@tonic-gate 		cond = CTTY;
1032*7c478bd9Sstevel@tonic-gate 		break;
1033*7c478bd9Sstevel@tonic-gate 
1034*7c478bd9Sstevel@tonic-gate 	default:
1035*7c478bd9Sstevel@tonic-gate 		printf(gettext("invalid condition encountered\n"));
1036*7c478bd9Sstevel@tonic-gate 		cond = CANY;
1037*7c478bd9Sstevel@tonic-gate 		break;
1038*7c478bd9Sstevel@tonic-gate 	}
1039*7c478bd9Sstevel@tonic-gate 	return(0);
1040*7c478bd9Sstevel@tonic-gate }
1041*7c478bd9Sstevel@tonic-gate 
1042*7c478bd9Sstevel@tonic-gate /*
1043*7c478bd9Sstevel@tonic-gate  * End of if statement.  Just set cond back to anything.
1044*7c478bd9Sstevel@tonic-gate  */
1045*7c478bd9Sstevel@tonic-gate 
1046*7c478bd9Sstevel@tonic-gate int
1047*7c478bd9Sstevel@tonic-gate endifcmd(void)
1048*7c478bd9Sstevel@tonic-gate {
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate 	if (cond == CANY) {
1051*7c478bd9Sstevel@tonic-gate 		printf(gettext("\"Endif\" without matching \"if\"\n"));
1052*7c478bd9Sstevel@tonic-gate 		return(1);
1053*7c478bd9Sstevel@tonic-gate 	}
1054*7c478bd9Sstevel@tonic-gate 	cond = CANY;
1055*7c478bd9Sstevel@tonic-gate 	return(0);
1056*7c478bd9Sstevel@tonic-gate }
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate /*
1059*7c478bd9Sstevel@tonic-gate  * Set the list of alternate names.
1060*7c478bd9Sstevel@tonic-gate  */
1061*7c478bd9Sstevel@tonic-gate int
1062*7c478bd9Sstevel@tonic-gate alternates(char **namelist)
1063*7c478bd9Sstevel@tonic-gate {
1064*7c478bd9Sstevel@tonic-gate 	register int c;
1065*7c478bd9Sstevel@tonic-gate 	register char **ap, **ap2, *cp;
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate 	c = argcount(namelist) + 1;
1068*7c478bd9Sstevel@tonic-gate 	if (c == 1) {
1069*7c478bd9Sstevel@tonic-gate 		if (altnames == 0)
1070*7c478bd9Sstevel@tonic-gate 			return(0);
1071*7c478bd9Sstevel@tonic-gate 		for (ap = altnames; *ap; ap++)
1072*7c478bd9Sstevel@tonic-gate 			printf("%s ", *ap);
1073*7c478bd9Sstevel@tonic-gate 		printf("\n");
1074*7c478bd9Sstevel@tonic-gate 		return (0);
1075*7c478bd9Sstevel@tonic-gate 	}
1076*7c478bd9Sstevel@tonic-gate 	if (altnames != 0)
1077*7c478bd9Sstevel@tonic-gate 		free((char *)altnames);
1078*7c478bd9Sstevel@tonic-gate 	if ((altnames = (char **)
1079*7c478bd9Sstevel@tonic-gate 	    calloc((unsigned)c, sizeof (char *))) == NULL)
1080*7c478bd9Sstevel@tonic-gate 		panic("Failed to allocate memory");
1081*7c478bd9Sstevel@tonic-gate 	for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) {
1082*7c478bd9Sstevel@tonic-gate 		if ((cp = (char *)
1083*7c478bd9Sstevel@tonic-gate 		    calloc((unsigned)strlen(*ap) + 1, sizeof (char))) == NULL)
1084*7c478bd9Sstevel@tonic-gate 			panic("Failed to allocate memory");
1085*7c478bd9Sstevel@tonic-gate 		strcpy(cp, *ap);
1086*7c478bd9Sstevel@tonic-gate 		*ap2 = cp;
1087*7c478bd9Sstevel@tonic-gate 	}
1088*7c478bd9Sstevel@tonic-gate 	*ap2 = 0;
1089*7c478bd9Sstevel@tonic-gate 	return(0);
1090*7c478bd9Sstevel@tonic-gate }
1091*7c478bd9Sstevel@tonic-gate 
1092*7c478bd9Sstevel@tonic-gate /*
1093*7c478bd9Sstevel@tonic-gate  * Figure out who to reply to.
1094*7c478bd9Sstevel@tonic-gate  * Return the real sender in *f.
1095*7c478bd9Sstevel@tonic-gate  */
1096*7c478bd9Sstevel@tonic-gate static char *
1097*7c478bd9Sstevel@tonic-gate replyto(struct message *mp, char **f)
1098*7c478bd9Sstevel@tonic-gate {
1099*7c478bd9Sstevel@tonic-gate 	char *r, *rf;
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate 	if ((rf = skin(hfield("from", mp, addto)))==NOSTR)
1102*7c478bd9Sstevel@tonic-gate 		rf = skin(addto(NOSTR, nameof(mp)));
1103*7c478bd9Sstevel@tonic-gate 	if ((r = skin(hfield("reply-to", mp, addto)))==NOSTR)
1104*7c478bd9Sstevel@tonic-gate 		r = rf;
1105*7c478bd9Sstevel@tonic-gate 	if (f)
1106*7c478bd9Sstevel@tonic-gate 		*f = rf;
1107*7c478bd9Sstevel@tonic-gate 	return (r);
1108*7c478bd9Sstevel@tonic-gate }
1109*7c478bd9Sstevel@tonic-gate 
1110*7c478bd9Sstevel@tonic-gate /*
1111*7c478bd9Sstevel@tonic-gate  * reply2sender - determine whether a "reply" command should reply to the
1112*7c478bd9Sstevel@tonic-gate  *                sender of the messages, or to all the recipients of the
1113*7c478bd9Sstevel@tonic-gate  *                message.
1114*7c478bd9Sstevel@tonic-gate  *
1115*7c478bd9Sstevel@tonic-gate  *                With the advent of POSIX.2 compliance, this has become
1116*7c478bd9Sstevel@tonic-gate  *                a bit more complicated, and so should be done in one
1117*7c478bd9Sstevel@tonic-gate  *                place, for all to use.
1118*7c478bd9Sstevel@tonic-gate  */
1119*7c478bd9Sstevel@tonic-gate 
1120*7c478bd9Sstevel@tonic-gate static int
1121*7c478bd9Sstevel@tonic-gate reply2sender (void)
1122*7c478bd9Sstevel@tonic-gate {
1123*7c478bd9Sstevel@tonic-gate 	register int rep = (value("replyall") != NOSTR);
1124*7c478bd9Sstevel@tonic-gate 	register int flp = (value("flipr") != NOSTR);
1125*7c478bd9Sstevel@tonic-gate 
1126*7c478bd9Sstevel@tonic-gate 	return((rep && !flp)|| (!rep && flp));
1127*7c478bd9Sstevel@tonic-gate }
1128