xref: /csrg-svn/usr.bin/mail/cmd3.c (revision 68818)
122446Sdist /*
262083Sbostic  * Copyright (c) 1980, 1993
362083Sbostic  *	The Regents of the University of California.  All rights reserved.
433499Sbostic  *
542741Sbostic  * %sccs.include.redist.c%
622446Sdist  */
722446Sdist 
834905Sbostic #ifndef lint
9*68818Sdab static char sccsid[] = "@(#)cmd3.c	8.2 (Berkeley) 04/20/95";
1034905Sbostic #endif /* not lint */
111225Skas 
121225Skas #include "rcv.h"
1354505Sbostic #include "extern.h"
141225Skas 
151225Skas /*
161225Skas  * Mail -- a mail program
171225Skas  *
181225Skas  * Still more user commands.
191225Skas  */
201225Skas 
211225Skas /*
221225Skas  * Process a shell escape by saving signals, ignoring signals,
231225Skas  * and forking a sh -c
241225Skas  */
2554505Sbostic int
shell(str)261225Skas shell(str)
271225Skas 	char *str;
281225Skas {
2939612Sedward 	sig_t sigint = signal(SIGINT, SIG_IGN);
3034963Sedward 	char *shell;
311271Skas 	char cmd[BUFSIZ];
321225Skas 
3334963Sedward 	(void) strcpy(cmd, str);
341271Skas 	if (bangexp(cmd) < 0)
3536554Sedward 		return 1;
3634963Sedward 	if ((shell = value("SHELL")) == NOSTR)
3737870Sbostic 		shell = _PATH_CSHELL;
3834963Sedward 	(void) run_command(shell, 0, -1, -1, "-c", cmd, NOSTR);
3934963Sedward 	(void) signal(SIGINT, sigint);
401225Skas 	printf("!\n");
4134963Sedward 	return 0;
421225Skas }
431225Skas 
441225Skas /*
451225Skas  * Fork an interactive shell.
461225Skas  */
4731142Sedward /*ARGSUSED*/
4854505Sbostic int
dosh(str)491225Skas dosh(str)
501225Skas 	char *str;
511225Skas {
5239612Sedward 	sig_t sigint = signal(SIGINT, SIG_IGN);
5334963Sedward 	char *shell;
5431142Sedward 
5534963Sedward 	if ((shell = value("SHELL")) == NOSTR)
5637870Sbostic 		shell = _PATH_CSHELL;
5754505Sbostic 	(void) run_command(shell, 0, -1, -1, NOSTR, NOSTR, NOSTR);
5834963Sedward 	(void) signal(SIGINT, sigint);
591225Skas 	putchar('\n');
6034963Sedward 	return 0;
611225Skas }
621225Skas 
631225Skas /*
641271Skas  * Expand the shell escape by expanding unescaped !'s into the
651271Skas  * last issued command where possible.
661271Skas  */
671271Skas 
681271Skas char	lastbang[128];
691271Skas 
7054505Sbostic int
bangexp(str)711271Skas bangexp(str)
721271Skas 	char *str;
731271Skas {
741271Skas 	char bangbuf[BUFSIZ];
751271Skas 	register char *cp, *cp2;
761271Skas 	register int n;
771271Skas 	int changed = 0;
781271Skas 
791271Skas 	cp = str;
801271Skas 	cp2 = bangbuf;
811271Skas 	n = BUFSIZ;
821271Skas 	while (*cp) {
831271Skas 		if (*cp == '!') {
841271Skas 			if (n < strlen(lastbang)) {
851271Skas overf:
861271Skas 				printf("Command buffer overflow\n");
871271Skas 				return(-1);
881271Skas 			}
891271Skas 			changed++;
901271Skas 			strcpy(cp2, lastbang);
911271Skas 			cp2 += strlen(lastbang);
921271Skas 			n -= strlen(lastbang);
931271Skas 			cp++;
941271Skas 			continue;
951271Skas 		}
961271Skas 		if (*cp == '\\' && cp[1] == '!') {
971271Skas 			if (--n <= 1)
981271Skas 				goto overf;
991271Skas 			*cp2++ = '!';
1001271Skas 			cp += 2;
1011271Skas 			changed++;
1021271Skas 		}
1031271Skas 		if (--n <= 1)
1041271Skas 			goto overf;
1051271Skas 		*cp2++ = *cp++;
1061271Skas 	}
1071271Skas 	*cp2 = 0;
1081271Skas 	if (changed) {
1091271Skas 		printf("!%s\n", bangbuf);
1101271Skas 		fflush(stdout);
1111271Skas 	}
1121271Skas 	strcpy(str, bangbuf);
1131271Skas 	strncpy(lastbang, bangbuf, 128);
1141271Skas 	lastbang[127] = 0;
1151271Skas 	return(0);
1161271Skas }
1171271Skas 
1181271Skas /*
1191225Skas  * Print out a nice help message from some file or another.
1201225Skas  */
1211225Skas 
12254505Sbostic int
help()1231225Skas help()
1241225Skas {
1251225Skas 	register c;
1261225Skas 	register FILE *f;
1271225Skas 
12843865Sedward 	if ((f = Fopen(_PATH_HELP, "r")) == NULL) {
12937870Sbostic 		perror(_PATH_HELP);
1301225Skas 		return(1);
1311225Skas 	}
1321225Skas 	while ((c = getc(f)) != EOF)
1331225Skas 		putchar(c);
13443865Sedward 	Fclose(f);
1351225Skas 	return(0);
1361225Skas }
1371225Skas 
1381225Skas /*
1391225Skas  * Change user's working directory.
1401225Skas  */
14154505Sbostic int
schdir(arglist)14234966Sedward schdir(arglist)
14334966Sedward 	char **arglist;
1441225Skas {
14534966Sedward 	char *cp;
1461225Skas 
14734966Sedward 	if (*arglist == NOSTR)
1481225Skas 		cp = homedir;
1491225Skas 	else
15034966Sedward 		if ((cp = expand(*arglist)) == NOSTR)
1511225Skas 			return(1);
1521225Skas 	if (chdir(cp) < 0) {
1531225Skas 		perror(cp);
1541225Skas 		return(1);
1551225Skas 	}
15634966Sedward 	return 0;
1571225Skas }
1581225Skas 
15954505Sbostic int
respond(msgvec)16024752Sserge respond(msgvec)
16124752Sserge 	int *msgvec;
16224752Sserge {
16324752Sserge 	if (value("Replyall") == NOSTR)
16424752Sserge 		return (_respond(msgvec));
16524752Sserge 	else
16624752Sserge 		return (_Respond(msgvec));
16724752Sserge }
16824752Sserge 
1691225Skas /*
1701225Skas  * Reply to a list of messages.  Extract each name from the
1711225Skas  * message header and send them off to mail1()
1721225Skas  */
17354505Sbostic int
_respond(msgvec)17424752Sserge _respond(msgvec)
1751225Skas 	int *msgvec;
1761225Skas {
1771225Skas 	struct message *mp;
17831142Sedward 	char *cp, *rcv, *replyto;
17934800Sedward 	char **ap;
1801225Skas 	struct name *np;
1811225Skas 	struct header head;
1821225Skas 
1831225Skas 	if (msgvec[1] != 0) {
1841225Skas 		printf("Sorry, can't reply to multiple messages at once\n");
1851225Skas 		return(1);
1861225Skas 	}
1871225Skas 	mp = &message[msgvec[0] - 1];
18835107Sedward 	touch(mp);
1891225Skas 	dot = mp;
19034800Sedward 	if ((rcv = skin(hfield("from", mp))) == NOSTR)
19134800Sedward 		rcv = skin(nameof(mp, 1));
19234800Sedward 	if ((replyto = skin(hfield("reply-to", mp))) != NOSTR)
19334800Sedward 		np = extract(replyto, GTO);
19434800Sedward 	else if ((cp = skin(hfield("to", mp))) != NOSTR)
19534800Sedward 		np = extract(cp, GTO);
19634800Sedward 	else
19734800Sedward 		np = NIL;
19834800Sedward 	np = elide(np);
1994391Skurt 	/*
2004391Skurt 	 * Delete my name from the reply list,
2014391Skurt 	 * and with it, all my alternate names.
2024391Skurt 	 */
20334987Sedward 	np = delname(np, myname);
20410583Sleres 	if (altnames)
2054391Skurt 		for (ap = altnames; *ap; ap++)
20634987Sedward 			np = delname(np, *ap);
20734800Sedward 	if (np != NIL && replyto == NOSTR)
20834800Sedward 		np = cat(np, extract(rcv, GTO));
20934800Sedward 	else if (np == NIL) {
21034800Sedward 		if (replyto != NOSTR)
2112350Skas 			printf("Empty reply-to field -- replying to author\n");
21234800Sedward 		np = extract(rcv, GTO);
2132350Skas 	}
21434800Sedward 	head.h_to = np;
21534800Sedward 	if ((head.h_subject = hfield("subject", mp)) == NOSTR)
2161225Skas 		head.h_subject = hfield("subj", mp);
2172228Skas 	head.h_subject = reedit(head.h_subject);
21834800Sedward 	if (replyto == NOSTR && (cp = skin(hfield("cc", mp))) != NOSTR) {
21934800Sedward 		np = elide(extract(cp, GCC));
22034987Sedward 		np = delname(np, myname);
22134800Sedward 		if (altnames != 0)
22234800Sedward 			for (ap = altnames; *ap; ap++)
22334987Sedward 				np = delname(np, *ap);
22434800Sedward 		head.h_cc = np;
22534800Sedward 	} else
22634800Sedward 		head.h_cc = NIL;
22734800Sedward 	head.h_bcc = NIL;
22834800Sedward 	head.h_smopts = NIL;
22934800Sedward 	mail1(&head, 1);
2301225Skas 	return(0);
2311225Skas }
2321225Skas 
2331225Skas /*
2342228Skas  * Modify the subject we are replying to to begin with Re: if
2352228Skas  * it does not already.
2362228Skas  */
2372228Skas char *
reedit(subj)2382228Skas reedit(subj)
23934800Sedward 	register char *subj;
2402228Skas {
24134800Sedward 	char *newsubj;
2422228Skas 
2432228Skas 	if (subj == NOSTR)
24434800Sedward 		return NOSTR;
24534800Sedward 	if ((subj[0] == 'r' || subj[0] == 'R') &&
24634800Sedward 	    (subj[1] == 'e' || subj[1] == 'E') &&
24734800Sedward 	    subj[2] == ':')
24834800Sedward 		return subj;
24934800Sedward 	newsubj = salloc(strlen(subj) + 5);
25034800Sedward 	strcpy(newsubj, "Re: ");
25134802Sedward 	strcpy(newsubj + 4, subj);
25234800Sedward 	return newsubj;
2532228Skas }
2542228Skas 
2552228Skas /*
2561225Skas  * Preserve the named messages, so that they will be sent
2571225Skas  * back to the system mailbox.
2581225Skas  */
25954505Sbostic int
preserve(msgvec)2601225Skas preserve(msgvec)
2611225Skas 	int *msgvec;
2621225Skas {
2631225Skas 	register struct message *mp;
2641225Skas 	register int *ip, mesg;
2651225Skas 
2661225Skas 	if (edit) {
2671225Skas 		printf("Cannot \"preserve\" in edit mode\n");
2681225Skas 		return(1);
2691225Skas 	}
2701225Skas 	for (ip = msgvec; *ip != NULL; ip++) {
2711225Skas 		mesg = *ip;
2721225Skas 		mp = &message[mesg-1];
2731225Skas 		mp->m_flag |= MPRESERVE;
2743320Skas 		mp->m_flag &= ~MBOX;
2751225Skas 		dot = mp;
2761225Skas 	}
2771225Skas 	return(0);
2781225Skas }
2791225Skas 
2801225Skas /*
28124752Sserge  * Mark all given messages as unread.
28224752Sserge  */
28354505Sbostic int
unread(msgvec)28424752Sserge unread(msgvec)
28524752Sserge 	int	msgvec[];
28624752Sserge {
28724752Sserge 	register int *ip;
28824752Sserge 
28924752Sserge 	for (ip = msgvec; *ip != NULL; ip++) {
29024752Sserge 		dot = &message[*ip-1];
29124752Sserge 		dot->m_flag &= ~(MREAD|MTOUCH);
29224752Sserge 		dot->m_flag |= MSTATUS;
29324752Sserge 	}
29424752Sserge 	return(0);
29524752Sserge }
29624752Sserge 
29724752Sserge /*
2981225Skas  * Print the size of each message.
2991225Skas  */
30054505Sbostic int
messize(msgvec)3011225Skas messize(msgvec)
3021225Skas 	int *msgvec;
3031225Skas {
3041225Skas 	register struct message *mp;
3051225Skas 	register int *ip, mesg;
3061225Skas 
3071225Skas 	for (ip = msgvec; *ip != NULL; ip++) {
3081225Skas 		mesg = *ip;
3091225Skas 		mp = &message[mesg-1];
31024752Sserge 		printf("%d: %d/%ld\n", mesg, mp->m_lines, mp->m_size);
3111225Skas 	}
3121225Skas 	return(0);
3131225Skas }
3141225Skas 
3151225Skas /*
3161225Skas  * Quit quickly.  If we are sourcing, just pop the input level
3171225Skas  * by returning an error.
3181225Skas  */
31954505Sbostic int
rexit(e)3201225Skas rexit(e)
32154505Sbostic 	int e;
3221225Skas {
3231225Skas 	if (sourcing)
3241225Skas 		return(1);
3251225Skas 	exit(e);
32631142Sedward 	/*NOTREACHED*/
3271225Skas }
3281225Skas 
3291225Skas /*
3301225Skas  * Set or display a variable value.  Syntax is similar to that
3311225Skas  * of csh.
3321225Skas  */
33354505Sbostic int
set(arglist)3341225Skas set(arglist)
3351225Skas 	char **arglist;
3361225Skas {
3371225Skas 	register struct var *vp;
3381225Skas 	register char *cp, *cp2;
3391225Skas 	char varbuf[BUFSIZ], **ap, **p;
3401225Skas 	int errs, h, s;
3411225Skas 
34234987Sedward 	if (*arglist == NOSTR) {
3431225Skas 		for (h = 0, s = 1; h < HSHSIZE; h++)
3441225Skas 			for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
3451225Skas 				s++;
3461225Skas 		ap = (char **) salloc(s * sizeof *ap);
3471225Skas 		for (h = 0, p = ap; h < HSHSIZE; h++)
3481225Skas 			for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
3491225Skas 				*p++ = vp->v_name;
3501225Skas 		*p = NOSTR;
3511225Skas 		sort(ap);
3521225Skas 		for (p = ap; *p != NOSTR; p++)
3531225Skas 			printf("%s\t%s\n", *p, value(*p));
3541225Skas 		return(0);
3551225Skas 	}
3561225Skas 	errs = 0;
3571225Skas 	for (ap = arglist; *ap != NOSTR; ap++) {
3581225Skas 		cp = *ap;
3591225Skas 		cp2 = varbuf;
3601225Skas 		while (*cp != '=' && *cp != '\0')
3611225Skas 			*cp2++ = *cp++;
3621225Skas 		*cp2 = '\0';
3631225Skas 		if (*cp == '\0')
3641225Skas 			cp = "";
3651225Skas 		else
3661225Skas 			cp++;
3671225Skas 		if (equal(varbuf, "")) {
3681225Skas 			printf("Non-null variable name required\n");
3691225Skas 			errs++;
3701225Skas 			continue;
3711225Skas 		}
3721225Skas 		assign(varbuf, cp);
3731225Skas 	}
3741225Skas 	return(errs);
3751225Skas }
3761225Skas 
3771225Skas /*
3781225Skas  * Unset a bunch of variable values.
3791225Skas  */
38054505Sbostic int
unset(arglist)3811225Skas unset(arglist)
3821225Skas 	char **arglist;
3831225Skas {
3841225Skas 	register struct var *vp, *vp2;
3851225Skas 	int errs, h;
3861225Skas 	char **ap;
3871225Skas 
3881225Skas 	errs = 0;
3891225Skas 	for (ap = arglist; *ap != NOSTR; ap++) {
3901225Skas 		if ((vp2 = lookup(*ap)) == NOVAR) {
3911225Skas 			if (!sourcing) {
3921225Skas 				printf("\"%s\": undefined variable\n", *ap);
3931225Skas 				errs++;
3941225Skas 			}
3951225Skas 			continue;
3961225Skas 		}
3971225Skas 		h = hash(*ap);
3981225Skas 		if (vp2 == variables[h]) {
3991225Skas 			variables[h] = variables[h]->v_link;
4001225Skas 			vfree(vp2->v_name);
4011225Skas 			vfree(vp2->v_value);
40257659Sbostic 			free((char *)vp2);
4031225Skas 			continue;
4041225Skas 		}
4051225Skas 		for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link)
4061225Skas 			;
4071225Skas 		vp->v_link = vp2->v_link;
4081225Skas 		vfree(vp2->v_name);
4091225Skas 		vfree(vp2->v_value);
41057659Sbostic 		free((char *) vp2);
4111225Skas 	}
4121225Skas 	return(errs);
4131225Skas }
4141225Skas 
4151225Skas /*
4161225Skas  * Put add users to a group.
4171225Skas  */
41854505Sbostic int
group(argv)4191225Skas group(argv)
4201225Skas 	char **argv;
4211225Skas {
4221225Skas 	register struct grouphead *gh;
4231225Skas 	register struct group *gp;
4241225Skas 	register int h;
4251225Skas 	int s;
4261225Skas 	char **ap, *gname, **p;
4271225Skas 
42834987Sedward 	if (*argv == NOSTR) {
4291225Skas 		for (h = 0, s = 1; h < HSHSIZE; h++)
4301225Skas 			for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
4311225Skas 				s++;
4321225Skas 		ap = (char **) salloc(s * sizeof *ap);
4331225Skas 		for (h = 0, p = ap; h < HSHSIZE; h++)
4341225Skas 			for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
4351225Skas 				*p++ = gh->g_name;
4361225Skas 		*p = NOSTR;
4371225Skas 		sort(ap);
4381225Skas 		for (p = ap; *p != NOSTR; p++)
4391225Skas 			printgroup(*p);
4401225Skas 		return(0);
4411225Skas 	}
44234987Sedward 	if (argv[1] == NOSTR) {
4431225Skas 		printgroup(*argv);
4441225Skas 		return(0);
4451225Skas 	}
4461225Skas 	gname = *argv;
4471225Skas 	h = hash(gname);
4481225Skas 	if ((gh = findgroup(gname)) == NOGRP) {
4491225Skas 		gh = (struct grouphead *) calloc(sizeof *gh, 1);
4501225Skas 		gh->g_name = vcopy(gname);
4511225Skas 		gh->g_list = NOGE;
4521225Skas 		gh->g_link = groups[h];
4531225Skas 		groups[h] = gh;
4541225Skas 	}
4551225Skas 
4561225Skas 	/*
4571225Skas 	 * Insert names from the command list into the group.
4581225Skas 	 * Who cares if there are duplicates?  They get tossed
4591225Skas 	 * later anyway.
4601225Skas 	 */
4611225Skas 
4621225Skas 	for (ap = argv+1; *ap != NOSTR; ap++) {
4631225Skas 		gp = (struct group *) calloc(sizeof *gp, 1);
4641225Skas 		gp->ge_name = vcopy(*ap);
4651225Skas 		gp->ge_link = gh->g_list;
4661225Skas 		gh->g_list = gp;
4671225Skas 	}
4681225Skas 	return(0);
4691225Skas }
4701225Skas 
4711225Skas /*
4721225Skas  * Sort the passed string vecotor into ascending dictionary
4731225Skas  * order.
4741225Skas  */
47554505Sbostic void
sort(list)4761225Skas sort(list)
4771225Skas 	char **list;
4781225Skas {
4791225Skas 	register char **ap;
4801225Skas 	int diction();
4811225Skas 
4821225Skas 	for (ap = list; *ap != NOSTR; ap++)
4831225Skas 		;
4841225Skas 	if (ap-list < 2)
4851225Skas 		return;
48654505Sbostic 	qsort(list, ap-list, sizeof(*list), diction);
4871225Skas }
4881225Skas 
4891225Skas /*
4901225Skas  * Do a dictionary order comparison of the arguments from
4911225Skas  * qsort.
4921225Skas  */
49354505Sbostic int
diction(a,b)4941225Skas diction(a, b)
49554505Sbostic 	const void *a, *b;
4961225Skas {
49754505Sbostic 	return(strcmp(*(char **)a, *(char **)b));
4981225Skas }
4991225Skas 
5001225Skas /*
5011225Skas  * The do nothing command for comments.
5021225Skas  */
5031225Skas 
50431142Sedward /*ARGSUSED*/
50554505Sbostic int
null(e)5061225Skas null(e)
50754505Sbostic 	int e;
5081225Skas {
50931142Sedward 	return 0;
5101225Skas }
5111225Skas 
5121225Skas /*
51336554Sedward  * Change to another file.  With no argument, print information about
51436554Sedward  * the current file.
5151225Skas  */
51654505Sbostic int
file(argv)5171308Skas file(argv)
51834753Sedward 	register char **argv;
5191225Skas {
5201225Skas 
5211308Skas 	if (argv[0] == NOSTR) {
522*68818Sdab 		newfileinfo(0);
52334753Sedward 		return 0;
5241308Skas 	}
52536734Sedward 	if (setfile(*argv) < 0)
52636554Sedward 		return 1;
52734754Sedward 	announce();
52831142Sedward 	return 0;
5291225Skas }
5301225Skas 
5311225Skas /*
5321225Skas  * Expand file names like echo
5331225Skas  */
53454505Sbostic int
echo(argv)5351225Skas echo(argv)
5361225Skas 	char **argv;
5371225Skas {
5381225Skas 	register char **ap;
5391225Skas 	register char *cp;
5401225Skas 
5411225Skas 	for (ap = argv; *ap != NOSTR; ap++) {
5421225Skas 		cp = *ap;
54334702Sedward 		if ((cp = expand(cp)) != NOSTR) {
54434702Sedward 			if (ap != argv)
54534702Sedward 				putchar(' ');
54634702Sedward 			printf("%s", cp);
54734702Sedward 		}
5481225Skas 	}
54934702Sedward 	putchar('\n');
55034800Sedward 	return 0;
5511225Skas }
5521225Skas 
55354505Sbostic int
Respond(msgvec)55424752Sserge Respond(msgvec)
55524752Sserge 	int *msgvec;
55624752Sserge {
55724752Sserge 	if (value("Replyall") == NOSTR)
55824752Sserge 		return (_Respond(msgvec));
55924752Sserge 	else
56024752Sserge 		return (_respond(msgvec));
56124752Sserge }
56224752Sserge 
5631225Skas /*
5641225Skas  * Reply to a series of messages by simply mailing to the senders
5651225Skas  * and not messing around with the To: and Cc: lists as in normal
5661225Skas  * reply.
5671225Skas  */
56854505Sbostic int
_Respond(msgvec)56924752Sserge _Respond(msgvec)
5701225Skas 	int msgvec[];
5711225Skas {
5721225Skas 	struct header head;
5731225Skas 	struct message *mp;
57434800Sedward 	register int *ap;
57534800Sedward 	register char *cp;
5761225Skas 
57734800Sedward 	head.h_to = NIL;
57834800Sedward 	for (ap = msgvec; *ap != 0; ap++) {
5791225Skas 		mp = &message[*ap - 1];
58035107Sedward 		touch(mp);
5811225Skas 		dot = mp;
58234800Sedward 		if ((cp = skin(hfield("from", mp))) == NOSTR)
58334800Sedward 			cp = skin(nameof(mp, 2));
58434800Sedward 		head.h_to = cat(head.h_to, extract(cp, GTO));
5851225Skas 	}
58634800Sedward 	if (head.h_to == NIL)
58734800Sedward 		return 0;
5881225Skas 	mp = &message[msgvec[0] - 1];
58934800Sedward 	if ((head.h_subject = hfield("subject", mp)) == NOSTR)
59034800Sedward 		head.h_subject = hfield("subj", mp);
59134800Sedward 	head.h_subject = reedit(head.h_subject);
59234800Sedward 	head.h_cc = NIL;
59334800Sedward 	head.h_bcc = NIL;
59434800Sedward 	head.h_smopts = NIL;
59534800Sedward 	mail1(&head, 1);
59634800Sedward 	return 0;
5971225Skas }
5981521Skas 
5991521Skas /*
6001521Skas  * Conditional commands.  These allow one to parameterize one's
6011521Skas  * .mailrc and do some things if sending, others if receiving.
6021521Skas  */
60354505Sbostic int
ifcmd(argv)6041521Skas ifcmd(argv)
6051521Skas 	char **argv;
6061521Skas {
6071521Skas 	register char *cp;
6081521Skas 
6091521Skas 	if (cond != CANY) {
6101521Skas 		printf("Illegal nested \"if\"\n");
6111521Skas 		return(1);
6121521Skas 	}
6131521Skas 	cond = CANY;
6141521Skas 	cp = argv[0];
6151521Skas 	switch (*cp) {
6161521Skas 	case 'r': case 'R':
6171521Skas 		cond = CRCV;
6181521Skas 		break;
6191521Skas 
6201521Skas 	case 's': case 'S':
6211521Skas 		cond = CSEND;
6221521Skas 		break;
6231521Skas 
6241521Skas 	default:
6251521Skas 		printf("Unrecognized if-keyword: \"%s\"\n", cp);
6261521Skas 		return(1);
6271521Skas 	}
6281521Skas 	return(0);
6291521Skas }
6301521Skas 
6311521Skas /*
6321521Skas  * Implement 'else'.  This is pretty simple -- we just
6331521Skas  * flip over the conditional flag.
6341521Skas  */
63554505Sbostic int
elsecmd()6361521Skas elsecmd()
6371521Skas {
6381521Skas 
6391521Skas 	switch (cond) {
6401521Skas 	case CANY:
6411521Skas 		printf("\"Else\" without matching \"if\"\n");
6421521Skas 		return(1);
6431521Skas 
6441521Skas 	case CSEND:
6451521Skas 		cond = CRCV;
6461521Skas 		break;
6471521Skas 
6481521Skas 	case CRCV:
6491521Skas 		cond = CSEND;
6501521Skas 		break;
6511521Skas 
6521521Skas 	default:
6531521Skas 		printf("Mail's idea of conditions is screwed up\n");
6541521Skas 		cond = CANY;
6551521Skas 		break;
6561521Skas 	}
6571521Skas 	return(0);
6581521Skas }
6591521Skas 
6601521Skas /*
6611521Skas  * End of if statement.  Just set cond back to anything.
6621521Skas  */
66354505Sbostic int
endifcmd()6641521Skas endifcmd()
6651521Skas {
6661521Skas 
6671521Skas 	if (cond == CANY) {
6681521Skas 		printf("\"Endif\" without matching \"if\"\n");
6691521Skas 		return(1);
6701521Skas 	}
6711521Skas 	cond = CANY;
6721521Skas 	return(0);
6731521Skas }
6744391Skurt 
6754391Skurt /*
6764391Skurt  * Set the list of alternate names.
6774391Skurt  */
67854505Sbostic int
alternates(namelist)6794391Skurt alternates(namelist)
6804391Skurt 	char **namelist;
6814391Skurt {
6824391Skurt 	register int c;
6834391Skurt 	register char **ap, **ap2, *cp;
6844391Skurt 
6854391Skurt 	c = argcount(namelist) + 1;
6864391Skurt 	if (c == 1) {
6874391Skurt 		if (altnames == 0)
6884391Skurt 			return(0);
6894391Skurt 		for (ap = altnames; *ap; ap++)
6904391Skurt 			printf("%s ", *ap);
6914391Skurt 		printf("\n");
6924391Skurt 		return(0);
6934391Skurt 	}
6944391Skurt 	if (altnames != 0)
69557659Sbostic 		free((char *) altnames);
69631142Sedward 	altnames = (char **) calloc((unsigned) c, sizeof (char *));
6974391Skurt 	for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) {
69831142Sedward 		cp = (char *) calloc((unsigned) strlen(*ap) + 1, sizeof (char));
6994391Skurt 		strcpy(cp, *ap);
7004391Skurt 		*ap2 = cp;
7014391Skurt 	}
7024391Skurt 	*ap2 = 0;
7034391Skurt 	return(0);
7044391Skurt }
705