1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include "ex.h" 35*7c478bd9Sstevel@tonic-gate #include "ex_argv.h" 36*7c478bd9Sstevel@tonic-gate #include "ex_temp.h" 37*7c478bd9Sstevel@tonic-gate #include "ex_tty.h" 38*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 39*7c478bd9Sstevel@tonic-gate #include <locale.h> 40*7c478bd9Sstevel@tonic-gate #include <stdio.h> 41*7c478bd9Sstevel@tonic-gate #ifdef TRACE 42*7c478bd9Sstevel@tonic-gate unsigned char tttrace[BUFSIZ]; 43*7c478bd9Sstevel@tonic-gate #endif 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #define EQ(a, b) (strcmp(a, b) == 0) 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate char *strrchr(); 48*7c478bd9Sstevel@tonic-gate void init_re(void); 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate /* 51*7c478bd9Sstevel@tonic-gate * The code for ex is divided as follows: 52*7c478bd9Sstevel@tonic-gate * 53*7c478bd9Sstevel@tonic-gate * ex.c Entry point and routines handling interrupt, hangup 54*7c478bd9Sstevel@tonic-gate * signals; initialization code. 55*7c478bd9Sstevel@tonic-gate * 56*7c478bd9Sstevel@tonic-gate * ex_addr.c Address parsing routines for command mode decoding. 57*7c478bd9Sstevel@tonic-gate * Routines to set and check address ranges on commands. 58*7c478bd9Sstevel@tonic-gate * 59*7c478bd9Sstevel@tonic-gate * ex_cmds.c Command mode command decoding. 60*7c478bd9Sstevel@tonic-gate * 61*7c478bd9Sstevel@tonic-gate * ex_cmds2.c Subroutines for command decoding and processing of 62*7c478bd9Sstevel@tonic-gate * file names in the argument list. Routines to print 63*7c478bd9Sstevel@tonic-gate * messages and reset state when errors occur. 64*7c478bd9Sstevel@tonic-gate * 65*7c478bd9Sstevel@tonic-gate * ex_cmdsub.c Subroutines which implement command mode functions 66*7c478bd9Sstevel@tonic-gate * such as append, delete, join. 67*7c478bd9Sstevel@tonic-gate * 68*7c478bd9Sstevel@tonic-gate * ex_data.c Initialization of options. 69*7c478bd9Sstevel@tonic-gate * 70*7c478bd9Sstevel@tonic-gate * ex_get.c Command mode input routines. 71*7c478bd9Sstevel@tonic-gate * 72*7c478bd9Sstevel@tonic-gate * ex_io.c General input/output processing: file i/o, unix 73*7c478bd9Sstevel@tonic-gate * escapes, filtering, source commands, preserving 74*7c478bd9Sstevel@tonic-gate * and recovering. 75*7c478bd9Sstevel@tonic-gate * 76*7c478bd9Sstevel@tonic-gate * ex_put.c Terminal driving and optimizing routines for low-level 77*7c478bd9Sstevel@tonic-gate * output (cursor-positioning); output line formatting 78*7c478bd9Sstevel@tonic-gate * routines. 79*7c478bd9Sstevel@tonic-gate * 80*7c478bd9Sstevel@tonic-gate * ex_re.c Global commands, substitute, regular expression 81*7c478bd9Sstevel@tonic-gate * compilation and execution. 82*7c478bd9Sstevel@tonic-gate * 83*7c478bd9Sstevel@tonic-gate * ex_set.c The set command. 84*7c478bd9Sstevel@tonic-gate * 85*7c478bd9Sstevel@tonic-gate * ex_subr.c Loads of miscellaneous subroutines. 86*7c478bd9Sstevel@tonic-gate * 87*7c478bd9Sstevel@tonic-gate * ex_temp.c Editor buffer routines for main buffer and also 88*7c478bd9Sstevel@tonic-gate * for named buffers (Q registers if you will.) 89*7c478bd9Sstevel@tonic-gate * 90*7c478bd9Sstevel@tonic-gate * ex_tty.c Terminal dependent initializations from termcap 91*7c478bd9Sstevel@tonic-gate * data base, grabbing of tty modes (at beginning 92*7c478bd9Sstevel@tonic-gate * and after escapes). 93*7c478bd9Sstevel@tonic-gate * 94*7c478bd9Sstevel@tonic-gate * ex_unix.c Routines for the ! command and its variations. 95*7c478bd9Sstevel@tonic-gate * 96*7c478bd9Sstevel@tonic-gate * ex_v*.c Visual/open mode routines... see ex_v.c for a 97*7c478bd9Sstevel@tonic-gate * guide to the overall organization. 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* 101*7c478bd9Sstevel@tonic-gate * This sets the Version of ex/vi for both the exstrings file and 102*7c478bd9Sstevel@tonic-gate * the version command (":ver"). 103*7c478bd9Sstevel@tonic-gate */ 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* variable used by ":ver" command */ 106*7c478bd9Sstevel@tonic-gate unsigned char *Version = (unsigned char *)"Version SVR4.0, Solaris 2.5.0"; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate * NOTE: when changing the Version number, it must be changed in the 110*7c478bd9Sstevel@tonic-gate * following files: 111*7c478bd9Sstevel@tonic-gate * 112*7c478bd9Sstevel@tonic-gate * port/READ_ME 113*7c478bd9Sstevel@tonic-gate * port/ex.c 114*7c478bd9Sstevel@tonic-gate * port/ex.news 115*7c478bd9Sstevel@tonic-gate * 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate #ifdef XPG4 118*7c478bd9Sstevel@tonic-gate unsigned char *savepat = (unsigned char *) NULL; /* firstpat storage */ 119*7c478bd9Sstevel@tonic-gate #endif /* XPG4 */ 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * Main procedure. Process arguments and then 123*7c478bd9Sstevel@tonic-gate * transfer control to the main command processing loop 124*7c478bd9Sstevel@tonic-gate * in the routine commands. We are entered as either "ex", "edit", "vi" 125*7c478bd9Sstevel@tonic-gate * or "view" and the distinction is made here. For edit we just diddle options; 126*7c478bd9Sstevel@tonic-gate * for vi we actually force an early visual command. 127*7c478bd9Sstevel@tonic-gate */ 128*7c478bd9Sstevel@tonic-gate static unsigned char cryptkey[19]; /* contents of encryption key */ 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate static void usage(unsigned char *); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate static int validate_exrc(unsigned char *); 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate int 135*7c478bd9Sstevel@tonic-gate main(int ac, unsigned char *av[]) 136*7c478bd9Sstevel@tonic-gate { 137*7c478bd9Sstevel@tonic-gate extern char *optarg; 138*7c478bd9Sstevel@tonic-gate extern int optind; 139*7c478bd9Sstevel@tonic-gate unsigned char *rcvname = 0; 140*7c478bd9Sstevel@tonic-gate unsigned char *cp; 141*7c478bd9Sstevel@tonic-gate int c; 142*7c478bd9Sstevel@tonic-gate unsigned char *cmdnam; 143*7c478bd9Sstevel@tonic-gate bool recov = 0; 144*7c478bd9Sstevel@tonic-gate bool ivis = 0; 145*7c478bd9Sstevel@tonic-gate bool itag = 0; 146*7c478bd9Sstevel@tonic-gate bool fast = 0; 147*7c478bd9Sstevel@tonic-gate extern int verbose; 148*7c478bd9Sstevel@tonic-gate int argcounter = 0; 149*7c478bd9Sstevel@tonic-gate extern int tags_flag; /* Set if tag file is not sorted (-S flag) */ 150*7c478bd9Sstevel@tonic-gate unsigned char scratch [PATH_MAX+1]; /* temp for sourcing rc file(s) */ 151*7c478bd9Sstevel@tonic-gate int vret = 0; 152*7c478bd9Sstevel@tonic-gate unsigned char exrcpath [PATH_MAX+1]; /* temp for sourcing rc file(s) */ 153*7c478bd9Sstevel@tonic-gate int toptseen = 0; 154*7c478bd9Sstevel@tonic-gate #ifdef TRACE 155*7c478bd9Sstevel@tonic-gate unsigned char *tracef; 156*7c478bd9Sstevel@tonic-gate #endif 157*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 158*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 159*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 160*7c478bd9Sstevel@tonic-gate #endif 161*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * Immediately grab the tty modes so that we won't 165*7c478bd9Sstevel@tonic-gate * get messed up if an interrupt comes in quickly. 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate gTTY(2); 168*7c478bd9Sstevel@tonic-gate normf = tty; 169*7c478bd9Sstevel@tonic-gate ppid = getpid(); 170*7c478bd9Sstevel@tonic-gate /* Note - this will core dump if you didn't -DSINGLE in CFLAGS */ 171*7c478bd9Sstevel@tonic-gate lines = 24; 172*7c478bd9Sstevel@tonic-gate columns = 80; /* until defined right by setupterm */ 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * Defend against d's, v's, w's, and a's in directories of 175*7c478bd9Sstevel@tonic-gate * path leading to our true name. 176*7c478bd9Sstevel@tonic-gate */ 177*7c478bd9Sstevel@tonic-gate if ((cmdnam = (unsigned char *)strrchr(av[0], '/')) != 0) 178*7c478bd9Sstevel@tonic-gate cmdnam++; 179*7c478bd9Sstevel@tonic-gate else 180*7c478bd9Sstevel@tonic-gate cmdnam = av[0]; 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate if (EQ(cmdnam, "vi")) 183*7c478bd9Sstevel@tonic-gate ivis = 1; 184*7c478bd9Sstevel@tonic-gate else if (EQ(cmdnam, "view")) { 185*7c478bd9Sstevel@tonic-gate ivis = 1; 186*7c478bd9Sstevel@tonic-gate value(vi_READONLY) = 1; 187*7c478bd9Sstevel@tonic-gate } else if (EQ(cmdnam, "vedit")) { 188*7c478bd9Sstevel@tonic-gate ivis = 1; 189*7c478bd9Sstevel@tonic-gate value(vi_NOVICE) = 1; 190*7c478bd9Sstevel@tonic-gate value(vi_REPORT) = 1; 191*7c478bd9Sstevel@tonic-gate value(vi_MAGIC) = 0; 192*7c478bd9Sstevel@tonic-gate value(vi_SHOWMODE) = 1; 193*7c478bd9Sstevel@tonic-gate } else if (EQ(cmdnam, "edit")) { 194*7c478bd9Sstevel@tonic-gate value(vi_NOVICE) = 1; 195*7c478bd9Sstevel@tonic-gate value(vi_REPORT) = 1; 196*7c478bd9Sstevel@tonic-gate value(vi_MAGIC) = 0; 197*7c478bd9Sstevel@tonic-gate value(vi_SHOWMODE) = 1; 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate #ifdef XPG4 201*7c478bd9Sstevel@tonic-gate { 202*7c478bd9Sstevel@tonic-gate struct winsize jwin; 203*7c478bd9Sstevel@tonic-gate char *envptr; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate envlines = envcolumns = -1; 206*7c478bd9Sstevel@tonic-gate oldlines = oldcolumns = -1; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate if (ioctl(0, TIOCGWINSZ, &jwin) != -1) { 209*7c478bd9Sstevel@tonic-gate oldlines = jwin.ws_row; 210*7c478bd9Sstevel@tonic-gate oldcolumns = jwin.ws_col; 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if ((envptr = getenv("LINES")) != NULL && 214*7c478bd9Sstevel@tonic-gate *envptr != '\0' && isdigit(*envptr)) { 215*7c478bd9Sstevel@tonic-gate if ((envlines = atoi(envptr)) <= 0) { 216*7c478bd9Sstevel@tonic-gate envlines = -1; 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate if ((envptr = getenv("COLUMNS")) != NULL && 221*7c478bd9Sstevel@tonic-gate *envptr != '\0' && isdigit(*envptr)) { 222*7c478bd9Sstevel@tonic-gate if ((envcolumns = atoi(envptr)) <= 0) { 223*7c478bd9Sstevel@tonic-gate envcolumns = -1; 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate #endif /* XPG4 */ 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate draino(); 230*7c478bd9Sstevel@tonic-gate pstop(); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate /* 233*7c478bd9Sstevel@tonic-gate * Initialize interrupt handling. 234*7c478bd9Sstevel@tonic-gate */ 235*7c478bd9Sstevel@tonic-gate oldhup = signal(SIGHUP, SIG_IGN); 236*7c478bd9Sstevel@tonic-gate if (oldhup == SIG_DFL) 237*7c478bd9Sstevel@tonic-gate signal(SIGHUP, onhup); 238*7c478bd9Sstevel@tonic-gate oldquit = signal(SIGQUIT, SIG_IGN); 239*7c478bd9Sstevel@tonic-gate ruptible = signal(SIGINT, SIG_IGN) == SIG_DFL; 240*7c478bd9Sstevel@tonic-gate if (signal(SIGTERM, SIG_IGN) == SIG_DFL) 241*7c478bd9Sstevel@tonic-gate signal(SIGTERM, onhup); 242*7c478bd9Sstevel@tonic-gate if (signal(SIGEMT, SIG_IGN) == SIG_DFL) 243*7c478bd9Sstevel@tonic-gate signal(SIGEMT, onemt); 244*7c478bd9Sstevel@tonic-gate signal(SIGILL, oncore); 245*7c478bd9Sstevel@tonic-gate signal(SIGTRAP, oncore); 246*7c478bd9Sstevel@tonic-gate signal(SIGIOT, oncore); 247*7c478bd9Sstevel@tonic-gate signal(SIGFPE, oncore); 248*7c478bd9Sstevel@tonic-gate signal(SIGBUS, oncore); 249*7c478bd9Sstevel@tonic-gate signal(SIGSEGV, oncore); 250*7c478bd9Sstevel@tonic-gate signal(SIGPIPE, oncore); 251*7c478bd9Sstevel@tonic-gate init_re(); 252*7c478bd9Sstevel@tonic-gate while (1) { 253*7c478bd9Sstevel@tonic-gate #ifdef TRACE 254*7c478bd9Sstevel@tonic-gate while ((c = getopt(ac, (char **)av, "VU:Lc:Tvt:rlw:xRCsS")) != 255*7c478bd9Sstevel@tonic-gate EOF) 256*7c478bd9Sstevel@tonic-gate #else 257*7c478bd9Sstevel@tonic-gate while ((c = getopt(ac, (char **)av, 258*7c478bd9Sstevel@tonic-gate "VLc:vt:rlw:xRCsS")) != EOF) 259*7c478bd9Sstevel@tonic-gate #endif 260*7c478bd9Sstevel@tonic-gate switch (c) { 261*7c478bd9Sstevel@tonic-gate case 's': 262*7c478bd9Sstevel@tonic-gate hush = 1; 263*7c478bd9Sstevel@tonic-gate value(vi_AUTOPRINT) = 0; 264*7c478bd9Sstevel@tonic-gate fast++; 265*7c478bd9Sstevel@tonic-gate break; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate case 'R': 268*7c478bd9Sstevel@tonic-gate value(vi_READONLY) = 1; 269*7c478bd9Sstevel@tonic-gate break; 270*7c478bd9Sstevel@tonic-gate case 'S': 271*7c478bd9Sstevel@tonic-gate tags_flag = 1; 272*7c478bd9Sstevel@tonic-gate break; 273*7c478bd9Sstevel@tonic-gate #ifdef TRACE 274*7c478bd9Sstevel@tonic-gate case 'T': 275*7c478bd9Sstevel@tonic-gate tracef = (unsigned char *)"trace"; 276*7c478bd9Sstevel@tonic-gate goto trace; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate case 'U': 279*7c478bd9Sstevel@tonic-gate tracef = tttrace; 280*7c478bd9Sstevel@tonic-gate strcpy(tracef, optarg); 281*7c478bd9Sstevel@tonic-gate trace: 282*7c478bd9Sstevel@tonic-gate trace = fopen((char *)tracef, "w"); 283*7c478bd9Sstevel@tonic-gate #define tracbuf NULL 284*7c478bd9Sstevel@tonic-gate if (trace == NULL) 285*7c478bd9Sstevel@tonic-gate printf("Trace create error\n"); 286*7c478bd9Sstevel@tonic-gate else 287*7c478bd9Sstevel@tonic-gate setbuf(trace, (char *)tracbuf); 288*7c478bd9Sstevel@tonic-gate break; 289*7c478bd9Sstevel@tonic-gate #endif 290*7c478bd9Sstevel@tonic-gate case 'c': 291*7c478bd9Sstevel@tonic-gate if (optarg != NULL) 292*7c478bd9Sstevel@tonic-gate firstpat = (unsigned char *)optarg; 293*7c478bd9Sstevel@tonic-gate else 294*7c478bd9Sstevel@tonic-gate firstpat = (unsigned char *)""; 295*7c478bd9Sstevel@tonic-gate break; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate case 'l': 298*7c478bd9Sstevel@tonic-gate value(vi_LISP) = 1; 299*7c478bd9Sstevel@tonic-gate value(vi_SHOWMATCH) = 1; 300*7c478bd9Sstevel@tonic-gate break; 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate case 'r': 303*7c478bd9Sstevel@tonic-gate if (av[optind] && (c = av[optind][0]) && 304*7c478bd9Sstevel@tonic-gate c != '-') { 305*7c478bd9Sstevel@tonic-gate if ((strlen(av[optind])) >= 306*7c478bd9Sstevel@tonic-gate sizeof (savedfile)) { 307*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 308*7c478bd9Sstevel@tonic-gate "Recovered file name" 309*7c478bd9Sstevel@tonic-gate " too long\n")); 310*7c478bd9Sstevel@tonic-gate exit(1); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate rcvname = (unsigned char *)av[optind]; 314*7c478bd9Sstevel@tonic-gate optind++; 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate case 'L': 318*7c478bd9Sstevel@tonic-gate recov++; 319*7c478bd9Sstevel@tonic-gate break; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate case 'V': 322*7c478bd9Sstevel@tonic-gate verbose = 1; 323*7c478bd9Sstevel@tonic-gate break; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate case 't': 326*7c478bd9Sstevel@tonic-gate if (toptseen) { 327*7c478bd9Sstevel@tonic-gate usage(cmdnam); 328*7c478bd9Sstevel@tonic-gate exit(1); 329*7c478bd9Sstevel@tonic-gate } else { 330*7c478bd9Sstevel@tonic-gate toptseen++; 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate itag = 1; 333*7c478bd9Sstevel@tonic-gate if (strlcpy(lasttag, optarg, 334*7c478bd9Sstevel@tonic-gate sizeof (lasttag)) >= sizeof (lasttag)) { 335*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Tag" 336*7c478bd9Sstevel@tonic-gate " file name too long\n")); 337*7c478bd9Sstevel@tonic-gate exit(1); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate break; 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate case 'w': 342*7c478bd9Sstevel@tonic-gate defwind = 0; 343*7c478bd9Sstevel@tonic-gate if (optarg[0] == NULL) 344*7c478bd9Sstevel@tonic-gate defwind = 3; 345*7c478bd9Sstevel@tonic-gate else for (cp = (unsigned char *)optarg; 346*7c478bd9Sstevel@tonic-gate isdigit(*cp); cp++) 347*7c478bd9Sstevel@tonic-gate defwind = 10*defwind + *cp - '0'; 348*7c478bd9Sstevel@tonic-gate if (defwind < 0) 349*7c478bd9Sstevel@tonic-gate defwind = 3; 350*7c478bd9Sstevel@tonic-gate break; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate case 'C': 353*7c478bd9Sstevel@tonic-gate crflag = 1; 354*7c478bd9Sstevel@tonic-gate xflag = 1; 355*7c478bd9Sstevel@tonic-gate break; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate case 'x': 358*7c478bd9Sstevel@tonic-gate /* encrypted mode */ 359*7c478bd9Sstevel@tonic-gate xflag = 1; 360*7c478bd9Sstevel@tonic-gate crflag = -1; 361*7c478bd9Sstevel@tonic-gate break; 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate case 'v': 364*7c478bd9Sstevel@tonic-gate ivis = 1; 365*7c478bd9Sstevel@tonic-gate break; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate default: 368*7c478bd9Sstevel@tonic-gate usage(cmdnam); 369*7c478bd9Sstevel@tonic-gate exit(1); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate if (av[optind] && av[optind][0] == '+' && 372*7c478bd9Sstevel@tonic-gate av[optind-1] && strcmp(av[optind-1], "--")) { 373*7c478bd9Sstevel@tonic-gate firstpat = &av[optind][1]; 374*7c478bd9Sstevel@tonic-gate optind++; 375*7c478bd9Sstevel@tonic-gate continue; 376*7c478bd9Sstevel@tonic-gate } else if (av[optind] && av[optind][0] == '-' && 377*7c478bd9Sstevel@tonic-gate av[optind-1] && strcmp(av[optind-1], "--")) { 378*7c478bd9Sstevel@tonic-gate hush = 1; 379*7c478bd9Sstevel@tonic-gate value(vi_AUTOPRINT) = 0; 380*7c478bd9Sstevel@tonic-gate fast++; 381*7c478bd9Sstevel@tonic-gate optind++; 382*7c478bd9Sstevel@tonic-gate continue; 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate break; 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * If -V option is set and input is coming in via 389*7c478bd9Sstevel@tonic-gate * stdin then vi behavior should be ignored. The vi 390*7c478bd9Sstevel@tonic-gate * command should act like ex and only process ex commands 391*7c478bd9Sstevel@tonic-gate * and echo the input ex commands to stderr 392*7c478bd9Sstevel@tonic-gate */ 393*7c478bd9Sstevel@tonic-gate if (verbose == 1 && isatty(0) == 0) { 394*7c478bd9Sstevel@tonic-gate ivis = 0; 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate ac -= optind; 398*7c478bd9Sstevel@tonic-gate av = &av[optind]; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate for (argcounter = 0; argcounter < ac; argcounter++) { 401*7c478bd9Sstevel@tonic-gate if ((strlen(av[argcounter])) >= sizeof (savedfile)) { 402*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("File argument" 403*7c478bd9Sstevel@tonic-gate " too long\n")); 404*7c478bd9Sstevel@tonic-gate exit(1); 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate #ifdef SIGTSTP 409*7c478bd9Sstevel@tonic-gate if (!hush && signal(SIGTSTP, SIG_IGN) == SIG_DFL) 410*7c478bd9Sstevel@tonic-gate signal(SIGTSTP, onsusp), dosusp++; 411*7c478bd9Sstevel@tonic-gate #endif 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if (xflag) { 414*7c478bd9Sstevel@tonic-gate permflag = 1; 415*7c478bd9Sstevel@tonic-gate if ((kflag = run_setkey(perm, 416*7c478bd9Sstevel@tonic-gate (key = (unsigned char *)getpass( 417*7c478bd9Sstevel@tonic-gate gettext("Enter key:"))))) == -1) { 418*7c478bd9Sstevel@tonic-gate kflag = 0; 419*7c478bd9Sstevel@tonic-gate xflag = 0; 420*7c478bd9Sstevel@tonic-gate smerror(gettext("Encryption facility not available\n")); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate if (kflag == 0) 423*7c478bd9Sstevel@tonic-gate crflag = 0; 424*7c478bd9Sstevel@tonic-gate else { 425*7c478bd9Sstevel@tonic-gate strcpy(cryptkey, "CrYpTkEy=XXXXXXXXX"); 426*7c478bd9Sstevel@tonic-gate strcpy(cryptkey + 9, key); 427*7c478bd9Sstevel@tonic-gate if (putenv((char *)cryptkey) != 0) 428*7c478bd9Sstevel@tonic-gate smerror(gettext(" Cannot copy key to environment")); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC 433*7c478bd9Sstevel@tonic-gate /* 434*7c478bd9Sstevel@tonic-gate * Perform locale-specific initialization 435*7c478bd9Sstevel@tonic-gate */ 436*7c478bd9Sstevel@tonic-gate (void) localize(); 437*7c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate /* 440*7c478bd9Sstevel@tonic-gate * Initialize end of core pointers. 441*7c478bd9Sstevel@tonic-gate * Normally we avoid breaking back to fendcore after each 442*7c478bd9Sstevel@tonic-gate * file since this can be expensive (much core-core copying). 443*7c478bd9Sstevel@tonic-gate * If your system can scatter load processes you could do 444*7c478bd9Sstevel@tonic-gate * this as ed does, saving a little core, but it will probably 445*7c478bd9Sstevel@tonic-gate * not often make much difference. 446*7c478bd9Sstevel@tonic-gate */ 447*7c478bd9Sstevel@tonic-gate fendcore = (line *) sbrk(0); 448*7c478bd9Sstevel@tonic-gate endcore = fendcore - 2; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate /* 451*7c478bd9Sstevel@tonic-gate * If we are doing a recover and no filename 452*7c478bd9Sstevel@tonic-gate * was given, then execute an exrecover command with 453*7c478bd9Sstevel@tonic-gate * the -r option to type out the list of saved file names. 454*7c478bd9Sstevel@tonic-gate * Otherwise set the remembered file name to the first argument 455*7c478bd9Sstevel@tonic-gate * file name so the "recover" initial command will find it. 456*7c478bd9Sstevel@tonic-gate */ 457*7c478bd9Sstevel@tonic-gate if (recov) { 458*7c478bd9Sstevel@tonic-gate if (ac == 0 && (rcvname == NULL || *rcvname == NULL)) { 459*7c478bd9Sstevel@tonic-gate ppid = 0; 460*7c478bd9Sstevel@tonic-gate setrupt(); 461*7c478bd9Sstevel@tonic-gate execlp(EXRECOVER, "exrecover", "-r", (char *)0); 462*7c478bd9Sstevel@tonic-gate filioerr(EXRECOVER); 463*7c478bd9Sstevel@tonic-gate exit(++errcnt); 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate if (rcvname && *rcvname) 466*7c478bd9Sstevel@tonic-gate (void) strlcpy(savedfile, rcvname, sizeof (savedfile)); 467*7c478bd9Sstevel@tonic-gate else { 468*7c478bd9Sstevel@tonic-gate (void) strlcpy(savedfile, *av++, sizeof (savedfile)); 469*7c478bd9Sstevel@tonic-gate ac--; 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate /* 474*7c478bd9Sstevel@tonic-gate * Initialize the argument list. 475*7c478bd9Sstevel@tonic-gate */ 476*7c478bd9Sstevel@tonic-gate argv0 = av; 477*7c478bd9Sstevel@tonic-gate argc0 = ac; 478*7c478bd9Sstevel@tonic-gate args0 = av[0]; 479*7c478bd9Sstevel@tonic-gate erewind(); 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate /* 482*7c478bd9Sstevel@tonic-gate * Initialize a temporary file (buffer) and 483*7c478bd9Sstevel@tonic-gate * set up terminal environment. Read user startup commands. 484*7c478bd9Sstevel@tonic-gate */ 485*7c478bd9Sstevel@tonic-gate if (setexit() == 0) { 486*7c478bd9Sstevel@tonic-gate setrupt(); 487*7c478bd9Sstevel@tonic-gate intty = isatty(0); 488*7c478bd9Sstevel@tonic-gate value(vi_PROMPT) = intty; 489*7c478bd9Sstevel@tonic-gate if (((cp = (unsigned char *)getenv("SHELL")) != NULL) && 490*7c478bd9Sstevel@tonic-gate (*cp != '\0')) { 491*7c478bd9Sstevel@tonic-gate if (strlen(cp) < sizeof (shell)) { 492*7c478bd9Sstevel@tonic-gate (void) strlcpy(shell, cp, sizeof (shell)); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate if (fast) 496*7c478bd9Sstevel@tonic-gate setterm("dumb"); 497*7c478bd9Sstevel@tonic-gate else { 498*7c478bd9Sstevel@tonic-gate gettmode(); 499*7c478bd9Sstevel@tonic-gate cp = (unsigned char *)getenv("TERM"); 500*7c478bd9Sstevel@tonic-gate if (cp == NULL || *cp == '\0') 501*7c478bd9Sstevel@tonic-gate cp = (unsigned char *)"unknown"; 502*7c478bd9Sstevel@tonic-gate setterm(cp); 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate /* 507*7c478bd9Sstevel@tonic-gate * Bring up some code from init() 508*7c478bd9Sstevel@tonic-gate * This is still done in init later. This 509*7c478bd9Sstevel@tonic-gate * avoids null pointer problems 510*7c478bd9Sstevel@tonic-gate */ 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate dot = zero = truedol = unddol = dol = fendcore; 513*7c478bd9Sstevel@tonic-gate one = zero+1; 514*7c478bd9Sstevel@tonic-gate { 515*7c478bd9Sstevel@tonic-gate register int i; 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate for (i = 0; i <= 'z'-'a'+1; i++) 518*7c478bd9Sstevel@tonic-gate names[i] = 1; 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate if (setexit() == 0 && !fast) { 522*7c478bd9Sstevel@tonic-gate if ((globp = 523*7c478bd9Sstevel@tonic-gate (unsigned char *) getenv("EXINIT")) && *globp) { 524*7c478bd9Sstevel@tonic-gate if (ivis) 525*7c478bd9Sstevel@tonic-gate inexrc = 1; 526*7c478bd9Sstevel@tonic-gate commands(1, 1); 527*7c478bd9Sstevel@tonic-gate inexrc = 0; 528*7c478bd9Sstevel@tonic-gate } else { 529*7c478bd9Sstevel@tonic-gate globp = 0; 530*7c478bd9Sstevel@tonic-gate if ((cp = (unsigned char *) getenv("HOME")) != 531*7c478bd9Sstevel@tonic-gate 0 && *cp) { 532*7c478bd9Sstevel@tonic-gate strncpy(scratch, cp, sizeof (scratch) - 1); 533*7c478bd9Sstevel@tonic-gate strncat(scratch, "/.exrc", 534*7c478bd9Sstevel@tonic-gate sizeof (scratch) - 1 - strlen(scratch)); 535*7c478bd9Sstevel@tonic-gate if (ivis) 536*7c478bd9Sstevel@tonic-gate inexrc = 1; 537*7c478bd9Sstevel@tonic-gate if ((vret = validate_exrc(scratch)) == 0) { 538*7c478bd9Sstevel@tonic-gate source(scratch, 1); 539*7c478bd9Sstevel@tonic-gate } else { 540*7c478bd9Sstevel@tonic-gate if (vret == -1) { 541*7c478bd9Sstevel@tonic-gate error(gettext( 542*7c478bd9Sstevel@tonic-gate "Not owner of .exrc " 543*7c478bd9Sstevel@tonic-gate "or .exrc is group or " 544*7c478bd9Sstevel@tonic-gate "world writable")); 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate inexrc = 0; 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate /* 552*7c478bd9Sstevel@tonic-gate * Allow local .exrc if the "exrc" option was set. This 553*7c478bd9Sstevel@tonic-gate * loses if . is $HOME, but nobody should notice unless 554*7c478bd9Sstevel@tonic-gate * they do stupid things like putting a version command 555*7c478bd9Sstevel@tonic-gate * in .exrc. 556*7c478bd9Sstevel@tonic-gate * Besides, they should be using EXINIT, not .exrc, right? 557*7c478bd9Sstevel@tonic-gate */ 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate if (value(vi_EXRC)) { 560*7c478bd9Sstevel@tonic-gate if (ivis) 561*7c478bd9Sstevel@tonic-gate inexrc = 1; 562*7c478bd9Sstevel@tonic-gate if ((cp = (unsigned char *) getenv("PWD")) != 0 && 563*7c478bd9Sstevel@tonic-gate *cp) { 564*7c478bd9Sstevel@tonic-gate strncpy(exrcpath, cp, sizeof (exrcpath) - 1); 565*7c478bd9Sstevel@tonic-gate strncat(exrcpath, "/.exrc", 566*7c478bd9Sstevel@tonic-gate sizeof (exrcpath) - 1 - strlen(exrcpath)); 567*7c478bd9Sstevel@tonic-gate if (strcmp(scratch, exrcpath) != 0) { 568*7c478bd9Sstevel@tonic-gate if ((vret = 569*7c478bd9Sstevel@tonic-gate validate_exrc(exrcpath)) == 0) { 570*7c478bd9Sstevel@tonic-gate source(exrcpath, 1); 571*7c478bd9Sstevel@tonic-gate } else { 572*7c478bd9Sstevel@tonic-gate if (vret == -1) { 573*7c478bd9Sstevel@tonic-gate error(gettext( 574*7c478bd9Sstevel@tonic-gate "Not owner of " 575*7c478bd9Sstevel@tonic-gate ".exrc or .exrc " 576*7c478bd9Sstevel@tonic-gate "is group or world " 577*7c478bd9Sstevel@tonic-gate "writable")); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate inexrc = 0; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate init(); /* moved after prev 2 chunks to fix directory option */ 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate /* 589*7c478bd9Sstevel@tonic-gate * Initial processing. Handle tag, recover, and file argument 590*7c478bd9Sstevel@tonic-gate * implied next commands. If going in as 'vi', then don't do 591*7c478bd9Sstevel@tonic-gate * anything, just set initev so we will do it later (from within 592*7c478bd9Sstevel@tonic-gate * visual). 593*7c478bd9Sstevel@tonic-gate */ 594*7c478bd9Sstevel@tonic-gate if (setexit() == 0) { 595*7c478bd9Sstevel@tonic-gate if (recov) 596*7c478bd9Sstevel@tonic-gate globp = (unsigned char *)"recover"; 597*7c478bd9Sstevel@tonic-gate else if (itag) { 598*7c478bd9Sstevel@tonic-gate globp = ivis ? (unsigned char *)"tag" : 599*7c478bd9Sstevel@tonic-gate (unsigned char *)"tag|p"; 600*7c478bd9Sstevel@tonic-gate #ifdef XPG4 601*7c478bd9Sstevel@tonic-gate if (firstpat != NULL) { 602*7c478bd9Sstevel@tonic-gate /* 603*7c478bd9Sstevel@tonic-gate * if the user specified the -t and -c 604*7c478bd9Sstevel@tonic-gate * flags together, then we service these 605*7c478bd9Sstevel@tonic-gate * commands here. -t is handled first. 606*7c478bd9Sstevel@tonic-gate */ 607*7c478bd9Sstevel@tonic-gate savepat = firstpat; 608*7c478bd9Sstevel@tonic-gate firstpat = NULL; 609*7c478bd9Sstevel@tonic-gate inglobal = 1; 610*7c478bd9Sstevel@tonic-gate commands(1, 1); 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* now handle the -c argument: */ 613*7c478bd9Sstevel@tonic-gate globp = savepat; 614*7c478bd9Sstevel@tonic-gate commands(1, 1); 615*7c478bd9Sstevel@tonic-gate inglobal = 0; 616*7c478bd9Sstevel@tonic-gate globp = savepat = NULL; 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate /* the above isn't sufficient for ex mode: */ 619*7c478bd9Sstevel@tonic-gate if (!ivis) { 620*7c478bd9Sstevel@tonic-gate setdot(); 621*7c478bd9Sstevel@tonic-gate nonzero(); 622*7c478bd9Sstevel@tonic-gate plines(addr1, addr2, 1); 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate #endif /* XPG4 */ 626*7c478bd9Sstevel@tonic-gate } else if (argc) 627*7c478bd9Sstevel@tonic-gate globp = (unsigned char *)"next"; 628*7c478bd9Sstevel@tonic-gate if (ivis) 629*7c478bd9Sstevel@tonic-gate initev = globp; 630*7c478bd9Sstevel@tonic-gate else if (globp) { 631*7c478bd9Sstevel@tonic-gate inglobal = 1; 632*7c478bd9Sstevel@tonic-gate commands(1, 1); 633*7c478bd9Sstevel@tonic-gate inglobal = 0; 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate /* 638*7c478bd9Sstevel@tonic-gate * Vi command... go into visual. 639*7c478bd9Sstevel@tonic-gate */ 640*7c478bd9Sstevel@tonic-gate if (ivis) { 641*7c478bd9Sstevel@tonic-gate /* 642*7c478bd9Sstevel@tonic-gate * Don't have to be upward compatible 643*7c478bd9Sstevel@tonic-gate * by starting editing at line $. 644*7c478bd9Sstevel@tonic-gate */ 645*7c478bd9Sstevel@tonic-gate #ifdef XPG4 646*7c478bd9Sstevel@tonic-gate if (!itag && (dol > zero)) 647*7c478bd9Sstevel@tonic-gate #else /* XPG4 */ 648*7c478bd9Sstevel@tonic-gate if (dol > zero) 649*7c478bd9Sstevel@tonic-gate #endif /* XPG4 */ 650*7c478bd9Sstevel@tonic-gate dot = one; 651*7c478bd9Sstevel@tonic-gate globp = (unsigned char *)"visual"; 652*7c478bd9Sstevel@tonic-gate if (setexit() == 0) 653*7c478bd9Sstevel@tonic-gate commands(1, 1); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate /* 657*7c478bd9Sstevel@tonic-gate * Clear out trash in state accumulated by startup, 658*7c478bd9Sstevel@tonic-gate * and then do the main command loop for a normal edit. 659*7c478bd9Sstevel@tonic-gate * If you quit out of a 'vi' command by doing Q or ^\, 660*7c478bd9Sstevel@tonic-gate * you also fall through to here. 661*7c478bd9Sstevel@tonic-gate */ 662*7c478bd9Sstevel@tonic-gate seenprompt = 1; 663*7c478bd9Sstevel@tonic-gate ungetchar(0); 664*7c478bd9Sstevel@tonic-gate globp = 0; 665*7c478bd9Sstevel@tonic-gate initev = 0; 666*7c478bd9Sstevel@tonic-gate setlastchar('\n'); 667*7c478bd9Sstevel@tonic-gate setexit(); 668*7c478bd9Sstevel@tonic-gate commands(0, 0); 669*7c478bd9Sstevel@tonic-gate cleanup(1); 670*7c478bd9Sstevel@tonic-gate exit(errcnt); 671*7c478bd9Sstevel@tonic-gate } 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate /* 674*7c478bd9Sstevel@tonic-gate * Initialization, before editing a new file. 675*7c478bd9Sstevel@tonic-gate * Main thing here is to get a new buffer (in fileinit), 676*7c478bd9Sstevel@tonic-gate * rest is peripheral state resetting. 677*7c478bd9Sstevel@tonic-gate */ 678*7c478bd9Sstevel@tonic-gate init() 679*7c478bd9Sstevel@tonic-gate { 680*7c478bd9Sstevel@tonic-gate register int i; 681*7c478bd9Sstevel@tonic-gate void (*pstat)(); 682*7c478bd9Sstevel@tonic-gate fileinit(); 683*7c478bd9Sstevel@tonic-gate dot = zero = truedol = unddol = dol = fendcore; 684*7c478bd9Sstevel@tonic-gate one = zero+1; 685*7c478bd9Sstevel@tonic-gate undkind = UNDNONE; 686*7c478bd9Sstevel@tonic-gate chng = 0; 687*7c478bd9Sstevel@tonic-gate edited = 0; 688*7c478bd9Sstevel@tonic-gate for (i = 0; i <= 'z'-'a'+1; i++) 689*7c478bd9Sstevel@tonic-gate names[i] = 1; 690*7c478bd9Sstevel@tonic-gate anymarks = 0; 691*7c478bd9Sstevel@tonic-gate if (xflag) { 692*7c478bd9Sstevel@tonic-gate xtflag = 1; 693*7c478bd9Sstevel@tonic-gate /* ignore SIGINT before crypt process */ 694*7c478bd9Sstevel@tonic-gate pstat = signal(SIGINT, SIG_IGN); 695*7c478bd9Sstevel@tonic-gate if (tpermflag) 696*7c478bd9Sstevel@tonic-gate (void) crypt_close(tperm); 697*7c478bd9Sstevel@tonic-gate tpermflag = 1; 698*7c478bd9Sstevel@tonic-gate if (makekey(tperm) != 0) { 699*7c478bd9Sstevel@tonic-gate xtflag = 0; 700*7c478bd9Sstevel@tonic-gate smerror(gettext( 701*7c478bd9Sstevel@tonic-gate "Warning--Cannot encrypt temporary buffer\n")); 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate signal(SIGINT, pstat); 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate /* 708*7c478bd9Sstevel@tonic-gate * Return last component of unix path name p. 709*7c478bd9Sstevel@tonic-gate */ 710*7c478bd9Sstevel@tonic-gate unsigned char * 711*7c478bd9Sstevel@tonic-gate tailpath(p) 712*7c478bd9Sstevel@tonic-gate register unsigned char *p; 713*7c478bd9Sstevel@tonic-gate { 714*7c478bd9Sstevel@tonic-gate register unsigned char *r; 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate for (r = p; *p; p++) 717*7c478bd9Sstevel@tonic-gate if (*p == '/') 718*7c478bd9Sstevel@tonic-gate r = p+1; 719*7c478bd9Sstevel@tonic-gate return (r); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate /* 724*7c478bd9Sstevel@tonic-gate * validate_exrc - verify .exrc as belonging to the user. 725*7c478bd9Sstevel@tonic-gate * The file uid should match the process ruid, 726*7c478bd9Sstevel@tonic-gate * and the file should be writable only by the owner. 727*7c478bd9Sstevel@tonic-gate */ 728*7c478bd9Sstevel@tonic-gate static int 729*7c478bd9Sstevel@tonic-gate validate_exrc(unsigned char *exrc_path) 730*7c478bd9Sstevel@tonic-gate { 731*7c478bd9Sstevel@tonic-gate struct stat64 exrc_stat; 732*7c478bd9Sstevel@tonic-gate int process_uid; 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate if (stat64((char *)exrc_path, &exrc_stat) == -1) 735*7c478bd9Sstevel@tonic-gate return (0); /* ignore if .exrec is not found */ 736*7c478bd9Sstevel@tonic-gate process_uid = geteuid(); 737*7c478bd9Sstevel@tonic-gate /* if not root, uid must match file owner */ 738*7c478bd9Sstevel@tonic-gate if (process_uid && process_uid != exrc_stat.st_uid) 739*7c478bd9Sstevel@tonic-gate return (-1); 740*7c478bd9Sstevel@tonic-gate if ((exrc_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) 741*7c478bd9Sstevel@tonic-gate return (-1); 742*7c478bd9Sstevel@tonic-gate return (0); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate /* 746*7c478bd9Sstevel@tonic-gate * print usage message to stdout 747*7c478bd9Sstevel@tonic-gate */ 748*7c478bd9Sstevel@tonic-gate static void 749*7c478bd9Sstevel@tonic-gate usage(unsigned char *name) 750*7c478bd9Sstevel@tonic-gate { 751*7c478bd9Sstevel@tonic-gate char buf[160]; 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate #ifdef TRACE 754*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), gettext( 755*7c478bd9Sstevel@tonic-gate "Usage: %s [- | -s] [-l] [-L] [-wn] " 756*7c478bd9Sstevel@tonic-gate "[-R] [-S] [-r [file]] [-t tag] [-T] [-U tracefile]\n" 757*7c478bd9Sstevel@tonic-gate "[-v] [-V] [-x] [-C] [+cmd | -c cmd] file...\n"), name); 758*7c478bd9Sstevel@tonic-gate #else 759*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), gettext( 760*7c478bd9Sstevel@tonic-gate "Usage: %s [- | -s] [-l] [-L] [-wn] " 761*7c478bd9Sstevel@tonic-gate "[-R] [-S] [-r [file]] [-t tag]\n" 762*7c478bd9Sstevel@tonic-gate "[-v] [-V] [-x] [-C] [+cmd | -c cmd] file...\n"), name); 763*7c478bd9Sstevel@tonic-gate #endif 764*7c478bd9Sstevel@tonic-gate (void) write(2, buf, strlen(buf)); 765*7c478bd9Sstevel@tonic-gate } 766