/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* Copyright (c) 1981 Regents of the University of California */
#include "ex.h"
#include "ex_argv.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#ifdef TRACE
#endif
char *strrchr();
void init_re(void);
/*
* The code for ex is divided as follows:
*
* ex.c Entry point and routines handling interrupt, hangup
* signals; initialization code.
*
* ex_addr.c Address parsing routines for command mode decoding.
* Routines to set and check address ranges on commands.
*
* ex_cmds.c Command mode command decoding.
*
* ex_cmds2.c Subroutines for command decoding and processing of
* file names in the argument list. Routines to print
* messages and reset state when errors occur.
*
* ex_cmdsub.c Subroutines which implement command mode functions
* such as append, delete, join.
*
* ex_data.c Initialization of options.
*
* ex_get.c Command mode input routines.
*
* escapes, filtering, source commands, preserving
* and recovering.
*
* ex_put.c Terminal driving and optimizing routines for low-level
* output (cursor-positioning); output line formatting
* routines.
*
* ex_re.c Global commands, substitute, regular expression
* compilation and execution.
*
* ex_set.c The set command.
*
* ex_subr.c Loads of miscellaneous subroutines.
*
* ex_temp.c Editor buffer routines for main buffer and also
* for named buffers (Q registers if you will.)
*
* ex_tty.c Terminal dependent initializations from termcap
* data base, grabbing of tty modes (at beginning
* and after escapes).
*
* ex_unix.c Routines for the ! command and its variations.
*
* guide to the overall organization.
*/
/*
* the version command (":ver").
*/
/* variable used by ":ver" command */
/*
* NOTE: when changing the Version number, it must be changed in the
* following files:
*
*
*/
#ifdef XPG4
#endif /* XPG4 */
/*
* Main procedure. Process arguments and then
* transfer control to the main command processing loop
* in the routine commands. We are entered as either "ex", "edit", "vi"
* or "view" and the distinction is made here. For edit we just diddle options;
* for vi we actually force an early visual command.
*/
static void usage(unsigned char *);
static int validate_exrc(unsigned char *);
void init(void);
int
{
extern char *optarg;
extern int optind;
unsigned char *rcvname = 0;
unsigned char *cp;
int c;
unsigned char *cmdnam;
bool recov = 0;
bool ivis = 0;
bool itag = 0;
bool fast = 0;
extern int verbose;
int argcounter = 0;
extern int tags_flag; /* Set if tag file is not sorted (-S flag) */
int vret = 0;
int toptseen = 0;
#ifdef TRACE
unsigned char *tracef;
#endif
tagflg = 0;
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
/*
* Immediately grab the tty modes so that we won't
* get messed up if an interrupt comes in quickly.
*/
(void) gTTY(2);
/* Note - this will core dump if you didn't -DSINGLE in CFLAGS */
lines = 24;
/*
* Defend against d's, v's, w's, and a's in directories of
* path leading to our true name.
*/
cmdnam++;
else
ivis = 1;
ivis = 1;
ivis = 1;
}
#ifdef XPG4
{
char *envptr;
}
envlines = -1;
}
}
envcolumns = -1;
}
}
}
#endif /* XPG4 */
draino();
pstop();
/*
* Initialize interrupt handling.
*/
init_re();
while (1) {
#ifdef TRACE
EOF)
#else
"VLc:vt:rlw:xRCsS")) != EOF)
#endif
switch (c) {
case 's':
hush = 1;
value(vi_AUTOPRINT) = 0;
fast++;
break;
case 'R':
break;
case 'S':
tags_flag = 1;
break;
#ifdef TRACE
case 'T':
tracef = (unsigned char *)"trace";
goto trace;
case 'U':
viprintf("Trace create error\n");
else
break;
#endif
case 'c':
else
firstpat = (unsigned char *)"";
break;
case 'l':
break;
case 'r':
c != '-') {
sizeof (savedfile)) {
"Recovered file name"
" too long\n"));
exit(1);
}
optind++;
}
case 'L':
recov++;
break;
case 'V':
verbose = 1;
break;
case 't':
if (toptseen) {
exit(1);
} else {
toptseen++;
}
" file name too long\n"));
exit(1);
}
break;
case 'w':
defwind = 0;
defwind = 3;
if (defwind < 0)
defwind = 3;
break;
case 'C':
crflag = 1;
xflag = 1;
break;
case 'x':
/* encrypted mode */
xflag = 1;
crflag = -1;
break;
case 'v':
ivis = 1;
break;
default:
exit(1);
}
optind++;
continue;
hush = 1;
value(vi_AUTOPRINT) = 0;
fast++;
optind++;
continue;
}
break;
}
if (isatty(0) == 0) {
/*
* If -V option is set and input is coming in via
* stdin then vi behavior should be ignored. The vi
* command should act like ex and only process ex commands
* and echo the input ex commands to stderr
*/
if (verbose == 1) {
ivis = 0;
}
/*
* If the standard input is not a terminal device,
* it is as if the -s option has been specified.
*/
if (ivis == 0) {
hush = 1;
value(vi_AUTOPRINT) = 0;
fast++;
}
}
" too long\n"));
exit(1);
}
}
#ifdef SIGTSTP
#endif
if (xflag) {
permflag = 1;
kflag = 0;
xflag = 0;
}
if (kflag == 0)
crflag = 0;
else {
}
}
#ifndef PRESUNEUC
/*
* Perform locale-specific initialization
*/
localize();
#endif /* PRESUNEUC */
/*
* Initialize end of core pointers.
* Normally we avoid breaking back to fendcore after each
* file since this can be expensive (much core-core copying).
* If your system can scatter load processes you could do
* this as ed does, saving a little core, but it will probably
* not often make much difference.
*/
/*
* If we are doing a recover and no filename
* was given, then execute an exrecover command with
* the -r option to type out the list of saved file names.
* Otherwise set the remembered file name to the first argument
* file name so the "recover" initial command will find it.
*/
if (recov) {
ppid = 0;
setrupt();
}
else {
ac--;
}
}
/*
* Initialize the argument list.
*/
erewind();
/*
* Initialize a temporary file (buffer) and
* set up terminal environment. Read user startup commands.
*/
if (setexit() == 0) {
setrupt();
(*cp != '\0')) {
}
}
if (fast)
setterm((unsigned char *)"dumb");
else {
gettmode();
cp = (unsigned char *)"unknown";
}
}
/*
* Bring up some code from init()
* This is still done in init later. This
* avoids null pointer problems
*/
{
int i;
for (i = 0; i <= 'z'-'a'+1; i++)
names[i] = 1;
}
if ((globp =
if (ivis)
inexrc = 1;
inexrc = 0;
} else {
globp = 0;
0 && *cp) {
if (ivis)
inexrc = 1;
} else {
if (vret == -1) {
"Not owner of .exrc "
"or .exrc is group or "
"world writable"));
}
}
inexrc = 0;
}
}
/*
* Allow local .exrc if the "exrc" option was set. This
* loses if . is $HOME, but nobody should notice unless
* they do stupid things like putting a version command
* in .exrc.
* Besides, they should be using EXINIT, not .exrc, right?
*/
if (ivis)
inexrc = 1;
*cp) {
if ((vret =
validate_exrc(exrcpath)) == 0) {
} else {
if (vret == -1) {
"Not owner of "
".exrc or .exrc "
"is group or world "
"writable"));
}
}
}
}
inexrc = 0;
}
}
init(); /* moved after prev 2 chunks to fix directory option */
/*
* Initial processing. Handle tag, recover, and file argument
* implied next commands. If going in as 'vi', then don't do
* anything, just set initev so we will do it later (from within
* visual).
*/
if (setexit() == 0) {
if (recov)
globp = (unsigned char *)"recover";
else if (itag) {
(unsigned char *)"tag|p";
#ifdef XPG4
/*
* if the user specified the -t and -c
* flags together, then we service these
* commands here. -t is handled first.
*/
inglobal = 1;
/* now handle the -c argument: */
inglobal = 0;
/* the above isn't sufficient for ex mode: */
if (!ivis) {
setdot();
nonzero();
}
}
#endif /* XPG4 */
} else if (argc)
globp = (unsigned char *)"next";
if (ivis)
else if (globp) {
inglobal = 1;
inglobal = 0;
}
}
/*
* Vi command... go into visual.
*/
if (ivis) {
/*
* Don't have to be upward compatible
* by starting editing at line $.
*/
#ifdef XPG4
#else /* XPG4 */
#endif /* XPG4 */
globp = (unsigned char *)"visual";
if (setexit() == 0)
}
/*
* Clear out trash in state accumulated by startup,
* and then do the main command loop for a normal edit.
* If you quit out of a 'vi' command by doing Q or ^\,
* you also fall through to here.
*/
seenprompt = 1;
ungetchar(0);
globp = 0;
initev = 0;
setlastchar('\n');
setexit();
commands(0, 0);
cleanup(1);
return (errcnt);
}
/*
* Initialization, before editing a new file.
* Main thing here is to get a new buffer (in fileinit),
* rest is peripheral state resetting.
*/
void
init(void)
{
int i;
void (*pstat)();
fileinit();
chng = 0;
edited = 0;
for (i = 0; i <= 'z'-'a'+1; i++)
names[i] = 1;
anymarks = 0;
if (xflag) {
xtflag = 1;
/* ignore SIGINT before crypt process */
if (tpermflag)
(void) crypt_close(tperm);
tpermflag = 1;
xtflag = 0;
"Warning--Cannot encrypt temporary buffer\n"));
}
}
}
/*
* Return last component of unix path name p.
*/
unsigned char *
tailpath(p)
unsigned char *p;
{
unsigned char *r;
for (r = p; *p; p++)
if (*p == '/')
r = p+1;
return (r);
}
/*
* validate_exrc - verify .exrc as belonging to the user.
* The file uid should match the process ruid,
* and the file should be writable only by the owner.
*/
static int
{
int process_uid;
return (0); /* ignore if .exrec is not found */
process_uid = geteuid();
/* if not root, uid must match file owner */
return (-1);
return (-1);
return (0);
}
/*
* print usage message to stdout
*/
static void
{
#ifdef TRACE
"Usage: %s [- | -s] [-l] [-L] [-wn] "
"[-R] [-S] [-r [file]] [-t tag] [-T] [-U tracefile]\n"
"[-v] [-V] [-x] [-C] [+cmd | -c cmd] file...\n"), name);
#else
"Usage: %s [- | -s] [-l] [-L] [-wn] "
"[-R] [-S] [-r [file]] [-t tag]\n"
"[-v] [-V] [-x] [-C] [+cmd | -c cmd] file...\n"), name);
#endif
}