xref: /titanic_44/usr/src/cmd/mailx/lex.c (revision eb2b0a6162b47bdee86cc3d2e844dc8f89d95371)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*eb2b0a61Sas145665  * Common Development and Distribution License (the "License").
6*eb2b0a61Sas145665  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate /*
23*eb2b0a61Sas145665  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*eb2b0a61Sas145665 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*eb2b0a61Sas145665 /*	All Rights Reserved   */
29*eb2b0a61Sas145665 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
327c478bd9Sstevel@tonic-gate  * The Regents of the University of California
337c478bd9Sstevel@tonic-gate  * All Rights Reserved
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
367c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
377c478bd9Sstevel@tonic-gate  * contributors.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include "rcv.h"
437c478bd9Sstevel@tonic-gate #include <locale.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * mailx -- a modified version of a University of California at Berkeley
477c478bd9Sstevel@tonic-gate  *	mail program
487c478bd9Sstevel@tonic-gate  *
497c478bd9Sstevel@tonic-gate  * Lexical processing of commands.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #ifdef SIGCONT
537c478bd9Sstevel@tonic-gate static void		contin(int);
547c478bd9Sstevel@tonic-gate #endif
557c478bd9Sstevel@tonic-gate static int		isprefix(char *as1, char *as2);
567c478bd9Sstevel@tonic-gate static const struct cmd	*lex(char word[]);
577c478bd9Sstevel@tonic-gate static int		Passeren(void);
587c478bd9Sstevel@tonic-gate static void		setmsize(int sz);
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate  * Set up editing on the given file name.
627c478bd9Sstevel@tonic-gate  * If isedit is true, we are considered to be editing the file,
637c478bd9Sstevel@tonic-gate  * otherwise we are reading our mail which has signficance for
647c478bd9Sstevel@tonic-gate  * mbox and so forth.
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate int
setfile(char * name,int isedit)687c478bd9Sstevel@tonic-gate setfile(char *name, int isedit)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate 	FILE *ibuf;
717c478bd9Sstevel@tonic-gate 	int i;
727c478bd9Sstevel@tonic-gate 	static int shudclob;
737c478bd9Sstevel@tonic-gate 	static char efile[PATHSIZE];
747c478bd9Sstevel@tonic-gate 	char fortest[128];
757c478bd9Sstevel@tonic-gate 	struct stat stbuf;
767c478bd9Sstevel@tonic-gate 	int exrc = 1;
777c478bd9Sstevel@tonic-gate 	int rc = -1;
787c478bd9Sstevel@tonic-gate 	int fd = -1;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	if (!isedit && issysmbox)
817c478bd9Sstevel@tonic-gate 		lockmail();
827c478bd9Sstevel@tonic-gate 	if (stat(name, &stbuf) < 0 && errno == EOVERFLOW) {
837c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("mailbox %s is too large to"
847c478bd9Sstevel@tonic-gate 		    " accept incoming mail\n"), name);
857c478bd9Sstevel@tonic-gate 		goto doret;
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 	if ((ibuf = fopen(name, "r")) == NULL) {
887c478bd9Sstevel@tonic-gate 		extern int errno;
897c478bd9Sstevel@tonic-gate 		int sverrno = errno;
907c478bd9Sstevel@tonic-gate 		int filethere = (access(name, 0) == 0);
917c478bd9Sstevel@tonic-gate 		errno = sverrno;
927c478bd9Sstevel@tonic-gate 		if (exitflg)
937c478bd9Sstevel@tonic-gate 			goto doexit;	/* no mail, return error */
947c478bd9Sstevel@tonic-gate 		if (isedit || filethere)
957c478bd9Sstevel@tonic-gate 			perror(name);
967c478bd9Sstevel@tonic-gate 		else if (!Hflag) {
977c478bd9Sstevel@tonic-gate 			char *f = strrchr(name, '/');
987c478bd9Sstevel@tonic-gate 			if (f == NOSTR)
997c478bd9Sstevel@tonic-gate 				fprintf(stderr, gettext("No mail.\n"));
1007c478bd9Sstevel@tonic-gate 			else
1017c478bd9Sstevel@tonic-gate 				fprintf(stderr, gettext("No mail for %s\n"),
1027c478bd9Sstevel@tonic-gate f+1);
1037c478bd9Sstevel@tonic-gate 		}
1047c478bd9Sstevel@tonic-gate 		goto doret;
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 	fstat(fileno(ibuf), &stbuf);
1077c478bd9Sstevel@tonic-gate 	if (stbuf.st_size == 0L || (stbuf.st_mode&S_IFMT) != S_IFREG) {
1087c478bd9Sstevel@tonic-gate 		if (exitflg)
1097c478bd9Sstevel@tonic-gate 			goto doexit;	/* no mail, return error */
1107c478bd9Sstevel@tonic-gate 		if (isedit)
1117c478bd9Sstevel@tonic-gate 			if (stbuf.st_size == 0L)
1127c478bd9Sstevel@tonic-gate 				fprintf(stderr, gettext("%s: empty file\n"),
1137c478bd9Sstevel@tonic-gate name);
1147c478bd9Sstevel@tonic-gate 			else
1157c478bd9Sstevel@tonic-gate 				fprintf(stderr,
1167c478bd9Sstevel@tonic-gate 				    gettext("%s: not a regular file\n"), name);
1177c478bd9Sstevel@tonic-gate 		else if (!Hflag) {
1187c478bd9Sstevel@tonic-gate 			if (strrchr(name, '/') == NOSTR)
1197c478bd9Sstevel@tonic-gate 				fprintf(stderr, gettext("No mail.\n"));
1207c478bd9Sstevel@tonic-gate 			else
1217c478bd9Sstevel@tonic-gate 				fprintf(stderr, gettext("No mail for %s\n"),
1227c478bd9Sstevel@tonic-gate strrchr(name, '/') + 1);
1237c478bd9Sstevel@tonic-gate 		}
1247c478bd9Sstevel@tonic-gate 		fclose(ibuf);
1257c478bd9Sstevel@tonic-gate 		goto doret;
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 
128*eb2b0a61Sas145665 	if (fgets(fortest, sizeof (fortest), ibuf) == NULL) {
129*eb2b0a61Sas145665 		perror(gettext("mailx: Unable to read from mail file"));
130*eb2b0a61Sas145665 		goto doexit;
131*eb2b0a61Sas145665 	}
132*eb2b0a61Sas145665 
1337c478bd9Sstevel@tonic-gate 	fseek(ibuf, (long)(BUFSIZ+1), 0);	/* flush input buffer */
1347c478bd9Sstevel@tonic-gate 	fseek(ibuf, 0L, 0);
1357c478bd9Sstevel@tonic-gate 	if (strncmp(fortest, "Forward to ", 11) == 0) {
1367c478bd9Sstevel@tonic-gate 		if (exitflg)
1377c478bd9Sstevel@tonic-gate 			goto doexit;	/* no mail, return error */
1387c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Your mail is being forwarded to %s"),
1397c478bd9Sstevel@tonic-gate fortest+11);
1407c478bd9Sstevel@tonic-gate 		fclose(ibuf);
1417c478bd9Sstevel@tonic-gate 		goto doret;
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 	if (exitflg) {
1447c478bd9Sstevel@tonic-gate 		exrc = 0;
1457c478bd9Sstevel@tonic-gate 		goto doexit;	/* there is mail, return success */
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/*
1497c478bd9Sstevel@tonic-gate 	 * Looks like all will be well. Must hold signals
1507c478bd9Sstevel@tonic-gate 	 * while we are reading the new file, else we will ruin
1517c478bd9Sstevel@tonic-gate 	 * the message[] data structure.
1527c478bd9Sstevel@tonic-gate 	 * Copy the messages into /tmp and set pointers.
1537c478bd9Sstevel@tonic-gate 	 */
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	holdsigs();
1567c478bd9Sstevel@tonic-gate 	if (shudclob) {
1577c478bd9Sstevel@tonic-gate 		/*
1587c478bd9Sstevel@tonic-gate 		 * Now that we know we can switch to the new file
1597c478bd9Sstevel@tonic-gate 		 * it's safe to close out the current file.
1607c478bd9Sstevel@tonic-gate 		 *
1617c478bd9Sstevel@tonic-gate 		 * If we're switching to the file we are currently
1627c478bd9Sstevel@tonic-gate 		 * editing, don't allow it to be removed as a side
1637c478bd9Sstevel@tonic-gate 		 * effect of closing it out.
1647c478bd9Sstevel@tonic-gate 		 */
1657c478bd9Sstevel@tonic-gate 		if (edit)
1667c478bd9Sstevel@tonic-gate 			edstop(strcmp(editfile, name) == 0);
1677c478bd9Sstevel@tonic-gate 		else {
1687c478bd9Sstevel@tonic-gate 			quit(strcmp(editfile, name) == 0);
1697c478bd9Sstevel@tonic-gate 			if (issysmbox)
1707c478bd9Sstevel@tonic-gate 				Verhogen();
1717c478bd9Sstevel@tonic-gate 		}
1727c478bd9Sstevel@tonic-gate 		fflush(stdout);
1737c478bd9Sstevel@tonic-gate 		fclose(itf);
1747c478bd9Sstevel@tonic-gate 		fclose(otf);
1757c478bd9Sstevel@tonic-gate 		free(message);
1767c478bd9Sstevel@tonic-gate 		space = 0;
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 	readonly = 0;
1797c478bd9Sstevel@tonic-gate 	if (!isedit && issysmbox && !Hflag)
1807c478bd9Sstevel@tonic-gate 		readonly = Passeren() == -1;
1817c478bd9Sstevel@tonic-gate 	lock(ibuf, "r", 1);
1827c478bd9Sstevel@tonic-gate 	fstat(fileno(ibuf), &stbuf);
1837c478bd9Sstevel@tonic-gate 	utimep->actime = stbuf.st_atime;
1847c478bd9Sstevel@tonic-gate 	utimep->modtime = stbuf.st_mtime;
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	if (!readonly)
1877c478bd9Sstevel@tonic-gate 		if ((i = open(name, O_WRONLY)) < 0)
1887c478bd9Sstevel@tonic-gate 			readonly++;
1897c478bd9Sstevel@tonic-gate 		else
1907c478bd9Sstevel@tonic-gate 			close(i);
1917c478bd9Sstevel@tonic-gate 	shudclob = 1;
1927c478bd9Sstevel@tonic-gate 	edit = isedit;
1937c478bd9Sstevel@tonic-gate 	nstrcpy(efile, PATHSIZE, name);
1947c478bd9Sstevel@tonic-gate 	editfile = efile;
1957c478bd9Sstevel@tonic-gate #ifdef notdef
1967c478bd9Sstevel@tonic-gate 	if (name != mailname)
1977c478bd9Sstevel@tonic-gate 		nstrcpy(mailname, PATHSIZE, name);
1987c478bd9Sstevel@tonic-gate #endif
1997c478bd9Sstevel@tonic-gate 	mailsize = fsize(ibuf);
2007c478bd9Sstevel@tonic-gate 	if ((fd = open(tempMesg, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 ||
2017c478bd9Sstevel@tonic-gate 	(otf = fdopen(fd, "w")) == NULL) {
2027c478bd9Sstevel@tonic-gate 		perror(tempMesg);
2037c478bd9Sstevel@tonic-gate 		if (!edit && issysmbox)
2047c478bd9Sstevel@tonic-gate 			Verhogen();
2057c478bd9Sstevel@tonic-gate 		goto doexit;
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 	if ((itf = fopen(tempMesg, "r")) == NULL) {
2087c478bd9Sstevel@tonic-gate 		perror(tempMesg);
2097c478bd9Sstevel@tonic-gate 		if (!edit && issysmbox)
2107c478bd9Sstevel@tonic-gate 			Verhogen();
2117c478bd9Sstevel@tonic-gate 		goto doexit;
2127c478bd9Sstevel@tonic-gate 	}
2137c478bd9Sstevel@tonic-gate 	removefile(tempMesg);
2147c478bd9Sstevel@tonic-gate 	setptr(ibuf);
2157c478bd9Sstevel@tonic-gate 	setmsize(msgCount);
2167c478bd9Sstevel@tonic-gate 	fclose(ibuf);
2177c478bd9Sstevel@tonic-gate 	relsesigs();
2187c478bd9Sstevel@tonic-gate 	sawcom = 0;
2197c478bd9Sstevel@tonic-gate 	rc = 0;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate doret:
2227c478bd9Sstevel@tonic-gate 	if (!isedit && issysmbox)
2237c478bd9Sstevel@tonic-gate 		unlockmail();
2247c478bd9Sstevel@tonic-gate 	return (rc);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate doexit:
2277c478bd9Sstevel@tonic-gate 	if (!isedit && issysmbox)
2287c478bd9Sstevel@tonic-gate 		unlockmail();
2297c478bd9Sstevel@tonic-gate 	exit(exrc ? exrc : rpterr);
2307c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate /* global to semaphores */
2347c478bd9Sstevel@tonic-gate static char semfn[128];
2357c478bd9Sstevel@tonic-gate static FILE *semfp = NULL;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate  *  return -1 if file is already being read, 0 otherwise
2397c478bd9Sstevel@tonic-gate  */
2407c478bd9Sstevel@tonic-gate static int
Passeren(void)2417c478bd9Sstevel@tonic-gate Passeren(void)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 	char *home;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if ((home = getenv("HOME")) == NULL)
246*eb2b0a61Sas145665 		return (0);
2477c478bd9Sstevel@tonic-gate 	snprintf(semfn, sizeof (semfn), "%s%s", home, "/.Maillock");
2487c478bd9Sstevel@tonic-gate 	if ((semfp = fopen(semfn, "w")) == NULL) {
2497c478bd9Sstevel@tonic-gate 		fprintf(stderr,
2507c478bd9Sstevel@tonic-gate 	    gettext("WARNING: Can't open mail lock file (%s).\n"), semfn);
2517c478bd9Sstevel@tonic-gate 		fprintf(stderr,
2527c478bd9Sstevel@tonic-gate 	    gettext("\t Assuming you are not already reading mail.\n"));
253*eb2b0a61Sas145665 		return (0);
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 	if (lock(semfp, "w", 0) < 0) {
2567c478bd9Sstevel@tonic-gate 		if (errno == ENOLCK) {
2577c478bd9Sstevel@tonic-gate 			fprintf(stderr,
2587c478bd9Sstevel@tonic-gate gettext("WARNING: Unable to acquire mail lock, no record locks available.\n"));
2597c478bd9Sstevel@tonic-gate 			fprintf(stderr,
2607c478bd9Sstevel@tonic-gate 		    gettext("\t Assuming you are not already reading mail.\n"));
261*eb2b0a61Sas145665 			return (0);
2627c478bd9Sstevel@tonic-gate 		}
2637c478bd9Sstevel@tonic-gate 		fprintf(stderr,
2647c478bd9Sstevel@tonic-gate 		    gettext("WARNING: You are already reading mail.\n"));
2657c478bd9Sstevel@tonic-gate 		fprintf(stderr,
2667c478bd9Sstevel@tonic-gate 		    gettext("\t This instance of mail is read only.\n"));
2677c478bd9Sstevel@tonic-gate 		fclose(semfp);
2687c478bd9Sstevel@tonic-gate 		semfp = NULL;
269*eb2b0a61Sas145665 		return (-1);
2707c478bd9Sstevel@tonic-gate 	}
271*eb2b0a61Sas145665 	return (0);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate void
Verhogen(void)2757c478bd9Sstevel@tonic-gate Verhogen(void)
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate 	if (semfp != NULL) {
2787c478bd9Sstevel@tonic-gate 		unlink(semfn);
2797c478bd9Sstevel@tonic-gate 		fclose(semfp);
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate  * Interpret user commands one by one.  If standard input is not a tty,
2857c478bd9Sstevel@tonic-gate  * print no prompt.
2867c478bd9Sstevel@tonic-gate  */
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate static int	*msgvec;
2897c478bd9Sstevel@tonic-gate static int	shudprompt;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate void
commands(void)2927c478bd9Sstevel@tonic-gate commands(void)
2937c478bd9Sstevel@tonic-gate {
2947c478bd9Sstevel@tonic-gate 	int eofloop;
2957c478bd9Sstevel@tonic-gate 	register int n;
2967c478bd9Sstevel@tonic-gate 	char linebuf[LINESIZE];
2977c478bd9Sstevel@tonic-gate 	char line[LINESIZE];
2987c478bd9Sstevel@tonic-gate 	struct stat minfo;
2997c478bd9Sstevel@tonic-gate 	FILE *ibuf;
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate #ifdef SIGCONT
3027c478bd9Sstevel@tonic-gate 	sigset(SIGCONT, SIG_DFL);
3037c478bd9Sstevel@tonic-gate #endif
3047c478bd9Sstevel@tonic-gate 	if (rcvmode && !sourcing) {
3057c478bd9Sstevel@tonic-gate 		if (sigset(SIGINT, SIG_IGN) != SIG_IGN)
3067c478bd9Sstevel@tonic-gate 			sigset(SIGINT, stop);
3077c478bd9Sstevel@tonic-gate 		if (sigset(SIGHUP, SIG_IGN) != SIG_IGN)
3087c478bd9Sstevel@tonic-gate 			sigset(SIGHUP, hangup);
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 	for (;;) {
3117c478bd9Sstevel@tonic-gate 		setjmp(srbuf);
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 		/*
3147c478bd9Sstevel@tonic-gate 		 * Print the prompt, if needed.  Clear out
3157c478bd9Sstevel@tonic-gate 		 * string space, and flush the output.
3167c478bd9Sstevel@tonic-gate 		 */
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 		if (!rcvmode && !sourcing)
3197c478bd9Sstevel@tonic-gate 			return;
3207c478bd9Sstevel@tonic-gate 		eofloop = 0;
3217c478bd9Sstevel@tonic-gate top:
3227c478bd9Sstevel@tonic-gate 		if ((shudprompt = (intty && !sourcing)) != 0) {
3237c478bd9Sstevel@tonic-gate 			if (prompt == NOSTR) {
3247c478bd9Sstevel@tonic-gate 				if ((int)value("bsdcompat"))
3257c478bd9Sstevel@tonic-gate 					prompt = "& ";
3267c478bd9Sstevel@tonic-gate 				else
3277c478bd9Sstevel@tonic-gate 					prompt = "";
3287c478bd9Sstevel@tonic-gate 			}
3297c478bd9Sstevel@tonic-gate #ifdef SIGCONT
3307c478bd9Sstevel@tonic-gate 			sigset(SIGCONT, contin);
3317c478bd9Sstevel@tonic-gate #endif
3327c478bd9Sstevel@tonic-gate 			if (intty && value("autoinc") &&
3337c478bd9Sstevel@tonic-gate 			    stat(editfile, &minfo) >= 0 &&
3347c478bd9Sstevel@tonic-gate 			    minfo.st_size > mailsize) {
3357c478bd9Sstevel@tonic-gate 				int OmsgCount, i;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 				OmsgCount = msgCount;
3387c478bd9Sstevel@tonic-gate 				fseek(otf, 0L, 2);
3397c478bd9Sstevel@tonic-gate 				holdsigs();
3407c478bd9Sstevel@tonic-gate 				if (!edit && issysmbox)
3417c478bd9Sstevel@tonic-gate 					lockmail();
3427c478bd9Sstevel@tonic-gate 				if ((ibuf = fopen(editfile, "r")) == NULL) {
3437c478bd9Sstevel@tonic-gate 					fprintf(stderr,
3447c478bd9Sstevel@tonic-gate 					    gettext("Can't reopen %s\n"),
3457c478bd9Sstevel@tonic-gate 					    editfile);
3467c478bd9Sstevel@tonic-gate 					if (!edit && issysmbox)
3477c478bd9Sstevel@tonic-gate 						unlockmail();
3487c478bd9Sstevel@tonic-gate 					exit(1);
3497c478bd9Sstevel@tonic-gate 					/* NOTREACHED */
3507c478bd9Sstevel@tonic-gate 				}
3517c478bd9Sstevel@tonic-gate 				if (edit || !issysmbox)
3527c478bd9Sstevel@tonic-gate 					lock(ibuf, "r", 1);
3537c478bd9Sstevel@tonic-gate 				fseek(ibuf, mailsize, 0);
3547c478bd9Sstevel@tonic-gate 				mailsize = fsize(ibuf);
3557c478bd9Sstevel@tonic-gate 				setptr(ibuf);
3567c478bd9Sstevel@tonic-gate 				setmsize(msgCount);
3577c478bd9Sstevel@tonic-gate 				fclose(ibuf);
3587c478bd9Sstevel@tonic-gate 				if (!edit && issysmbox)
3597c478bd9Sstevel@tonic-gate 					unlockmail();
3607c478bd9Sstevel@tonic-gate 				if (msgCount-OmsgCount > 0) {
3617c478bd9Sstevel@tonic-gate 					printf(gettext(
3627c478bd9Sstevel@tonic-gate 					    "New mail has arrived.\n"));
3637c478bd9Sstevel@tonic-gate 					if (msgCount - OmsgCount == 1)
3647c478bd9Sstevel@tonic-gate 						printf(gettext(
3657c478bd9Sstevel@tonic-gate 						    "Loaded 1 new message\n"));
3667c478bd9Sstevel@tonic-gate 					else
3677c478bd9Sstevel@tonic-gate 						printf(gettext(
3687c478bd9Sstevel@tonic-gate 						    "Loaded %d new messages\n"),
3697c478bd9Sstevel@tonic-gate 						    msgCount-OmsgCount);
3707c478bd9Sstevel@tonic-gate 					if (value("header") != NOSTR)
3717c478bd9Sstevel@tonic-gate 						for (i = OmsgCount+1;
3727c478bd9Sstevel@tonic-gate 						    i <= msgCount; i++) {
3737c478bd9Sstevel@tonic-gate 							printhead(i);
3747c478bd9Sstevel@tonic-gate 							sreset();
3757c478bd9Sstevel@tonic-gate 						}
3767c478bd9Sstevel@tonic-gate 				}
3777c478bd9Sstevel@tonic-gate 				relsesigs();
3787c478bd9Sstevel@tonic-gate 			}
3797c478bd9Sstevel@tonic-gate 			printf("%s", prompt);
3807c478bd9Sstevel@tonic-gate 		}
3817c478bd9Sstevel@tonic-gate 		flush();
3827c478bd9Sstevel@tonic-gate 		sreset();
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 		/*
3857c478bd9Sstevel@tonic-gate 		 * Read a line of commands from the current input
3867c478bd9Sstevel@tonic-gate 		 * and handle end of file specially.
3877c478bd9Sstevel@tonic-gate 		 */
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 		n = 0;
3907c478bd9Sstevel@tonic-gate 		linebuf[0] = '\0';
3917c478bd9Sstevel@tonic-gate 		for (;;) {
3927c478bd9Sstevel@tonic-gate 			if (readline(input, line) <= 0) {
3937c478bd9Sstevel@tonic-gate 				if (n != 0)
3947c478bd9Sstevel@tonic-gate 					break;
3957c478bd9Sstevel@tonic-gate 				if (loading)
3967c478bd9Sstevel@tonic-gate 					return;
3977c478bd9Sstevel@tonic-gate 				if (sourcing) {
3987c478bd9Sstevel@tonic-gate 					unstack();
3997c478bd9Sstevel@tonic-gate 					goto more;
4007c478bd9Sstevel@tonic-gate 				}
4017c478bd9Sstevel@tonic-gate 				if (value("ignoreeof") != NOSTR && shudprompt) {
4027c478bd9Sstevel@tonic-gate 					if (++eofloop < 25) {
4037c478bd9Sstevel@tonic-gate 						printf(gettext(
4047c478bd9Sstevel@tonic-gate 						    "Use \"quit\" to quit.\n"));
4057c478bd9Sstevel@tonic-gate 						goto top;
4067c478bd9Sstevel@tonic-gate 					}
4077c478bd9Sstevel@tonic-gate 				}
4087c478bd9Sstevel@tonic-gate 				return;
4097c478bd9Sstevel@tonic-gate 			}
4107c478bd9Sstevel@tonic-gate 			if ((n = strlen(line)) == 0)
4117c478bd9Sstevel@tonic-gate 				break;
4127c478bd9Sstevel@tonic-gate 			n--;
4137c478bd9Sstevel@tonic-gate 			if (line[n] != '\\')
4147c478bd9Sstevel@tonic-gate 				break;
4157c478bd9Sstevel@tonic-gate 			line[n++] = ' ';
4167c478bd9Sstevel@tonic-gate 			if (n > LINESIZE - (int)strlen(linebuf) - 1)
4177c478bd9Sstevel@tonic-gate 				break;
4187c478bd9Sstevel@tonic-gate 			strcat(linebuf, line);
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 		n = LINESIZE - strlen(linebuf) - 1;
4217c478bd9Sstevel@tonic-gate 		if ((int)strlen(line) > n) {
4227c478bd9Sstevel@tonic-gate 			printf(gettext(
4237c478bd9Sstevel@tonic-gate 		"Line plus continuation line too long:\n\t%s\n\nplus\n\t%s\n"),
4247c478bd9Sstevel@tonic-gate 			    linebuf, line);
4257c478bd9Sstevel@tonic-gate 			if (loading)
4267c478bd9Sstevel@tonic-gate 				return;
4277c478bd9Sstevel@tonic-gate 			if (sourcing) {
4287c478bd9Sstevel@tonic-gate 				unstack();
4297c478bd9Sstevel@tonic-gate 				goto more;
4307c478bd9Sstevel@tonic-gate 			}
4317c478bd9Sstevel@tonic-gate 			return;
4327c478bd9Sstevel@tonic-gate 		}
4337c478bd9Sstevel@tonic-gate 		strncat(linebuf, line, n);
4347c478bd9Sstevel@tonic-gate #ifdef SIGCONT
4357c478bd9Sstevel@tonic-gate 		sigset(SIGCONT, SIG_DFL);
4367c478bd9Sstevel@tonic-gate #endif
4377c478bd9Sstevel@tonic-gate 		if (execute(linebuf, 0))
4387c478bd9Sstevel@tonic-gate 			return;
4397c478bd9Sstevel@tonic-gate more:;
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate /*
4447c478bd9Sstevel@tonic-gate  * Execute a single command.  If the command executed
4457c478bd9Sstevel@tonic-gate  * is "quit," then return non-zero so that the caller
4467c478bd9Sstevel@tonic-gate  * will know to return back to main, if he cares.
4477c478bd9Sstevel@tonic-gate  * Contxt is non-zero if called while composing mail.
4487c478bd9Sstevel@tonic-gate  */
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate int
execute(char linebuf[],int contxt)4517c478bd9Sstevel@tonic-gate execute(char linebuf[], int contxt)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	char word[LINESIZE];
4547c478bd9Sstevel@tonic-gate 	char *arglist[MAXARGC];
4557c478bd9Sstevel@tonic-gate 	const struct cmd *com;
4567c478bd9Sstevel@tonic-gate 	register char *cp, *cp2;
4577c478bd9Sstevel@tonic-gate 	register int c, e;
4587c478bd9Sstevel@tonic-gate 	int muvec[2];
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	/*
4617c478bd9Sstevel@tonic-gate 	 * Strip the white space away from the beginning
4627c478bd9Sstevel@tonic-gate 	 * of the command, then scan out a word, which
4637c478bd9Sstevel@tonic-gate 	 * consists of anything except digits and white space.
4647c478bd9Sstevel@tonic-gate 	 *
4657c478bd9Sstevel@tonic-gate 	 * Handle |, ! and # differently to get the correct
4667c478bd9Sstevel@tonic-gate 	 * lexical conventions.
4677c478bd9Sstevel@tonic-gate 	 */
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	cp = linebuf;
4707c478bd9Sstevel@tonic-gate 	while (any(*cp, " \t"))
4717c478bd9Sstevel@tonic-gate 		cp++;
4727c478bd9Sstevel@tonic-gate 	cp2 = word;
4737c478bd9Sstevel@tonic-gate 	if (any(*cp, "!|#"))
4747c478bd9Sstevel@tonic-gate 		*cp2++ = *cp++;
4757c478bd9Sstevel@tonic-gate 	else
4767c478bd9Sstevel@tonic-gate 		while (*cp && !any(*cp, " \t0123456789$^.:/-+*'\""))
4777c478bd9Sstevel@tonic-gate 			*cp2++ = *cp++;
4787c478bd9Sstevel@tonic-gate 	*cp2 = '\0';
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	/*
4817c478bd9Sstevel@tonic-gate 	 * Look up the command; if not found, complain.
4827c478bd9Sstevel@tonic-gate 	 * Normally, a blank command would map to the
4837c478bd9Sstevel@tonic-gate 	 * first command in the table; while sourcing,
4847c478bd9Sstevel@tonic-gate 	 * however, we ignore blank lines to eliminate
4857c478bd9Sstevel@tonic-gate 	 * confusion.
4867c478bd9Sstevel@tonic-gate 	 */
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	if (sourcing && equal(word, ""))
4897c478bd9Sstevel@tonic-gate 		return (0);
4907c478bd9Sstevel@tonic-gate 	com = lex(word);
4917c478bd9Sstevel@tonic-gate 	if (com == NONE) {
4927c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Unknown command: \"%s\"\n"), word);
4937c478bd9Sstevel@tonic-gate 		if (loading) {
4947c478bd9Sstevel@tonic-gate 			cond = CANY;
4957c478bd9Sstevel@tonic-gate 			return (1);
4967c478bd9Sstevel@tonic-gate 		}
4977c478bd9Sstevel@tonic-gate 		if (sourcing) {
4987c478bd9Sstevel@tonic-gate 			cond = CANY;
4997c478bd9Sstevel@tonic-gate 			unstack();
5007c478bd9Sstevel@tonic-gate 		}
5017c478bd9Sstevel@tonic-gate 		return (0);
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	/*
5057c478bd9Sstevel@tonic-gate 	 * See if we should execute the command -- if a conditional
5067c478bd9Sstevel@tonic-gate 	 * we always execute it, otherwise, check the state of cond.
5077c478bd9Sstevel@tonic-gate 	 */
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	if ((com->c_argtype & F) == 0)
5107c478bd9Sstevel@tonic-gate 		if (cond == CRCV && !rcvmode || cond == CSEND && rcvmode ||
5117c478bd9Sstevel@tonic-gate 		    cond == CTTY && !intty || cond == CNOTTY && intty)
5127c478bd9Sstevel@tonic-gate 			return (0);
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	/*
5157c478bd9Sstevel@tonic-gate 	 * Special case so that quit causes a return to
5167c478bd9Sstevel@tonic-gate 	 * main, who will call the quit code directly.
5177c478bd9Sstevel@tonic-gate 	 * If we are in a source file, just unstack.
5187c478bd9Sstevel@tonic-gate 	 */
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	if (com->c_func == (int (*)(void *))edstop) {
5217c478bd9Sstevel@tonic-gate 		if (sourcing) {
5227c478bd9Sstevel@tonic-gate 			if (loading)
5237c478bd9Sstevel@tonic-gate 				return (1);
5247c478bd9Sstevel@tonic-gate 			unstack();
5257c478bd9Sstevel@tonic-gate 			return (0);
5267c478bd9Sstevel@tonic-gate 		}
5277c478bd9Sstevel@tonic-gate 		return (1);
5287c478bd9Sstevel@tonic-gate 	}
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	/*
5317c478bd9Sstevel@tonic-gate 	 * Process the arguments to the command, depending
5327c478bd9Sstevel@tonic-gate 	 * on the type he expects.  Default to an error.
5337c478bd9Sstevel@tonic-gate 	 * If we are sourcing an interactive command, it's
5347c478bd9Sstevel@tonic-gate 	 * an error.
5357c478bd9Sstevel@tonic-gate 	 */
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if (!rcvmode && (com->c_argtype & M) == 0) {
5387c478bd9Sstevel@tonic-gate 		fprintf(stderr,
5397c478bd9Sstevel@tonic-gate 		    gettext("May not execute \"%s\" while sending\n"),
5407c478bd9Sstevel@tonic-gate 		    com->c_name);
5417c478bd9Sstevel@tonic-gate 		if (loading)
5427c478bd9Sstevel@tonic-gate 			return (1);
5437c478bd9Sstevel@tonic-gate 		if (sourcing)
5447c478bd9Sstevel@tonic-gate 			unstack();
5457c478bd9Sstevel@tonic-gate 		return (0);
5467c478bd9Sstevel@tonic-gate 	}
5477c478bd9Sstevel@tonic-gate 	if (sourcing && com->c_argtype & I) {
5487c478bd9Sstevel@tonic-gate 		fprintf(stderr,
5497c478bd9Sstevel@tonic-gate 		    gettext("May not execute \"%s\" while sourcing\n"),
5507c478bd9Sstevel@tonic-gate 		    com->c_name);
5517c478bd9Sstevel@tonic-gate 		rpterr = 1;
5527c478bd9Sstevel@tonic-gate 		if (loading)
5537c478bd9Sstevel@tonic-gate 			return (1);
5547c478bd9Sstevel@tonic-gate 		unstack();
5557c478bd9Sstevel@tonic-gate 		return (0);
5567c478bd9Sstevel@tonic-gate 	}
5577c478bd9Sstevel@tonic-gate 	if (readonly && com->c_argtype & W) {
5587c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext(
5597c478bd9Sstevel@tonic-gate 		    "May not execute \"%s\" -- message file is read only\n"),
5607c478bd9Sstevel@tonic-gate 		    com->c_name);
5617c478bd9Sstevel@tonic-gate 		if (loading)
5627c478bd9Sstevel@tonic-gate 			return (1);
5637c478bd9Sstevel@tonic-gate 		if (sourcing)
5647c478bd9Sstevel@tonic-gate 			unstack();
5657c478bd9Sstevel@tonic-gate 		return (0);
5667c478bd9Sstevel@tonic-gate 	}
5677c478bd9Sstevel@tonic-gate 	if (contxt && com->c_argtype & R) {
5687c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Cannot recursively invoke \"%s\"\n"),
5697c478bd9Sstevel@tonic-gate 		    com->c_name);
5707c478bd9Sstevel@tonic-gate 		return (0);
5717c478bd9Sstevel@tonic-gate 	}
5727c478bd9Sstevel@tonic-gate 	e = 1;
5737c478bd9Sstevel@tonic-gate 	switch (com->c_argtype & ~(F|P|I|M|T|W|R)) {
5747c478bd9Sstevel@tonic-gate 	case MSGLIST:
5757c478bd9Sstevel@tonic-gate 		/*
5767c478bd9Sstevel@tonic-gate 		 * A message list defaulting to nearest forward
5777c478bd9Sstevel@tonic-gate 		 * legal message.
5787c478bd9Sstevel@tonic-gate 		 */
5797c478bd9Sstevel@tonic-gate 		if (msgvec == 0) {
5807c478bd9Sstevel@tonic-gate 			fprintf(stderr,
5817c478bd9Sstevel@tonic-gate 			    gettext("Illegal use of \"message list\"\n"));
5827c478bd9Sstevel@tonic-gate 			return (-1);
5837c478bd9Sstevel@tonic-gate 		}
5847c478bd9Sstevel@tonic-gate 		if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0)
5857c478bd9Sstevel@tonic-gate 			break;
5867c478bd9Sstevel@tonic-gate 		if (c  == 0)
5877c478bd9Sstevel@tonic-gate 			if (msgCount == 0)
5887c478bd9Sstevel@tonic-gate 				*msgvec = NULL;
5897c478bd9Sstevel@tonic-gate 			else {
5907c478bd9Sstevel@tonic-gate 				*msgvec = first(com->c_msgflag,
5917c478bd9Sstevel@tonic-gate 					com->c_msgmask);
5927c478bd9Sstevel@tonic-gate 				msgvec[1] = NULL;
5937c478bd9Sstevel@tonic-gate 			}
5947c478bd9Sstevel@tonic-gate 		if (*msgvec == NULL) {
5957c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("No applicable messages\n"));
5967c478bd9Sstevel@tonic-gate 			break;
5977c478bd9Sstevel@tonic-gate 		}
5987c478bd9Sstevel@tonic-gate 		e = (*com->c_func)(msgvec);
5997c478bd9Sstevel@tonic-gate 		break;
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	case NDMLIST:
6027c478bd9Sstevel@tonic-gate 		/*
603*eb2b0a61Sas145665 		 * A message operand with no defaults, but no error
604*eb2b0a61Sas145665 		 * if none exists. There will be an error if the
605*eb2b0a61Sas145665 		 * msgvec pointer is of zero value.
6067c478bd9Sstevel@tonic-gate 		 */
6077c478bd9Sstevel@tonic-gate 		if (msgvec == 0) {
6087c478bd9Sstevel@tonic-gate 			fprintf(stderr,
609*eb2b0a61Sas145665 			    gettext("Illegal use of \"message operand\"\n"));
6107c478bd9Sstevel@tonic-gate 			return (-1);
6117c478bd9Sstevel@tonic-gate 		}
612*eb2b0a61Sas145665 		if (getmessage(cp, msgvec, com->c_msgflag) < 0)
6137c478bd9Sstevel@tonic-gate 			break;
6147c478bd9Sstevel@tonic-gate 		e = (*com->c_func)(msgvec);
6157c478bd9Sstevel@tonic-gate 		break;
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	case STRLIST:
6187c478bd9Sstevel@tonic-gate 		/*
6197c478bd9Sstevel@tonic-gate 		 * Just the straight string, with
6207c478bd9Sstevel@tonic-gate 		 * leading blanks removed.
6217c478bd9Sstevel@tonic-gate 		 */
6227c478bd9Sstevel@tonic-gate 		while (any(*cp, " \t"))
6237c478bd9Sstevel@tonic-gate 			cp++;
6247c478bd9Sstevel@tonic-gate 		e = (*com->c_func)(cp);
6257c478bd9Sstevel@tonic-gate 		break;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	case RAWLIST:
6287c478bd9Sstevel@tonic-gate 		/*
6297c478bd9Sstevel@tonic-gate 		 * A vector of strings, in shell style.
6307c478bd9Sstevel@tonic-gate 		 */
6317c478bd9Sstevel@tonic-gate 		if ((c = getrawlist(cp, arglist,
632*eb2b0a61Sas145665 				sizeof (arglist) / sizeof (*arglist))) < 0)
6337c478bd9Sstevel@tonic-gate 			break;
6347c478bd9Sstevel@tonic-gate 		if (c < com->c_minargs) {
6357c478bd9Sstevel@tonic-gate 			fprintf(stderr,
6367c478bd9Sstevel@tonic-gate 			    gettext("%s requires at least %d arg(s)\n"),
6377c478bd9Sstevel@tonic-gate 			    com->c_name, com->c_minargs);
6387c478bd9Sstevel@tonic-gate 			break;
6397c478bd9Sstevel@tonic-gate 		}
6407c478bd9Sstevel@tonic-gate 		if (c > com->c_maxargs) {
6417c478bd9Sstevel@tonic-gate 			fprintf(stderr,
6427c478bd9Sstevel@tonic-gate 			    gettext("%s takes no more than %d arg(s)\n"),
6437c478bd9Sstevel@tonic-gate 			    com->c_name, com->c_maxargs);
6447c478bd9Sstevel@tonic-gate 			break;
6457c478bd9Sstevel@tonic-gate 		}
6467c478bd9Sstevel@tonic-gate 		e = (*com->c_func)(arglist);
6477c478bd9Sstevel@tonic-gate 		break;
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 	case NOLIST:
6507c478bd9Sstevel@tonic-gate 		/*
6517c478bd9Sstevel@tonic-gate 		 * Just the constant zero, for exiting,
6527c478bd9Sstevel@tonic-gate 		 * eg.
6537c478bd9Sstevel@tonic-gate 		 */
6547c478bd9Sstevel@tonic-gate 		e = (*com->c_func)(0);
6557c478bd9Sstevel@tonic-gate 		break;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	default:
6587c478bd9Sstevel@tonic-gate 		panic("Unknown argtype");
6597c478bd9Sstevel@tonic-gate 	}
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	/*
6627c478bd9Sstevel@tonic-gate 	 * Exit the current source file on
6637c478bd9Sstevel@tonic-gate 	 * error.
6647c478bd9Sstevel@tonic-gate 	 */
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	if (e && loading)
6677c478bd9Sstevel@tonic-gate 		return (1);
6687c478bd9Sstevel@tonic-gate 	if (e && sourcing)
6697c478bd9Sstevel@tonic-gate 		unstack();
6707c478bd9Sstevel@tonic-gate 	if (com->c_func == (int (*)(void *))edstop)
6717c478bd9Sstevel@tonic-gate 		return (1);
6727c478bd9Sstevel@tonic-gate 	if (value("autoprint") != NOSTR && com->c_argtype & P)
6737c478bd9Sstevel@tonic-gate 		if ((dot->m_flag & MDELETED) == 0) {
6747c478bd9Sstevel@tonic-gate 			muvec[0] = dot - &message[0] + 1;
6757c478bd9Sstevel@tonic-gate 			muvec[1] = 0;
6767c478bd9Sstevel@tonic-gate 			type(muvec);
6777c478bd9Sstevel@tonic-gate 		}
6787c478bd9Sstevel@tonic-gate 	if (!sourcing && (com->c_argtype & T) == 0)
6797c478bd9Sstevel@tonic-gate 		sawcom = 1;
6807c478bd9Sstevel@tonic-gate 	return (0);
6817c478bd9Sstevel@tonic-gate }
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate #ifdef SIGCONT
6847c478bd9Sstevel@tonic-gate /*
6857c478bd9Sstevel@tonic-gate  * When we wake up after ^Z, reprint the prompt.
6867c478bd9Sstevel@tonic-gate  */
6877c478bd9Sstevel@tonic-gate static void
6887c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
contin(int)6897c478bd9Sstevel@tonic-gate contin(int)
6907c478bd9Sstevel@tonic-gate #else
6917c478bd9Sstevel@tonic-gate /* ARGSUSED */
6927c478bd9Sstevel@tonic-gate contin(int s)
6937c478bd9Sstevel@tonic-gate #endif
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate 	if (shudprompt)
6967c478bd9Sstevel@tonic-gate 		printf("%s", prompt);
6977c478bd9Sstevel@tonic-gate 	fflush(stdout);
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate #endif
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate /*
7027c478bd9Sstevel@tonic-gate  * Branch here on hangup signal and simulate quit.
7037c478bd9Sstevel@tonic-gate  */
7047c478bd9Sstevel@tonic-gate void
7057c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
hangup(int)7067c478bd9Sstevel@tonic-gate hangup(int)
7077c478bd9Sstevel@tonic-gate #else
7087c478bd9Sstevel@tonic-gate /* ARGSUSED */
7097c478bd9Sstevel@tonic-gate hangup(int s)
7107c478bd9Sstevel@tonic-gate #endif
7117c478bd9Sstevel@tonic-gate {
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	holdsigs();
7147c478bd9Sstevel@tonic-gate #ifdef OLD_BSD_SIGS
7157c478bd9Sstevel@tonic-gate 	sigignore(SIGHUP);
7167c478bd9Sstevel@tonic-gate #endif
7177c478bd9Sstevel@tonic-gate 	if (edit) {
7187c478bd9Sstevel@tonic-gate 		if (setjmp(srbuf))
7197c478bd9Sstevel@tonic-gate 			exit(rpterr);
7207c478bd9Sstevel@tonic-gate 		edstop(0);
7217c478bd9Sstevel@tonic-gate 	} else {
7227c478bd9Sstevel@tonic-gate 		if (issysmbox)
7237c478bd9Sstevel@tonic-gate 			Verhogen();
7247c478bd9Sstevel@tonic-gate 		if (value("exit") != NOSTR)
7257c478bd9Sstevel@tonic-gate 			exit(1);
7267c478bd9Sstevel@tonic-gate 		else
7277c478bd9Sstevel@tonic-gate 			quit(0);
7287c478bd9Sstevel@tonic-gate 	}
7297c478bd9Sstevel@tonic-gate 	exit(rpterr);
7307c478bd9Sstevel@tonic-gate }
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate /*
7337c478bd9Sstevel@tonic-gate  * Set the size of the message vector used to construct argument
7347c478bd9Sstevel@tonic-gate  * lists to message list functions.
7357c478bd9Sstevel@tonic-gate  */
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate static void
setmsize(int sz)7387c478bd9Sstevel@tonic-gate setmsize(int sz)
7397c478bd9Sstevel@tonic-gate {
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	if (msgvec != (int *)0)
7427c478bd9Sstevel@tonic-gate 		free(msgvec);
7437c478bd9Sstevel@tonic-gate 	if (sz < 1)
7447c478bd9Sstevel@tonic-gate 		sz = 1; /* need at least one cell for terminating 0 */
7457c478bd9Sstevel@tonic-gate 	if ((msgvec = (int *)
7467c478bd9Sstevel@tonic-gate 	    calloc((unsigned)(sz + 1), sizeof (*msgvec))) == NULL)
7477c478bd9Sstevel@tonic-gate 		panic("Failed to allocate memory for message vector");
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate /*
7517c478bd9Sstevel@tonic-gate  * Find the correct command in the command table corresponding
7527c478bd9Sstevel@tonic-gate  * to the passed command "word"
7537c478bd9Sstevel@tonic-gate  */
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate static const struct cmd *
lex(char word[])7567c478bd9Sstevel@tonic-gate lex(char word[])
7577c478bd9Sstevel@tonic-gate {
7587c478bd9Sstevel@tonic-gate 	register const struct cmd *cp;
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	for (cp = &cmdtab[0]; cp->c_name != NOSTR; cp++)
7617c478bd9Sstevel@tonic-gate 		if (isprefix(word, cp->c_name))
7627c478bd9Sstevel@tonic-gate 			return (cp);
7637c478bd9Sstevel@tonic-gate 	return (NONE);
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate /*
7677c478bd9Sstevel@tonic-gate  * Determine if as1 is a valid prefix of as2.
7687c478bd9Sstevel@tonic-gate  */
7697c478bd9Sstevel@tonic-gate static int
isprefix(char * as1,char * as2)7707c478bd9Sstevel@tonic-gate isprefix(char *as1, char *as2)
7717c478bd9Sstevel@tonic-gate {
7727c478bd9Sstevel@tonic-gate 	register char *s1, *s2;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	s1 = as1;
7757c478bd9Sstevel@tonic-gate 	s2 = as2;
7767c478bd9Sstevel@tonic-gate 	while (*s1++ == *s2)
7777c478bd9Sstevel@tonic-gate 		if (*s2++ == '\0')
7787c478bd9Sstevel@tonic-gate 			return (1);
7797c478bd9Sstevel@tonic-gate 	return (*--s1 == '\0');
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate /*
7837c478bd9Sstevel@tonic-gate  * The following gets called on receipt of a rubout.  This is
7847c478bd9Sstevel@tonic-gate  * to abort printout of a command, mainly.
7857c478bd9Sstevel@tonic-gate  * Dispatching here when command() is inactive crashes rcv.
7867c478bd9Sstevel@tonic-gate  * Close all open files except 0, 1, 2, and the temporary.
7877c478bd9Sstevel@tonic-gate  * The special call to getuserid() is needed so it won't get
7887c478bd9Sstevel@tonic-gate  * annoyed about losing its open file.
7897c478bd9Sstevel@tonic-gate  * Also, unstack all source files.
7907c478bd9Sstevel@tonic-gate  */
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate static int	inithdr;		/* am printing startup headers */
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate void
stop(int s)7957c478bd9Sstevel@tonic-gate stop(int s)
7967c478bd9Sstevel@tonic-gate {
7977c478bd9Sstevel@tonic-gate 	register NODE *head;
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	noreset = 0;
8007c478bd9Sstevel@tonic-gate 	if (!inithdr)
8017c478bd9Sstevel@tonic-gate 		sawcom++;
8027c478bd9Sstevel@tonic-gate 	inithdr = 0;
8037c478bd9Sstevel@tonic-gate 	while (sourcing)
8047c478bd9Sstevel@tonic-gate 		unstack();
805*eb2b0a61Sas145665 	(void) getuserid((char *)0);
8067c478bd9Sstevel@tonic-gate 	for (head = fplist; head != (NODE *)NULL; head = head->next) {
8077c478bd9Sstevel@tonic-gate 		if (head->fp == stdin || head->fp == stdout)
8087c478bd9Sstevel@tonic-gate 			continue;
8097c478bd9Sstevel@tonic-gate 		if (head->fp == itf || head->fp == otf)
8107c478bd9Sstevel@tonic-gate 			continue;
8117c478bd9Sstevel@tonic-gate 		if (head->fp == stderr)
8127c478bd9Sstevel@tonic-gate 			continue;
8137c478bd9Sstevel@tonic-gate 		if (head->fp == semfp)
8147c478bd9Sstevel@tonic-gate 			continue;
8157c478bd9Sstevel@tonic-gate 		if (head->fp == pipef) {
8167c478bd9Sstevel@tonic-gate 			npclose(pipef);
8177c478bd9Sstevel@tonic-gate 			pipef = NULL;
8187c478bd9Sstevel@tonic-gate 			continue;
8197c478bd9Sstevel@tonic-gate 		}
8207c478bd9Sstevel@tonic-gate 		fclose(head->fp);
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 	if (image >= 0) {
8237c478bd9Sstevel@tonic-gate 		close(image);
8247c478bd9Sstevel@tonic-gate 		image = -1;
8257c478bd9Sstevel@tonic-gate 	}
8267c478bd9Sstevel@tonic-gate 	if (s) {
8277c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Interrupt\n"));
8287c478bd9Sstevel@tonic-gate 		fflush(stderr);
8297c478bd9Sstevel@tonic-gate #ifdef OLD_BSD_SIGS
8307c478bd9Sstevel@tonic-gate 		sigrelse(s);
8317c478bd9Sstevel@tonic-gate #endif
8327c478bd9Sstevel@tonic-gate 	}
8337c478bd9Sstevel@tonic-gate 	longjmp(srbuf, 1);
8347c478bd9Sstevel@tonic-gate }
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate /*
8377c478bd9Sstevel@tonic-gate  * Announce the presence of the current mailx version,
8387c478bd9Sstevel@tonic-gate  * give the message count, and print a header listing.
8397c478bd9Sstevel@tonic-gate  */
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate #define	GREETING	"%s  Type ? for help.\n"
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate void
announce(void)8447c478bd9Sstevel@tonic-gate announce(void)
8457c478bd9Sstevel@tonic-gate {
8467c478bd9Sstevel@tonic-gate 	int vec[2], mdot;
8477c478bd9Sstevel@tonic-gate 	extern const char *const version;
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	if (!Hflag && value("quiet") == NOSTR)
8507c478bd9Sstevel@tonic-gate 		printf(gettext(GREETING), version);
8517c478bd9Sstevel@tonic-gate 	mdot = newfileinfo(1);
8527c478bd9Sstevel@tonic-gate 	vec[0] = mdot;
8537c478bd9Sstevel@tonic-gate 	vec[1] = 0;
8547c478bd9Sstevel@tonic-gate 	dot = &message[mdot - 1];
8557c478bd9Sstevel@tonic-gate 	if (msgCount > 0 && !noheader) {
8567c478bd9Sstevel@tonic-gate 		inithdr++;
8577c478bd9Sstevel@tonic-gate 		headers(vec);
8587c478bd9Sstevel@tonic-gate 		inithdr = 0;
8597c478bd9Sstevel@tonic-gate 	}
8607c478bd9Sstevel@tonic-gate }
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate /*
8637c478bd9Sstevel@tonic-gate  * Announce information about the file we are editing.
8647c478bd9Sstevel@tonic-gate  * Return a likely place to set dot.
8657c478bd9Sstevel@tonic-gate  */
8667c478bd9Sstevel@tonic-gate int
newfileinfo(int start)8677c478bd9Sstevel@tonic-gate newfileinfo(int start)
8687c478bd9Sstevel@tonic-gate {
8697c478bd9Sstevel@tonic-gate 	register struct message *mp;
8707c478bd9Sstevel@tonic-gate 	register int u, n, mdot, d, s;
8717c478bd9Sstevel@tonic-gate 	char fname[BUFSIZ], zname[BUFSIZ], *ename;
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 	if (Hflag)
8747c478bd9Sstevel@tonic-gate 		return (1);		/* fake it--return message 1 */
8757c478bd9Sstevel@tonic-gate 	for (mp = &message[start - 1]; mp < &message[msgCount]; mp++)
8767c478bd9Sstevel@tonic-gate 		if ((mp->m_flag & (MNEW|MREAD)) == MNEW)
8777c478bd9Sstevel@tonic-gate 			break;
8787c478bd9Sstevel@tonic-gate 	if (mp >= &message[msgCount])
8797c478bd9Sstevel@tonic-gate 		for (mp = &message[start - 1]; mp < &message[msgCount]; mp++)
8807c478bd9Sstevel@tonic-gate 			if ((mp->m_flag & MREAD) == 0)
8817c478bd9Sstevel@tonic-gate 				break;
8827c478bd9Sstevel@tonic-gate 	if (mp < &message[msgCount])
8837c478bd9Sstevel@tonic-gate 		mdot = mp - &message[0] + 1;
8847c478bd9Sstevel@tonic-gate 	else
8857c478bd9Sstevel@tonic-gate 		mdot = 1;
8867c478bd9Sstevel@tonic-gate 	n = u = d = s = 0;
8877c478bd9Sstevel@tonic-gate 	for (mp = &message[start - 1]; mp < &message[msgCount]; mp++) {
8887c478bd9Sstevel@tonic-gate 		if (mp->m_flag & MNEW)
8897c478bd9Sstevel@tonic-gate 			n++;
8907c478bd9Sstevel@tonic-gate 		if ((mp->m_flag & MREAD) == 0)
8917c478bd9Sstevel@tonic-gate 			u++;
8927c478bd9Sstevel@tonic-gate 		if (mp->m_flag & MDELETED)
8937c478bd9Sstevel@tonic-gate 			d++;
8947c478bd9Sstevel@tonic-gate 		if (mp->m_flag & MSAVED)
8957c478bd9Sstevel@tonic-gate 			s++;
8967c478bd9Sstevel@tonic-gate 	}
8977c478bd9Sstevel@tonic-gate 	ename = origname;
8987c478bd9Sstevel@tonic-gate 	if (getfold(fname) >= 0) {
8997c478bd9Sstevel@tonic-gate 		nstrcat(fname, sizeof (fname), "/");
9007c478bd9Sstevel@tonic-gate 		if (strncmp(fname, editfile, strlen(fname)) == 0) {
9017c478bd9Sstevel@tonic-gate 			snprintf(zname, sizeof (zname),
9027c478bd9Sstevel@tonic-gate 				"+%s", editfile + strlen(fname));
9037c478bd9Sstevel@tonic-gate 			ename = zname;
9047c478bd9Sstevel@tonic-gate 		}
9057c478bd9Sstevel@tonic-gate 	}
9067c478bd9Sstevel@tonic-gate 	printf("\"%s\": ", ename);
9077c478bd9Sstevel@tonic-gate 	if (msgCount == 1)
9087c478bd9Sstevel@tonic-gate 		printf(gettext("1 message"));
9097c478bd9Sstevel@tonic-gate 	else
9107c478bd9Sstevel@tonic-gate 		printf(gettext("%d messages"), msgCount);
9117c478bd9Sstevel@tonic-gate 	if (n > 0)
9127c478bd9Sstevel@tonic-gate 		printf(gettext(" %d new"), n);
9137c478bd9Sstevel@tonic-gate 	if (u-n > 0)
9147c478bd9Sstevel@tonic-gate 		printf(gettext(" %d unread"), u);
9157c478bd9Sstevel@tonic-gate 	if (d > 0)
9167c478bd9Sstevel@tonic-gate 		printf(gettext(" %d deleted"), d);
9177c478bd9Sstevel@tonic-gate 	if (s > 0)
9187c478bd9Sstevel@tonic-gate 		printf(gettext(" %d saved"), s);
9197c478bd9Sstevel@tonic-gate 	if (readonly)
9207c478bd9Sstevel@tonic-gate 		printf(gettext(" [Read only]"));
9217c478bd9Sstevel@tonic-gate 	printf("\n");
9227c478bd9Sstevel@tonic-gate 	return (mdot);
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate /*
9267c478bd9Sstevel@tonic-gate  * Print the current version number.
9277c478bd9Sstevel@tonic-gate  */
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate int
9307c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
pversion(char *)9317c478bd9Sstevel@tonic-gate pversion(char *)
9327c478bd9Sstevel@tonic-gate #else
9337c478bd9Sstevel@tonic-gate /* ARGSUSED */
9347c478bd9Sstevel@tonic-gate pversion(char *s)
9357c478bd9Sstevel@tonic-gate #endif
9367c478bd9Sstevel@tonic-gate {
9377c478bd9Sstevel@tonic-gate 	printf("%s\n", version);
9387c478bd9Sstevel@tonic-gate 	return (0);
9397c478bd9Sstevel@tonic-gate }
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate /*
9427c478bd9Sstevel@tonic-gate  * Load a file of user definitions.
9437c478bd9Sstevel@tonic-gate  */
9447c478bd9Sstevel@tonic-gate void
load(char * name)9457c478bd9Sstevel@tonic-gate load(char *name)
9467c478bd9Sstevel@tonic-gate {
9477c478bd9Sstevel@tonic-gate 	register FILE *in, *oldin;
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	if ((in = fopen(name, "r")) == NULL)
9507c478bd9Sstevel@tonic-gate 		return;
9517c478bd9Sstevel@tonic-gate 	oldin = input;
9527c478bd9Sstevel@tonic-gate 	input = in;
9537c478bd9Sstevel@tonic-gate 	loading = 1;
9547c478bd9Sstevel@tonic-gate 	sourcing = 1;
9557c478bd9Sstevel@tonic-gate 	commands();
9567c478bd9Sstevel@tonic-gate 	loading = 0;
9577c478bd9Sstevel@tonic-gate 	sourcing = 0;
9587c478bd9Sstevel@tonic-gate 	input = oldin;
9597c478bd9Sstevel@tonic-gate 	fclose(in);
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate /*
9637c478bd9Sstevel@tonic-gate  * Incorporate any new mail into the current session.
9647c478bd9Sstevel@tonic-gate  *
9657c478bd9Sstevel@tonic-gate  * XXX - Since autoinc works on "edited" files as well as the
9667c478bd9Sstevel@tonic-gate  * system mailbox, this probably ought to as well.
9677c478bd9Sstevel@tonic-gate  */
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate int
inc(void)9707c478bd9Sstevel@tonic-gate inc(void)
9717c478bd9Sstevel@tonic-gate {
9727c478bd9Sstevel@tonic-gate 	FILE *ibuf;
9737c478bd9Sstevel@tonic-gate 	int mdot;
9747c478bd9Sstevel@tonic-gate 	struct stat stbuf;
9757c478bd9Sstevel@tonic-gate 	int firstnewmsg = msgCount + 1;
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 	if (edit) {
9787c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Not in system mailbox\n"));
9797c478bd9Sstevel@tonic-gate 		return (-1);
9807c478bd9Sstevel@tonic-gate 	}
9817c478bd9Sstevel@tonic-gate 	if (((ibuf = fopen(mailname, "r")) == NULL) ||
9827c478bd9Sstevel@tonic-gate 	    (fstat(fileno(ibuf), &stbuf) < 0) || stbuf.st_size == 0L ||
9837c478bd9Sstevel@tonic-gate 	    stbuf.st_size == mailsize || (stbuf.st_mode&S_IFMT) != S_IFREG) {
9847c478bd9Sstevel@tonic-gate 		if (strrchr(mailname, '/') == NOSTR)
9857c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("No new mail.\n"));
9867c478bd9Sstevel@tonic-gate 		else
9877c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("No new mail for %s\n"),
9887c478bd9Sstevel@tonic-gate 			    strrchr(mailname, '/')+1);
9897c478bd9Sstevel@tonic-gate 		if (ibuf != NULL)
9907c478bd9Sstevel@tonic-gate 			fclose(ibuf);
9917c478bd9Sstevel@tonic-gate 		return (-1);
9927c478bd9Sstevel@tonic-gate 	}
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 	fseek(otf, 0L, 2);
9957c478bd9Sstevel@tonic-gate 	holdsigs();
9967c478bd9Sstevel@tonic-gate 	if (issysmbox)
9977c478bd9Sstevel@tonic-gate 		lockmail();
9987c478bd9Sstevel@tonic-gate 	fseek(ibuf, mailsize, 0);
9997c478bd9Sstevel@tonic-gate 	mailsize = fsize(ibuf);
10007c478bd9Sstevel@tonic-gate 	setptr(ibuf);
10017c478bd9Sstevel@tonic-gate 	setmsize(msgCount);
10027c478bd9Sstevel@tonic-gate 	fclose(ibuf);
10037c478bd9Sstevel@tonic-gate 	if (issysmbox)
10047c478bd9Sstevel@tonic-gate 		unlockmail();
10057c478bd9Sstevel@tonic-gate 	relsesigs();
10067c478bd9Sstevel@tonic-gate 	mdot = newfileinfo(firstnewmsg);
10077c478bd9Sstevel@tonic-gate 	dot = &message[mdot - 1];
10087c478bd9Sstevel@tonic-gate 	sawcom = 0;
10097c478bd9Sstevel@tonic-gate 	return (0);
10107c478bd9Sstevel@tonic-gate }
1011