1
0
Files
irix-657m-src/eoe/cmd/sh/xec.c
2022-09-29 17:59:04 +03:00

554 lines
10 KiB
C

/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)sh:xec.c 1.28.17.1"
/*
*
* UNIX shell
*
*/
#include "defs.h"
#include <errno.h>
#include "sym.h"
#include "hash.h"
#include <sys/types.h>
#include <sys/times.h>
pid_t parent;
static void execprint();
extern pid_t getpid();
extern pid_t fork();
extern int close();
extern int gmatch();
static int posix_path();
/* ======== command execution ========*/
/*VARARGS*/
int
execute(argt, xflags, errorflg, pf1, pf2)
struct trenod *argt;
int *pf1, *pf2;
{
/*
* `stakbot' is preserved by this routine
*/
register struct trenod *t;
unsigned char *sav = savstak();
sigchk();
if (!errorflg)
flags &= ~errflg;
t = argt;
if (t && execbrk == 0) {
register int treeflgs;
register unsigned char **com;
int type;
short pos;
treeflgs = t->tretyp;
type = treeflgs & COMMSK;
switch (type)
{
case TFND:
{
struct fndnod *f = (struct fndnod *)t;
struct namnod *n = lookup(f->fndnam);
exitval = 0;
if (n->namflg & N_RDONLY)
failed(0, n->namid, wtfailed, wtfailedid);
if (flags & rshflg && (n == &pathnod ||
eq(n->namid, "SHELL")))
failed(0, n->namid, restricted, restrictedid);
if (n->namflg & N_FUNCTN)
freefunc(n);
else
{
free(n->namval);
free(n->namenv);
n->namval = 0;
n->namflg &= ~(N_EXPORT | N_ENVCHG);
}
if (funcnt)
f->fndval->tretyp++;
n->namenv = (unsigned char *)f->fndval;
attrib(n, N_FUNCTN);
hash_func(n->namid);
break;
}
case TCOM:
{
int argn;
struct argnod *schain = gchain;
struct ionod *io = t->treio;
short cmdhash;
short comtype;
exitval = 0;
gchain = 0;
argn = getarg(t);
com = scan(argn);
gchain = schain;
if (argn != 0)
cmdhash = pathlook(com[0], 1, comptr(t)->comset);
if (argn == 0 || (comtype = hashtype(cmdhash)) == BUILTIN) {
setlist(comptr(t)->comset, 0);
setwidth();
}
/*
* For unique ksh builtin names that are not function names,
* look for the first found in a path search.
*/
if( argn != 0 && !any('/', com[0]) && comtype != FUNCTION &&
syslook(com[0],ksh_commands,no_ksh_commands))
{
register int cnt;
if ((cnt = findpath(com[0], 0)) > 0)
{
register unsigned char *path;
int len;
path = getpath(com[0]);
while (--cnt && path)
path = nextpath(path);
catpath(path,com[0]);
if(posix_path(curstak(),com[0])){
failure(0, *com, posix_builtin, posix_builtin_id);
break;
}
}
}
if (argn && (flags&noexec) == 0)
{
/* print command if execpr */
if (flags & execpr)
execprint(com);
if (comtype == NOTFOUND)
{
pos = hashdata(cmdhash);
if (pos == 1)
failure(0, *com, notfound, notfoundid);
else if (pos == 2)
failure(0, *com, badexec, badexecid);
else
failure(0, *com, badperm, badpermid);
break;
}
else if (comtype == PATH_COMMAND)
{
pos = -1;
}
else if (comtype & (COMMAND | REL_COMMAND))
{
pos = hashdata(cmdhash);
}
else if (comtype == BUILTIN) {
builtin(hashdata(cmdhash),argn,com,t);
freejobs();
break;
}
else if (comtype == FUNCTION)
{
struct dolnod *olddolh;
struct namnod *n;
short index;
unsigned char **olddolv = dolv;
int olddolc = dolc;
n = findnam(com[0]);
/* save current positional parameters */
olddolh = (struct dolnod *)savargs(funcnt);
funcnt++;
index = initio(io, 1);
setargs(com);
execute((struct trenod *)(n->namenv), xflags, errorflg, pf1, pf2);
execbrk = 0;
restore(index);
restorargs(olddolh, funcnt);
dolv = olddolv;
dolc = olddolc;
funcnt--;
break;
}
}
else if (t->treio == 0)
{
chktrap();
break;
}
}
case TFORK: /*FALLTHROUGH*/
{
int monitor = 0;
int linked = 0;
exitval = 0;
if (!(xflags & XEC_EXECED) || treeflgs&(FPOU|FAMP))
{
int forkcnt = 1;
if (!(treeflgs&FPOU))
{
monitor = (!(xflags & XEC_NOSTOP)
&& (flags&(monitorflg|jcflg|jcoff))
== (monitorflg|jcflg));
if (monitor) {
int savefd;
unsigned char *savebot;
savefd = setb(-1);
savebot = stakbot;
prcmd(t);
(void)setb(savefd);
allocjob(savebot, cwdget(), monitor);
} else
allocjob("", "", 0);
}
if (treeflgs & (FPOU|FAMP)) {
link_iodocs(iotemp);
linked = 1;
}
while ((parent = fork()) == -1)
{
/*
* FORKLIM is the max period between forks -
* power of 2 usually. Currently shell tries
* after 2,4,8,16, and 32 seconds and then quits
*/
if ((forkcnt = (forkcnt * 2)) > FORKLIM)
{
switch (errno)
{
case ENOMEM:
deallocjob();
error(0, noswap, noswapid);
break;
default:
deallocjob();
error(0, nofork, noforkid);
break;
}
}
sigchk();
mysleep(forkcnt);
}
if (parent) {
if (treeflgs & FPIN)
closepipe(pf1);
if (!(treeflgs&FPOU)) {
postjob(parent,!(treeflgs&FAMP));
freejobs();
}
chktrap();
break;
}
mypid = getpid();
}
flags |= (forked|jcoff);
fiotemp = 0;
if (linked == 1) {
swap_iodoc_nm(iotemp);
xflags |= XEC_LINKED;
} else if (!(xflags & XEC_LINKED))
iotemp = 0;
#ifdef ACCT
suspacct();
#endif
settmp();
oldsigs();
if (!(treeflgs & FPOU))
makejob(monitor, !(treeflgs & FAMP));
/*
* pipe in or out
*/
if (treeflgs & FPIN)
{
renam(pf1[INPIPE], 0);
(void)close(pf1[OTPIPE]);
}
if (treeflgs & FPOU)
{
(void)close(pf2[INPIPE]);
renam(pf2[OTPIPE], 1);
}
/*
* io redirection
*/
initio(t->treio, 0);
if (type == TFORK)
execute(forkptr(t)->forktre, xflags | XEC_EXECED, errorflg);
else if (com[0] != ENDARGS)
{
eflag = 0;
setlist(comptr(t)->comset, N_EXPORT);
rmtemp(0);
clearjobs();
execa(com, pos);
}
done(0);
}
/*NOTREACHED*/
case TPAR:
/*
* Original line caused problems whith sub-shells
* in jsh:
* flags &= ~jcoff;
* changed to:
* flags &= jcoff;
*
* sgi: this causes -e to not propagate, which is
* more important than unspecified problems in jsh.
* It's also not at all apparent that the above fix
* is correct.
*/
flags &= ~jcoff;
clearjobs();
execute(parptr(t)->partre, xflags|XEC_NOSTOP, errorflg);
done(0);
/*NOTREACHED*/
case TFIL:
{
int pv[2];
chkpipe(pv);
if (execute(lstptr(t)->lstlef, xflags & XEC_NOSTOP, errorflg, pf1, pv) == 0)
execute(lstptr(t)->lstrit, xflags, errorflg, pv, pf2);
else
closepipe(pv);
}
break;
case TBRA:
execute(parptr(t)->partre, xflags|XEC_NOSTOP, errorflg);
break;
case TLST:
execute(lstptr(t)->lstlef, xflags&XEC_NOSTOP, eflag);
execute(lstptr(t)->lstrit, xflags, eflag);
break;
case TAND:
case TORF:
{
register xval;
xval = execute(lstptr(t)->lstlef, XEC_NOSTOP, 0);
if ((xval == 0) == (type == TAND))
execute(lstptr(t)->lstrit, xflags|XEC_NOSTOP, errorflg);
break;
}
case TFOR:
{
struct namnod *n = lookup(forptr(t)->fornam);
unsigned char **args;
struct dolnod *argsav = 0;
if (forptr(t)->forlst == 0)
{
args = dolv + 1;
argsav = useargs();
}
else
{
struct argnod *schain = gchain;
gchain = 0;
args = scan(getarg(forptr(t)->forlst));
gchain = schain;
}
loopcnt++;
while (*args != ENDARGS && execbrk == 0)
{
assign(n, *args++);
execute(forptr(t)->fortre, XEC_NOSTOP, errorflg);
if (breakcnt < 0)
execbrk = (++breakcnt != 0);
}
if (breakcnt > 0)
execbrk = (--breakcnt != 0);
loopcnt--;
if(argsav)
argfor = (struct dolnod *)freeargs(argsav);
}
break;
case TWH:
case TUN:
{
int i = 0;
loopcnt++;
while (execbrk == 0 && (execute(whptr(t)->whtre, XEC_NOSTOP, 0) == 0) == (type == TWH))
{
i = execute(whptr(t)->dotre, XEC_NOSTOP, errorflg);
if(flags & noexec) {
break;
}
if (breakcnt < 0)
execbrk = (++breakcnt != 0);
}
if (breakcnt > 0)
execbrk = (--breakcnt != 0);
loopcnt--;
exitval = i;
}
break;
case TIF:
if (execute(ifptr(t)->iftre, XEC_NOSTOP, 0) == 0)
execute(ifptr(t)->thtre, xflags|XEC_NOSTOP, errorflg);
else if (ifptr(t)->eltre)
execute(ifptr(t)->eltre, xflags|XEC_NOSTOP, errorflg);
else
exitval = 0; /* force zero exit for if-then-fi */
break;
case TSW:
{
register unsigned char *r = mactrim(swptr(t)->swarg);
register struct regnod *regp;
regp = swptr(t)->swlst;
while (regp)
{
struct argnod *rex = regp->regptr;
while (rex)
{
register unsigned char *s;
if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s)))
{
execute(regp->regcom, XEC_NOSTOP, errorflg);
regp = 0;
break;
}
else
rex = rex->argnxt;
}
if (regp)
regp = regp->regnxt;
}
}
break;
}
exitset();
}
sigchk();
tdystak(sav);
flags |= eflag;
return(exitval);
}
void
execexp(s, f)
unsigned char *s;
int f;
{
struct fileblk fb;
push(&fb);
if (s)
{
estabf(s);
fb.feval = (unsigned char **)(f);
}
else if (f >= 0)
initf(f);
execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg));
pop();
}
static void
execprint(com)
unsigned char **com;
{
register int argn = 0;
prs(execpmsg);
while(com[argn] != ENDARGS)
{
prs(com[argn++]);
blank();
}
newline();
}
/* Determine if the command in path is in /sbin/... the POSIX builtins */
static int
posix_path(path,cmd)
char *path,*cmd;
{
char *sbin = "/sbin/";
if(*path && *cmd)
{
/* Match '/sbin/' first */
while(*path && *sbin && *path == *sbin)
{
++path; ++sbin;
}
/* Check if not completed sbin_path or completed path */
if(*sbin || *path == 0)
return(0);
/* Compare balance of path with command */
while(*path && *cmd && *path == *cmd)
{
++path; ++cmd;
}
if(*path == 0 && *cmd == 0)
return(1);
return(0);
}
return(0);
}