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