xref: /illumos-gate/usr/src/cmd/vi/port/ex.c (revision 68c92b9f)
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*68c92b9fScf  * Common Development and Distribution License (the "License").
6*68c92b9fScf  * 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 /*
22*68c92b9fScf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include "ex.h"
347c478bd9Sstevel@tonic-gate #include "ex_argv.h"
357c478bd9Sstevel@tonic-gate #include "ex_temp.h"
367c478bd9Sstevel@tonic-gate #include "ex_tty.h"
377c478bd9Sstevel@tonic-gate #include <stdlib.h>
387c478bd9Sstevel@tonic-gate #include <locale.h>
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #ifdef TRACE
417c478bd9Sstevel@tonic-gate unsigned char	tttrace[BUFSIZ];
427c478bd9Sstevel@tonic-gate #endif
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #define	EQ(a, b)	(strcmp(a, b) == 0)
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate char	*strrchr();
477c478bd9Sstevel@tonic-gate void	init_re(void);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * The code for ex is divided as follows:
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  * ex.c			Entry point and routines handling interrupt, hangup
537c478bd9Sstevel@tonic-gate  *			signals; initialization code.
547c478bd9Sstevel@tonic-gate  *
557c478bd9Sstevel@tonic-gate  * ex_addr.c		Address parsing routines for command mode decoding.
567c478bd9Sstevel@tonic-gate  *			Routines to set and check address ranges on commands.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  * ex_cmds.c		Command mode command decoding.
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * ex_cmds2.c		Subroutines for command decoding and processing of
617c478bd9Sstevel@tonic-gate  *			file names in the argument list.  Routines to print
627c478bd9Sstevel@tonic-gate  *			messages and reset state when errors occur.
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  * ex_cmdsub.c		Subroutines which implement command mode functions
657c478bd9Sstevel@tonic-gate  *			such as append, delete, join.
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  * ex_data.c		Initialization of options.
687c478bd9Sstevel@tonic-gate  *
697c478bd9Sstevel@tonic-gate  * ex_get.c		Command mode input routines.
707c478bd9Sstevel@tonic-gate  *
717c478bd9Sstevel@tonic-gate  * ex_io.c		General input/output processing: file i/o, unix
727c478bd9Sstevel@tonic-gate  *			escapes, filtering, source commands, preserving
737c478bd9Sstevel@tonic-gate  *			and recovering.
747c478bd9Sstevel@tonic-gate  *
757c478bd9Sstevel@tonic-gate  * ex_put.c		Terminal driving and optimizing routines for low-level
767c478bd9Sstevel@tonic-gate  *			output (cursor-positioning); output line formatting
777c478bd9Sstevel@tonic-gate  *			routines.
787c478bd9Sstevel@tonic-gate  *
797c478bd9Sstevel@tonic-gate  * ex_re.c		Global commands, substitute, regular expression
807c478bd9Sstevel@tonic-gate  *			compilation and execution.
817c478bd9Sstevel@tonic-gate  *
827c478bd9Sstevel@tonic-gate  * ex_set.c		The set command.
837c478bd9Sstevel@tonic-gate  *
847c478bd9Sstevel@tonic-gate  * ex_subr.c		Loads of miscellaneous subroutines.
857c478bd9Sstevel@tonic-gate  *
867c478bd9Sstevel@tonic-gate  * ex_temp.c		Editor buffer routines for main buffer and also
877c478bd9Sstevel@tonic-gate  *			for named buffers (Q registers if you will.)
887c478bd9Sstevel@tonic-gate  *
897c478bd9Sstevel@tonic-gate  * ex_tty.c		Terminal dependent initializations from termcap
907c478bd9Sstevel@tonic-gate  *			data base, grabbing of tty modes (at beginning
917c478bd9Sstevel@tonic-gate  *			and after escapes).
927c478bd9Sstevel@tonic-gate  *
937c478bd9Sstevel@tonic-gate  * ex_unix.c		Routines for the ! command and its variations.
947c478bd9Sstevel@tonic-gate  *
957c478bd9Sstevel@tonic-gate  * ex_v*.c		Visual/open mode routines... see ex_v.c for a
967c478bd9Sstevel@tonic-gate  *			guide to the overall organization.
977c478bd9Sstevel@tonic-gate  */
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate  * This sets the Version of ex/vi for both the exstrings file and
1017c478bd9Sstevel@tonic-gate  * the version command (":ver").
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate /* variable used by ":ver" command */
1057c478bd9Sstevel@tonic-gate unsigned char *Version = (unsigned char *)"Version SVR4.0, Solaris 2.5.0";
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * NOTE: when changing the Version number, it must be changed in the
1097c478bd9Sstevel@tonic-gate  *	 following files:
1107c478bd9Sstevel@tonic-gate  *
1117c478bd9Sstevel@tonic-gate  *			  port/READ_ME
1127c478bd9Sstevel@tonic-gate  *			  port/ex.c
1137c478bd9Sstevel@tonic-gate  *			  port/ex.news
1147c478bd9Sstevel@tonic-gate  *
1157c478bd9Sstevel@tonic-gate  */
1167c478bd9Sstevel@tonic-gate #ifdef XPG4
1177c478bd9Sstevel@tonic-gate unsigned char *savepat = (unsigned char *) NULL; /* firstpat storage	*/
1187c478bd9Sstevel@tonic-gate #endif /* XPG4 */
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate /*
1217c478bd9Sstevel@tonic-gate  * Main procedure.  Process arguments and then
1227c478bd9Sstevel@tonic-gate  * transfer control to the main command processing loop
1237c478bd9Sstevel@tonic-gate  * in the routine commands.  We are entered as either "ex", "edit", "vi"
1247c478bd9Sstevel@tonic-gate  * or "view" and the distinction is made here. For edit we just diddle options;
1257c478bd9Sstevel@tonic-gate  * for vi we actually force an early visual command.
1267c478bd9Sstevel@tonic-gate  */
1277c478bd9Sstevel@tonic-gate static unsigned char cryptkey[19]; /* contents of encryption key */
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate static void usage(unsigned char *);
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate static int validate_exrc(unsigned char *);
1327c478bd9Sstevel@tonic-gate 
133f6db9f27Scf void init(void);
134f6db9f27Scf 
1357c478bd9Sstevel@tonic-gate int
136f6db9f27Scf main(int ac, char *av[])
1377c478bd9Sstevel@tonic-gate {
1387c478bd9Sstevel@tonic-gate 	extern 	char 	*optarg;
1397c478bd9Sstevel@tonic-gate 	extern 	int	optind;
1407c478bd9Sstevel@tonic-gate 	unsigned char	*rcvname = 0;
1417c478bd9Sstevel@tonic-gate 	unsigned char *cp;
1427c478bd9Sstevel@tonic-gate 	int c;
1437c478bd9Sstevel@tonic-gate 	unsigned char	*cmdnam;
1447c478bd9Sstevel@tonic-gate 	bool recov = 0;
1457c478bd9Sstevel@tonic-gate 	bool ivis = 0;
1467c478bd9Sstevel@tonic-gate 	bool itag = 0;
1477c478bd9Sstevel@tonic-gate 	bool fast = 0;
1487c478bd9Sstevel@tonic-gate 	extern int verbose;
1497c478bd9Sstevel@tonic-gate 	int argcounter = 0;
1507c478bd9Sstevel@tonic-gate 	extern int tags_flag;	/* Set if tag file is not sorted (-S flag) */
1517c478bd9Sstevel@tonic-gate 	unsigned char scratch [PATH_MAX+1];   /* temp for sourcing rc file(s) */
1527c478bd9Sstevel@tonic-gate 	int vret = 0;
1537c478bd9Sstevel@tonic-gate 	unsigned char exrcpath [PATH_MAX+1]; /* temp for sourcing rc file(s) */
1547c478bd9Sstevel@tonic-gate 	int toptseen = 0;
1557c478bd9Sstevel@tonic-gate #ifdef TRACE
1567c478bd9Sstevel@tonic-gate 	unsigned char *tracef;
1577c478bd9Sstevel@tonic-gate #endif
158*68c92b9fScf 	tagflg = 0;
1597c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1607c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1617c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
1627c478bd9Sstevel@tonic-gate #endif
1637c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	/*
1667c478bd9Sstevel@tonic-gate 	 * Immediately grab the tty modes so that we won't
1677c478bd9Sstevel@tonic-gate 	 * get messed up if an interrupt comes in quickly.
1687c478bd9Sstevel@tonic-gate 	 */
169f6db9f27Scf 	(void) gTTY(2);
1707c478bd9Sstevel@tonic-gate 	normf = tty;
1717c478bd9Sstevel@tonic-gate 	ppid = getpid();
1727c478bd9Sstevel@tonic-gate 	/* Note - this will core dump if you didn't -DSINGLE in CFLAGS */
1737c478bd9Sstevel@tonic-gate 	lines = 24;
1747c478bd9Sstevel@tonic-gate 	columns = 80;	/* until defined right by setupterm */
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 * Defend against d's, v's, w's, and a's in directories of
1777c478bd9Sstevel@tonic-gate 	 * path leading to our true name.
1787c478bd9Sstevel@tonic-gate 	 */
1797c478bd9Sstevel@tonic-gate 	if ((cmdnam = (unsigned char *)strrchr(av[0], '/')) != 0)
1807c478bd9Sstevel@tonic-gate 		cmdnam++;
1817c478bd9Sstevel@tonic-gate 	else
182f6db9f27Scf 		cmdnam = (unsigned char *)av[0];
1837c478bd9Sstevel@tonic-gate 
184f6db9f27Scf 	if (EQ((char *)cmdnam, "vi"))
1857c478bd9Sstevel@tonic-gate 		ivis = 1;
1867c478bd9Sstevel@tonic-gate 	else if (EQ(cmdnam, "view")) {
1877c478bd9Sstevel@tonic-gate 		ivis = 1;
1887c478bd9Sstevel@tonic-gate 		value(vi_READONLY) = 1;
1897c478bd9Sstevel@tonic-gate 	} else if (EQ(cmdnam, "vedit")) {
1907c478bd9Sstevel@tonic-gate 		ivis = 1;
1917c478bd9Sstevel@tonic-gate 		value(vi_NOVICE) = 1;
1927c478bd9Sstevel@tonic-gate 		value(vi_REPORT) = 1;
1937c478bd9Sstevel@tonic-gate 		value(vi_MAGIC) = 0;
1947c478bd9Sstevel@tonic-gate 		value(vi_SHOWMODE) = 1;
1957c478bd9Sstevel@tonic-gate 	} else if (EQ(cmdnam, "edit")) {
1967c478bd9Sstevel@tonic-gate 		value(vi_NOVICE) = 1;
1977c478bd9Sstevel@tonic-gate 		value(vi_REPORT) = 1;
1987c478bd9Sstevel@tonic-gate 		value(vi_MAGIC) = 0;
1997c478bd9Sstevel@tonic-gate 		value(vi_SHOWMODE) = 1;
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate #ifdef	XPG4
2037c478bd9Sstevel@tonic-gate 	{
2047c478bd9Sstevel@tonic-gate 		struct winsize jwin;
2057c478bd9Sstevel@tonic-gate 		char *envptr;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 		envlines = envcolumns = -1;
2087c478bd9Sstevel@tonic-gate 		oldlines = oldcolumns = -1;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 		if (ioctl(0, TIOCGWINSZ, &jwin) != -1) {
2117c478bd9Sstevel@tonic-gate 			oldlines = jwin.ws_row;
2127c478bd9Sstevel@tonic-gate 			oldcolumns = jwin.ws_col;
2137c478bd9Sstevel@tonic-gate 		}
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 		if ((envptr = getenv("LINES")) != NULL &&
2167c478bd9Sstevel@tonic-gate 		    *envptr != '\0' && isdigit(*envptr)) {
2177c478bd9Sstevel@tonic-gate 			if ((envlines = atoi(envptr)) <= 0) {
2187c478bd9Sstevel@tonic-gate 				envlines = -1;
2197c478bd9Sstevel@tonic-gate 			}
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 		if ((envptr = getenv("COLUMNS")) != NULL &&
2237c478bd9Sstevel@tonic-gate 		    *envptr != '\0' && isdigit(*envptr)) {
2247c478bd9Sstevel@tonic-gate 			if ((envcolumns = atoi(envptr)) <= 0) {
2257c478bd9Sstevel@tonic-gate 				envcolumns = -1;
2267c478bd9Sstevel@tonic-gate 			}
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate #endif /* XPG4 */
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	draino();
2327c478bd9Sstevel@tonic-gate 	pstop();
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	/*
2357c478bd9Sstevel@tonic-gate 	 * Initialize interrupt handling.
2367c478bd9Sstevel@tonic-gate 	 */
2377c478bd9Sstevel@tonic-gate 	oldhup = signal(SIGHUP, SIG_IGN);
2387c478bd9Sstevel@tonic-gate 	if (oldhup == SIG_DFL)
2397c478bd9Sstevel@tonic-gate 		signal(SIGHUP, onhup);
2407c478bd9Sstevel@tonic-gate 	oldquit = signal(SIGQUIT, SIG_IGN);
2417c478bd9Sstevel@tonic-gate 	ruptible = signal(SIGINT, SIG_IGN) == SIG_DFL;
2427c478bd9Sstevel@tonic-gate 	if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
2437c478bd9Sstevel@tonic-gate 		signal(SIGTERM, onhup);
2447c478bd9Sstevel@tonic-gate 	if (signal(SIGEMT, SIG_IGN) == SIG_DFL)
2457c478bd9Sstevel@tonic-gate 		signal(SIGEMT, onemt);
2467c478bd9Sstevel@tonic-gate 	signal(SIGILL, oncore);
2477c478bd9Sstevel@tonic-gate 	signal(SIGTRAP, oncore);
2487c478bd9Sstevel@tonic-gate 	signal(SIGIOT, oncore);
2497c478bd9Sstevel@tonic-gate 	signal(SIGFPE, oncore);
2507c478bd9Sstevel@tonic-gate 	signal(SIGBUS, oncore);
2517c478bd9Sstevel@tonic-gate 	signal(SIGSEGV, oncore);
2527c478bd9Sstevel@tonic-gate 	signal(SIGPIPE, oncore);
2537c478bd9Sstevel@tonic-gate 	init_re();
2547c478bd9Sstevel@tonic-gate 	while (1) {
2557c478bd9Sstevel@tonic-gate #ifdef TRACE
2567c478bd9Sstevel@tonic-gate 		while ((c = getopt(ac, (char **)av, "VU:Lc:Tvt:rlw:xRCsS")) !=
2577c478bd9Sstevel@tonic-gate 		    EOF)
2587c478bd9Sstevel@tonic-gate #else
2597c478bd9Sstevel@tonic-gate 		while ((c = getopt(ac, (char **)av,
260a1d23db4Sceastha 		    "VLc:vt:rlw:xRCsS")) != EOF)
2617c478bd9Sstevel@tonic-gate #endif
2627c478bd9Sstevel@tonic-gate 			switch (c) {
2637c478bd9Sstevel@tonic-gate 			case 's':
2647c478bd9Sstevel@tonic-gate 				hush = 1;
2657c478bd9Sstevel@tonic-gate 				value(vi_AUTOPRINT) = 0;
2667c478bd9Sstevel@tonic-gate 				fast++;
2677c478bd9Sstevel@tonic-gate 				break;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 			case 'R':
2707c478bd9Sstevel@tonic-gate 				value(vi_READONLY) = 1;
2717c478bd9Sstevel@tonic-gate 				break;
2727c478bd9Sstevel@tonic-gate 			case 'S':
2737c478bd9Sstevel@tonic-gate 				tags_flag = 1;
2747c478bd9Sstevel@tonic-gate 				break;
2757c478bd9Sstevel@tonic-gate #ifdef TRACE
2767c478bd9Sstevel@tonic-gate 			case 'T':
2777c478bd9Sstevel@tonic-gate 				tracef = (unsigned char *)"trace";
2787c478bd9Sstevel@tonic-gate 				goto trace;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 			case 'U':
2817c478bd9Sstevel@tonic-gate 				tracef = tttrace;
2827c478bd9Sstevel@tonic-gate 				strcpy(tracef, optarg);
2837c478bd9Sstevel@tonic-gate 		trace:
2847c478bd9Sstevel@tonic-gate 				trace = fopen((char *)tracef, "w");
2857c478bd9Sstevel@tonic-gate #define	tracbuf	NULL
2867c478bd9Sstevel@tonic-gate 				if (trace == NULL)
287f6db9f27Scf 					viprintf("Trace create error\n");
2887c478bd9Sstevel@tonic-gate 				else
2897c478bd9Sstevel@tonic-gate 					setbuf(trace, (char *)tracbuf);
2907c478bd9Sstevel@tonic-gate 				break;
2917c478bd9Sstevel@tonic-gate #endif
2927c478bd9Sstevel@tonic-gate 			case 'c':
2937c478bd9Sstevel@tonic-gate 				if (optarg != NULL)
2947c478bd9Sstevel@tonic-gate 					firstpat = (unsigned char *)optarg;
2957c478bd9Sstevel@tonic-gate 				else
2967c478bd9Sstevel@tonic-gate 					firstpat = (unsigned char *)"";
2977c478bd9Sstevel@tonic-gate 				break;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 			case 'l':
3007c478bd9Sstevel@tonic-gate 				value(vi_LISP) = 1;
3017c478bd9Sstevel@tonic-gate 				value(vi_SHOWMATCH) = 1;
3027c478bd9Sstevel@tonic-gate 				break;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 			case 'r':
3057c478bd9Sstevel@tonic-gate 				if (av[optind] && (c = av[optind][0]) &&
3067c478bd9Sstevel@tonic-gate 				    c != '-') {
3077c478bd9Sstevel@tonic-gate 					if ((strlen(av[optind])) >=
3087c478bd9Sstevel@tonic-gate 					    sizeof (savedfile)) {
3097c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr, gettext(
310a1d23db4Sceastha 						    "Recovered file name"
311a1d23db4Sceastha 						    " too long\n"));
3127c478bd9Sstevel@tonic-gate 						exit(1);
3137c478bd9Sstevel@tonic-gate 					}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 					rcvname = (unsigned char *)av[optind];
3167c478bd9Sstevel@tonic-gate 					optind++;
3177c478bd9Sstevel@tonic-gate 				}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 			case 'L':
3207c478bd9Sstevel@tonic-gate 				recov++;
3217c478bd9Sstevel@tonic-gate 				break;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 			case 'V':
3247c478bd9Sstevel@tonic-gate 				verbose = 1;
3257c478bd9Sstevel@tonic-gate 				break;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 			case 't':
3287c478bd9Sstevel@tonic-gate 				if (toptseen) {
3297c478bd9Sstevel@tonic-gate 					usage(cmdnam);
3307c478bd9Sstevel@tonic-gate 					exit(1);
3317c478bd9Sstevel@tonic-gate 				} else {
3327c478bd9Sstevel@tonic-gate 					toptseen++;
3337c478bd9Sstevel@tonic-gate 				}
334*68c92b9fScf 				itag = tagflg = 1; /* -t option */
3357c478bd9Sstevel@tonic-gate 				if (strlcpy(lasttag, optarg,
3367c478bd9Sstevel@tonic-gate 				    sizeof (lasttag)) >= sizeof (lasttag)) {
3377c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, gettext("Tag"
3387c478bd9Sstevel@tonic-gate 					    " file name too long\n"));
3397c478bd9Sstevel@tonic-gate 					exit(1);
3407c478bd9Sstevel@tonic-gate 				}
3417c478bd9Sstevel@tonic-gate 				break;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 			case 'w':
3447c478bd9Sstevel@tonic-gate 				defwind = 0;
3457c478bd9Sstevel@tonic-gate 				if (optarg[0] == NULL)
3467c478bd9Sstevel@tonic-gate 					defwind = 3;
3477c478bd9Sstevel@tonic-gate 				else for (cp = (unsigned char *)optarg;
3487c478bd9Sstevel@tonic-gate 				    isdigit(*cp); cp++)
3497c478bd9Sstevel@tonic-gate 					defwind = 10*defwind + *cp - '0';
3507c478bd9Sstevel@tonic-gate 				if (defwind < 0)
3517c478bd9Sstevel@tonic-gate 					defwind = 3;
3527c478bd9Sstevel@tonic-gate 				break;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 			case 'C':
3557c478bd9Sstevel@tonic-gate 				crflag = 1;
3567c478bd9Sstevel@tonic-gate 				xflag = 1;
3577c478bd9Sstevel@tonic-gate 				break;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 			case 'x':
3607c478bd9Sstevel@tonic-gate 				/* encrypted mode */
3617c478bd9Sstevel@tonic-gate 				xflag = 1;
3627c478bd9Sstevel@tonic-gate 				crflag = -1;
3637c478bd9Sstevel@tonic-gate 				break;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 			case 'v':
3667c478bd9Sstevel@tonic-gate 				ivis = 1;
3677c478bd9Sstevel@tonic-gate 				break;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 			default:
3707c478bd9Sstevel@tonic-gate 				usage(cmdnam);
3717c478bd9Sstevel@tonic-gate 				exit(1);
3727c478bd9Sstevel@tonic-gate 			}
3737c478bd9Sstevel@tonic-gate 		if (av[optind] && av[optind][0] == '+' &&
3747c478bd9Sstevel@tonic-gate 		    av[optind-1] && strcmp(av[optind-1], "--")) {
375f6db9f27Scf 				firstpat = (unsigned char *)&av[optind][1];
3767c478bd9Sstevel@tonic-gate 				optind++;
3777c478bd9Sstevel@tonic-gate 				continue;
3787c478bd9Sstevel@tonic-gate 		} else if (av[optind] && av[optind][0] == '-' &&
3797c478bd9Sstevel@tonic-gate 		    av[optind-1] && strcmp(av[optind-1], "--")) {
3807c478bd9Sstevel@tonic-gate 			hush = 1;
3817c478bd9Sstevel@tonic-gate 			value(vi_AUTOPRINT) = 0;
3827c478bd9Sstevel@tonic-gate 			fast++;
3837c478bd9Sstevel@tonic-gate 			optind++;
3847c478bd9Sstevel@tonic-gate 			continue;
3857c478bd9Sstevel@tonic-gate 		}
3867c478bd9Sstevel@tonic-gate 		break;
3877c478bd9Sstevel@tonic-gate 	}
3887c478bd9Sstevel@tonic-gate 
389a1d23db4Sceastha 	if (isatty(0) == 0) {
390a1d23db4Sceastha 		/*
391a1d23db4Sceastha 		 * If -V option is set and input is coming in via
392a1d23db4Sceastha 		 * stdin then vi behavior should be ignored. The vi
393a1d23db4Sceastha 		 * command should act like ex and only process ex commands
394a1d23db4Sceastha 		 * and echo the input ex commands to stderr
395a1d23db4Sceastha 		 */
396a1d23db4Sceastha 		if (verbose == 1) {
397a1d23db4Sceastha 			ivis = 0;
398a1d23db4Sceastha 		}
399a1d23db4Sceastha 
400a1d23db4Sceastha 		/*
401a1d23db4Sceastha 		 * If the standard input is not a terminal device,
402a1d23db4Sceastha 		 * it is as if the -s option has been specified.
403a1d23db4Sceastha 		 */
404a1d23db4Sceastha 		if (ivis == 0) {
405a1d23db4Sceastha 			hush = 1;
406a1d23db4Sceastha 			value(vi_AUTOPRINT) = 0;
407a1d23db4Sceastha 			fast++;
408a1d23db4Sceastha 		}
4097c478bd9Sstevel@tonic-gate 	}
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	ac -= optind;
4127c478bd9Sstevel@tonic-gate 	av  = &av[optind];
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	for (argcounter = 0; argcounter < ac; argcounter++) {
4157c478bd9Sstevel@tonic-gate 		if ((strlen(av[argcounter])) >= sizeof (savedfile)) {
4167c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("File argument"
417a1d23db4Sceastha 			    " too long\n"));
4187c478bd9Sstevel@tonic-gate 			exit(1);
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 	}
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate #ifdef SIGTSTP
4237c478bd9Sstevel@tonic-gate 	if (!hush && signal(SIGTSTP, SIG_IGN) == SIG_DFL)
4247c478bd9Sstevel@tonic-gate 		signal(SIGTSTP, onsusp), dosusp++;
4257c478bd9Sstevel@tonic-gate #endif
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	if (xflag) {
4287c478bd9Sstevel@tonic-gate 		permflag = 1;
4297c478bd9Sstevel@tonic-gate 		if ((kflag = run_setkey(perm,
4307c478bd9Sstevel@tonic-gate 		    (key = (unsigned char *)getpass(
4317c478bd9Sstevel@tonic-gate 		    gettext("Enter key:"))))) == -1) {
4327c478bd9Sstevel@tonic-gate 			kflag = 0;
4337c478bd9Sstevel@tonic-gate 			xflag = 0;
4347c478bd9Sstevel@tonic-gate 			smerror(gettext("Encryption facility not available\n"));
4357c478bd9Sstevel@tonic-gate 		}
4367c478bd9Sstevel@tonic-gate 		if (kflag == 0)
4377c478bd9Sstevel@tonic-gate 			crflag = 0;
4387c478bd9Sstevel@tonic-gate 		else {
4397c478bd9Sstevel@tonic-gate 			strcpy(cryptkey, "CrYpTkEy=XXXXXXXXX");
4407c478bd9Sstevel@tonic-gate 			strcpy(cryptkey + 9, key);
4417c478bd9Sstevel@tonic-gate 			if (putenv((char *)cryptkey) != 0)
4427c478bd9Sstevel@tonic-gate 			smerror(gettext(" Cannot copy key to environment"));
4437c478bd9Sstevel@tonic-gate 		}
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC
4477c478bd9Sstevel@tonic-gate 	/*
4487c478bd9Sstevel@tonic-gate 	 * Perform locale-specific initialization
4497c478bd9Sstevel@tonic-gate 	 */
450f6db9f27Scf 	localize();
4517c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	/*
4547c478bd9Sstevel@tonic-gate 	 * Initialize end of core pointers.
4557c478bd9Sstevel@tonic-gate 	 * Normally we avoid breaking back to fendcore after each
4567c478bd9Sstevel@tonic-gate 	 * file since this can be expensive (much core-core copying).
4577c478bd9Sstevel@tonic-gate 	 * If your system can scatter load processes you could do
4587c478bd9Sstevel@tonic-gate 	 * this as ed does, saving a little core, but it will probably
4597c478bd9Sstevel@tonic-gate 	 * not often make much difference.
4607c478bd9Sstevel@tonic-gate 	 */
4617c478bd9Sstevel@tonic-gate 	fendcore = (line *) sbrk(0);
4627c478bd9Sstevel@tonic-gate 	endcore = fendcore - 2;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	/*
4657c478bd9Sstevel@tonic-gate 	 * If we are doing a recover and no filename
4667c478bd9Sstevel@tonic-gate 	 * was given, then execute an exrecover command with
4677c478bd9Sstevel@tonic-gate 	 * the -r option to type out the list of saved file names.
4687c478bd9Sstevel@tonic-gate 	 * Otherwise set the remembered file name to the first argument
4697c478bd9Sstevel@tonic-gate 	 * file name so the "recover" initial command will find it.
4707c478bd9Sstevel@tonic-gate 	 */
4717c478bd9Sstevel@tonic-gate 	if (recov) {
4727c478bd9Sstevel@tonic-gate 		if (ac == 0 && (rcvname == NULL || *rcvname == NULL)) {
4737c478bd9Sstevel@tonic-gate 			ppid = 0;
4747c478bd9Sstevel@tonic-gate 			setrupt();
4757c478bd9Sstevel@tonic-gate 			execlp(EXRECOVER, "exrecover", "-r", (char *)0);
4767c478bd9Sstevel@tonic-gate 			filioerr(EXRECOVER);
4777c478bd9Sstevel@tonic-gate 			exit(++errcnt);
4787c478bd9Sstevel@tonic-gate 		}
4797c478bd9Sstevel@tonic-gate 		if (rcvname && *rcvname)
4807c478bd9Sstevel@tonic-gate 			(void) strlcpy(savedfile, rcvname, sizeof (savedfile));
4817c478bd9Sstevel@tonic-gate 		else {
4827c478bd9Sstevel@tonic-gate 			(void) strlcpy(savedfile, *av++, sizeof (savedfile));
4837c478bd9Sstevel@tonic-gate 			ac--;
4847c478bd9Sstevel@tonic-gate 		}
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	/*
4887c478bd9Sstevel@tonic-gate 	 * Initialize the argument list.
4897c478bd9Sstevel@tonic-gate 	 */
490f6db9f27Scf 	argv0 = (unsigned char **)av;
4917c478bd9Sstevel@tonic-gate 	argc0 = ac;
492f6db9f27Scf 	args0 = (unsigned char *)av[0];
4937c478bd9Sstevel@tonic-gate 	erewind();
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	/*
4967c478bd9Sstevel@tonic-gate 	 * Initialize a temporary file (buffer) and
4977c478bd9Sstevel@tonic-gate 	 * set up terminal environment.  Read user startup commands.
4987c478bd9Sstevel@tonic-gate 	 */
4997c478bd9Sstevel@tonic-gate 	if (setexit() == 0) {
5007c478bd9Sstevel@tonic-gate 		setrupt();
5017c478bd9Sstevel@tonic-gate 		intty = isatty(0);
5027c478bd9Sstevel@tonic-gate 		value(vi_PROMPT) = intty;
5037c478bd9Sstevel@tonic-gate 		if (((cp = (unsigned char *)getenv("SHELL")) != NULL) &&
5047c478bd9Sstevel@tonic-gate 		    (*cp != '\0')) {
5057c478bd9Sstevel@tonic-gate 			if (strlen(cp) < sizeof (shell)) {
5067c478bd9Sstevel@tonic-gate 				(void) strlcpy(shell, cp, sizeof (shell));
5077c478bd9Sstevel@tonic-gate 			}
5087c478bd9Sstevel@tonic-gate 		}
5097c478bd9Sstevel@tonic-gate 		if (fast)
510f6db9f27Scf 			setterm((unsigned char *)"dumb");
5117c478bd9Sstevel@tonic-gate 		else {
5127c478bd9Sstevel@tonic-gate 			gettmode();
5137c478bd9Sstevel@tonic-gate 			cp = (unsigned char *)getenv("TERM");
5147c478bd9Sstevel@tonic-gate 			if (cp == NULL || *cp == '\0')
5157c478bd9Sstevel@tonic-gate 				cp = (unsigned char *)"unknown";
5167c478bd9Sstevel@tonic-gate 			setterm(cp);
5177c478bd9Sstevel@tonic-gate 		}
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	/*
5217c478bd9Sstevel@tonic-gate 	 * Bring up some code from init()
5227c478bd9Sstevel@tonic-gate 	 * This is still done in init later. This
5237c478bd9Sstevel@tonic-gate 	 * avoids null pointer problems
5247c478bd9Sstevel@tonic-gate 	 */
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	dot = zero = truedol = unddol = dol = fendcore;
5277c478bd9Sstevel@tonic-gate 	one = zero+1;
5287c478bd9Sstevel@tonic-gate 	{
529f6db9f27Scf 	int i;
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	for (i = 0; i <= 'z'-'a'+1; i++)
5327c478bd9Sstevel@tonic-gate 		names[i] = 1;
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	if (setexit() == 0 && !fast) {
5367c478bd9Sstevel@tonic-gate 		if ((globp =
537a1d23db4Sceastha 		    (unsigned char *) getenv("EXINIT")) && *globp) {
5387c478bd9Sstevel@tonic-gate 			if (ivis)
5397c478bd9Sstevel@tonic-gate 				inexrc = 1;
5407c478bd9Sstevel@tonic-gate 			commands(1, 1);
5417c478bd9Sstevel@tonic-gate 			inexrc = 0;
5427c478bd9Sstevel@tonic-gate 		} else {
5437c478bd9Sstevel@tonic-gate 			globp = 0;
5447c478bd9Sstevel@tonic-gate 			if ((cp = (unsigned char *) getenv("HOME")) !=
5457c478bd9Sstevel@tonic-gate 			    0 && *cp) {
5467c478bd9Sstevel@tonic-gate 				strncpy(scratch, cp, sizeof (scratch) - 1);
5477c478bd9Sstevel@tonic-gate 				strncat(scratch, "/.exrc",
5487c478bd9Sstevel@tonic-gate 				    sizeof (scratch) - 1 - strlen(scratch));
5497c478bd9Sstevel@tonic-gate 				if (ivis)
550a1d23db4Sceastha 					inexrc = 1;
5517c478bd9Sstevel@tonic-gate 				if ((vret = validate_exrc(scratch)) == 0) {
5527c478bd9Sstevel@tonic-gate 					source(scratch, 1);
5537c478bd9Sstevel@tonic-gate 				} else {
5547c478bd9Sstevel@tonic-gate 					if (vret == -1) {
5557c478bd9Sstevel@tonic-gate 						error(gettext(
5567c478bd9Sstevel@tonic-gate 						    "Not owner of .exrc "
5577c478bd9Sstevel@tonic-gate 						    "or .exrc is group or "
5587c478bd9Sstevel@tonic-gate 						    "world writable"));
5597c478bd9Sstevel@tonic-gate 					}
5607c478bd9Sstevel@tonic-gate 				}
5617c478bd9Sstevel@tonic-gate 				inexrc = 0;
5627c478bd9Sstevel@tonic-gate 			}
5637c478bd9Sstevel@tonic-gate 		}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 		/*
5667c478bd9Sstevel@tonic-gate 		 * Allow local .exrc if the "exrc" option was set. This
5677c478bd9Sstevel@tonic-gate 		 * loses if . is $HOME, but nobody should notice unless
5687c478bd9Sstevel@tonic-gate 		 * they do stupid things like putting a version command
5697c478bd9Sstevel@tonic-gate 		 * in .exrc.
5707c478bd9Sstevel@tonic-gate 		 * Besides, they should be using EXINIT, not .exrc, right?
5717c478bd9Sstevel@tonic-gate 		 */
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 		if (value(vi_EXRC)) {
5747c478bd9Sstevel@tonic-gate 			if (ivis)
5757c478bd9Sstevel@tonic-gate 				inexrc = 1;
5767c478bd9Sstevel@tonic-gate 			if ((cp = (unsigned char *) getenv("PWD")) != 0 &&
5777c478bd9Sstevel@tonic-gate 			    *cp) {
5787c478bd9Sstevel@tonic-gate 				strncpy(exrcpath, cp, sizeof (exrcpath) - 1);
5797c478bd9Sstevel@tonic-gate 				strncat(exrcpath, "/.exrc",
5807c478bd9Sstevel@tonic-gate 				    sizeof (exrcpath) - 1 - strlen(exrcpath));
5817c478bd9Sstevel@tonic-gate 				if (strcmp(scratch, exrcpath) != 0) {
5827c478bd9Sstevel@tonic-gate 					if ((vret =
5837c478bd9Sstevel@tonic-gate 					    validate_exrc(exrcpath)) == 0) {
5847c478bd9Sstevel@tonic-gate 						source(exrcpath, 1);
5857c478bd9Sstevel@tonic-gate 					} else {
5867c478bd9Sstevel@tonic-gate 						if (vret == -1) {
5877c478bd9Sstevel@tonic-gate 							error(gettext(
5887c478bd9Sstevel@tonic-gate 							    "Not owner of "
5897c478bd9Sstevel@tonic-gate 							    ".exrc or .exrc "
5907c478bd9Sstevel@tonic-gate 							    "is group or world "
5917c478bd9Sstevel@tonic-gate 							    "writable"));
5927c478bd9Sstevel@tonic-gate 						}
5937c478bd9Sstevel@tonic-gate 					}
5947c478bd9Sstevel@tonic-gate 				}
5957c478bd9Sstevel@tonic-gate 			}
5967c478bd9Sstevel@tonic-gate 			inexrc = 0;
5977c478bd9Sstevel@tonic-gate 		}
5987c478bd9Sstevel@tonic-gate 	}
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	init();	/* moved after prev 2 chunks to fix directory option */
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	/*
6037c478bd9Sstevel@tonic-gate 	 * Initial processing.  Handle tag, recover, and file argument
6047c478bd9Sstevel@tonic-gate 	 * implied next commands.  If going in as 'vi', then don't do
6057c478bd9Sstevel@tonic-gate 	 * anything, just set initev so we will do it later (from within
6067c478bd9Sstevel@tonic-gate 	 * visual).
6077c478bd9Sstevel@tonic-gate 	 */
6087c478bd9Sstevel@tonic-gate 	if (setexit() == 0) {
6097c478bd9Sstevel@tonic-gate 		if (recov)
6107c478bd9Sstevel@tonic-gate 			globp = (unsigned char *)"recover";
6117c478bd9Sstevel@tonic-gate 		else if (itag) {
6127c478bd9Sstevel@tonic-gate 			globp = ivis ? (unsigned char *)"tag" :
6137c478bd9Sstevel@tonic-gate 			    (unsigned char *)"tag|p";
6147c478bd9Sstevel@tonic-gate #ifdef	XPG4
6157c478bd9Sstevel@tonic-gate 			if (firstpat != NULL) {
6167c478bd9Sstevel@tonic-gate 				/*
6177c478bd9Sstevel@tonic-gate 				 * if the user specified the -t and -c
6187c478bd9Sstevel@tonic-gate 				 * flags together, then we service these
6197c478bd9Sstevel@tonic-gate 				 * commands here. -t is handled first.
6207c478bd9Sstevel@tonic-gate 				 */
6217c478bd9Sstevel@tonic-gate 				savepat = firstpat;
6227c478bd9Sstevel@tonic-gate 				firstpat = NULL;
6237c478bd9Sstevel@tonic-gate 				inglobal = 1;
6247c478bd9Sstevel@tonic-gate 				commands(1, 1);
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 				/* now handle the -c argument: */
6277c478bd9Sstevel@tonic-gate 				globp = savepat;
6287c478bd9Sstevel@tonic-gate 				commands(1, 1);
6297c478bd9Sstevel@tonic-gate 				inglobal = 0;
6307c478bd9Sstevel@tonic-gate 				globp = savepat = NULL;
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 				/* the above isn't sufficient for ex mode: */
6337c478bd9Sstevel@tonic-gate 				if (!ivis) {
6347c478bd9Sstevel@tonic-gate 					setdot();
6357c478bd9Sstevel@tonic-gate 					nonzero();
6367c478bd9Sstevel@tonic-gate 					plines(addr1, addr2, 1);
6377c478bd9Sstevel@tonic-gate 				}
6387c478bd9Sstevel@tonic-gate 			}
6397c478bd9Sstevel@tonic-gate #endif /* XPG4 */
6407c478bd9Sstevel@tonic-gate 		} else if (argc)
6417c478bd9Sstevel@tonic-gate 			globp = (unsigned char *)"next";
6427c478bd9Sstevel@tonic-gate 		if (ivis)
6437c478bd9Sstevel@tonic-gate 			initev = globp;
6447c478bd9Sstevel@tonic-gate 		else if (globp) {
6457c478bd9Sstevel@tonic-gate 			inglobal = 1;
6467c478bd9Sstevel@tonic-gate 			commands(1, 1);
6477c478bd9Sstevel@tonic-gate 			inglobal = 0;
6487c478bd9Sstevel@tonic-gate 		}
6497c478bd9Sstevel@tonic-gate 	}
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	/*
6527c478bd9Sstevel@tonic-gate 	 * Vi command... go into visual.
6537c478bd9Sstevel@tonic-gate 	 */
6547c478bd9Sstevel@tonic-gate 	if (ivis) {
6557c478bd9Sstevel@tonic-gate 		/*
6567c478bd9Sstevel@tonic-gate 		 * Don't have to be upward compatible
6577c478bd9Sstevel@tonic-gate 		 * by starting editing at line $.
6587c478bd9Sstevel@tonic-gate 		 */
6597c478bd9Sstevel@tonic-gate #ifdef	XPG4
6607c478bd9Sstevel@tonic-gate 		if (!itag && (dol > zero))
6617c478bd9Sstevel@tonic-gate #else /* XPG4 */
6627c478bd9Sstevel@tonic-gate 		if (dol > zero)
6637c478bd9Sstevel@tonic-gate #endif /* XPG4 */
6647c478bd9Sstevel@tonic-gate 			dot = one;
6657c478bd9Sstevel@tonic-gate 		globp = (unsigned char *)"visual";
6667c478bd9Sstevel@tonic-gate 		if (setexit() == 0)
6677c478bd9Sstevel@tonic-gate 			commands(1, 1);
6687c478bd9Sstevel@tonic-gate 	}
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	/*
6717c478bd9Sstevel@tonic-gate 	 * Clear out trash in state accumulated by startup,
6727c478bd9Sstevel@tonic-gate 	 * and then do the main command loop for a normal edit.
6737c478bd9Sstevel@tonic-gate 	 * If you quit out of a 'vi' command by doing Q or ^\,
6747c478bd9Sstevel@tonic-gate 	 * you also fall through to here.
6757c478bd9Sstevel@tonic-gate 	 */
6767c478bd9Sstevel@tonic-gate 	seenprompt = 1;
6777c478bd9Sstevel@tonic-gate 	ungetchar(0);
6787c478bd9Sstevel@tonic-gate 	globp = 0;
6797c478bd9Sstevel@tonic-gate 	initev = 0;
6807c478bd9Sstevel@tonic-gate 	setlastchar('\n');
6817c478bd9Sstevel@tonic-gate 	setexit();
6827c478bd9Sstevel@tonic-gate 	commands(0, 0);
6837c478bd9Sstevel@tonic-gate 	cleanup(1);
684f6db9f27Scf 	return (errcnt);
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate /*
6887c478bd9Sstevel@tonic-gate  * Initialization, before editing a new file.
6897c478bd9Sstevel@tonic-gate  * Main thing here is to get a new buffer (in fileinit),
6907c478bd9Sstevel@tonic-gate  * rest is peripheral state resetting.
6917c478bd9Sstevel@tonic-gate  */
692f6db9f27Scf void
693f6db9f27Scf init(void)
6947c478bd9Sstevel@tonic-gate {
695f6db9f27Scf 	int i;
6967c478bd9Sstevel@tonic-gate 	void (*pstat)();
6977c478bd9Sstevel@tonic-gate 	fileinit();
6987c478bd9Sstevel@tonic-gate 	dot = zero = truedol = unddol = dol = fendcore;
6997c478bd9Sstevel@tonic-gate 	one = zero+1;
7007c478bd9Sstevel@tonic-gate 	undkind = UNDNONE;
7017c478bd9Sstevel@tonic-gate 	chng = 0;
7027c478bd9Sstevel@tonic-gate 	edited = 0;
7037c478bd9Sstevel@tonic-gate 	for (i = 0; i <= 'z'-'a'+1; i++)
7047c478bd9Sstevel@tonic-gate 		names[i] = 1;
7057c478bd9Sstevel@tonic-gate 	anymarks = 0;
7067c478bd9Sstevel@tonic-gate 	if (xflag) {
7077c478bd9Sstevel@tonic-gate 		xtflag = 1;
7087c478bd9Sstevel@tonic-gate 		/* ignore SIGINT before crypt process */
7097c478bd9Sstevel@tonic-gate 		pstat = signal(SIGINT, SIG_IGN);
7107c478bd9Sstevel@tonic-gate 		if (tpermflag)
7117c478bd9Sstevel@tonic-gate 			(void) crypt_close(tperm);
7127c478bd9Sstevel@tonic-gate 		tpermflag = 1;
7137c478bd9Sstevel@tonic-gate 		if (makekey(tperm) != 0) {
7147c478bd9Sstevel@tonic-gate 			xtflag = 0;
7157c478bd9Sstevel@tonic-gate 			smerror(gettext(
7167c478bd9Sstevel@tonic-gate 			    "Warning--Cannot encrypt temporary buffer\n"));
7177c478bd9Sstevel@tonic-gate 		}
7187c478bd9Sstevel@tonic-gate 		signal(SIGINT, pstat);
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate /*
7237c478bd9Sstevel@tonic-gate  * Return last component of unix path name p.
7247c478bd9Sstevel@tonic-gate  */
7257c478bd9Sstevel@tonic-gate unsigned char *
7267c478bd9Sstevel@tonic-gate tailpath(p)
727f6db9f27Scf unsigned char *p;
7287c478bd9Sstevel@tonic-gate {
729f6db9f27Scf 	unsigned char *r;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	for (r = p; *p; p++)
7327c478bd9Sstevel@tonic-gate 		if (*p == '/')
7337c478bd9Sstevel@tonic-gate 			r = p+1;
7347c478bd9Sstevel@tonic-gate 	return (r);
7357c478bd9Sstevel@tonic-gate }
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate /*
7397c478bd9Sstevel@tonic-gate  * validate_exrc - verify .exrc as belonging to the user.
7407c478bd9Sstevel@tonic-gate  * The file uid should match the process ruid,
7417c478bd9Sstevel@tonic-gate  * and the file should be writable only by the owner.
7427c478bd9Sstevel@tonic-gate  */
7437c478bd9Sstevel@tonic-gate static int
7447c478bd9Sstevel@tonic-gate validate_exrc(unsigned char *exrc_path)
7457c478bd9Sstevel@tonic-gate {
7467c478bd9Sstevel@tonic-gate 	struct stat64 exrc_stat;
7477c478bd9Sstevel@tonic-gate 	int process_uid;
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	if (stat64((char *)exrc_path, &exrc_stat) == -1)
7507c478bd9Sstevel@tonic-gate 		return (0); /* ignore if .exrec is not found */
7517c478bd9Sstevel@tonic-gate 	process_uid = geteuid();
7527c478bd9Sstevel@tonic-gate 	/* if not root, uid must match file owner */
7537c478bd9Sstevel@tonic-gate 	if (process_uid && process_uid != exrc_stat.st_uid)
7547c478bd9Sstevel@tonic-gate 		return (-1);
7557c478bd9Sstevel@tonic-gate 	if ((exrc_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0)
7567c478bd9Sstevel@tonic-gate 		return (-1);
7577c478bd9Sstevel@tonic-gate 	return (0);
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate /*
7617c478bd9Sstevel@tonic-gate  * print usage message to stdout
7627c478bd9Sstevel@tonic-gate  */
7637c478bd9Sstevel@tonic-gate static void
7647c478bd9Sstevel@tonic-gate usage(unsigned char *name)
7657c478bd9Sstevel@tonic-gate {
7667c478bd9Sstevel@tonic-gate 	char buf[160];
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate #ifdef TRACE
7697c478bd9Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf), gettext(
770a1d23db4Sceastha 	    "Usage: %s [- | -s] [-l] [-L] [-wn] "
771a1d23db4Sceastha 	    "[-R] [-S] [-r [file]] [-t tag] [-T] [-U tracefile]\n"
772a1d23db4Sceastha 	    "[-v] [-V] [-x] [-C] [+cmd | -c cmd] file...\n"), name);
7737c478bd9Sstevel@tonic-gate #else
7747c478bd9Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf), gettext(
775a1d23db4Sceastha 	    "Usage: %s [- | -s] [-l] [-L] [-wn] "
776a1d23db4Sceastha 	    "[-R] [-S] [-r [file]] [-t tag]\n"
777a1d23db4Sceastha 	    "[-v] [-V] [-x] [-C] [+cmd | -c cmd] file...\n"), name);
7787c478bd9Sstevel@tonic-gate #endif
7797c478bd9Sstevel@tonic-gate 	(void) write(2, buf, strlen(buf));
7807c478bd9Sstevel@tonic-gate }
781