summaryrefslogtreecommitdiffstats
path: root/bin/sh/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sh/eval.c')
-rw-r--r--bin/sh/eval.c47
1 files changed, 30 insertions, 17 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index a50c53f..d5da7d3 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -140,7 +140,7 @@ evalcmd(int argc, char **argv)
STPUTC('\0', concat);
p = grabstackstr(concat);
}
- evalstring(p, builtin_flags & EV_TESTED);
+ evalstring(p, builtin_flags);
} else
exitstatus = 0;
return exitstatus;
@@ -165,7 +165,7 @@ evalstring(char *s, int flags)
setstackmark(&smark);
setinputstring(s, 1);
while ((n = parsecmd(0)) != NEOF) {
- if (n != NULL) {
+ if (n != NULL && !nflag) {
if (flags_exit && preadateof())
evaltree(n, flags | EV_EXIT);
else
@@ -386,6 +386,14 @@ evalcase(union node *n, int flags)
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
+ while (cp->nclist.next &&
+ cp->type == NCLISTFALLTHRU) {
+ if (evalskip != 0)
+ break;
+ evaltree(cp->nclist.body,
+ flags & ~EV_EXIT);
+ cp = cp->nclist.next;
+ }
if (evalskip == 0) {
evaltree(cp->nclist.body, flags);
}
@@ -409,6 +417,7 @@ evalsubshell(union node *n, int flags)
struct job *jp;
int backgnd = (n->type == NBACKGND);
+ oexitstatus = exitstatus;
expredir(n->nredir.redirect);
if ((!backgnd && flags & EV_EXIT && !have_traps()) ||
forkshell(jp = makejob(n, 1), n, backgnd) == 0) {
@@ -436,6 +445,7 @@ evalredir(union node *n, int flags)
struct jmploc *savehandler;
volatile int in_redirect = 1;
+ oexitstatus = exitstatus;
expredir(n->nredir.redirect);
savehandler = handler;
if (setjmp(jmploc.loc)) {
@@ -478,7 +488,6 @@ expredir(union node *n)
for (redir = n ; redir ; redir = redir->nfile.next) {
struct arglist fn;
fn.lastp = &fn.list;
- oexitstatus = exitstatus;
switch (redir->type) {
case NFROM:
case NTO:
@@ -570,14 +579,8 @@ evalpipe(union node *n)
static int
is_valid_fast_cmdsubst(union node *n)
{
- union node *argp;
- if (n->type != NCMD)
- return 0;
- for (argp = n->ncmd.args ; argp ; argp = argp->narg.next)
- if (expandhassideeffects(argp->narg.text))
- return 0;
- return 1;
+ return (n->type == NCMD);
}
/*
@@ -595,6 +598,7 @@ evalbackcmd(union node *n, struct backcmd *result)
struct stackmark smark; /* unnecessary */
struct jmploc jmploc;
struct jmploc *savehandler;
+ struct localvar *savelocalvars;
setstackmark(&smark);
result->fd = -1;
@@ -607,12 +611,18 @@ evalbackcmd(union node *n, struct backcmd *result)
}
if (is_valid_fast_cmdsubst(n)) {
exitstatus = oexitstatus;
+ savelocalvars = localvars;
+ localvars = NULL;
+ forcelocal++;
savehandler = handler;
if (setjmp(jmploc.loc)) {
if (exception == EXERROR || exception == EXEXEC)
exitstatus = 2;
else if (exception != 0) {
handler = savehandler;
+ forcelocal--;
+ poplocalvars();
+ localvars = savelocalvars;
longjmp(handler->loc, 1);
}
} else {
@@ -620,6 +630,9 @@ evalbackcmd(union node *n, struct backcmd *result)
evalcommand(n, EV_BACKCMD, result);
}
handler = savehandler;
+ forcelocal--;
+ poplocalvars();
+ localvars = savelocalvars;
} else {
exitstatus = 0;
if (pipe(pip) < 0)
@@ -744,8 +757,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
/* Print the command if xflag is set. */
if (xflag) {
char sep = 0;
- const char *p;
- out2str(ps4val());
+ const char *p, *ps4;
+ ps4 = expandstr(ps4val());
+ out2str(ps4 != NULL ? ps4 : ps4val());
for (sp = varlist.list ; sp ; sp = sp->next) {
if (sep != 0)
out2c(' ');
@@ -880,14 +894,13 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
}
/* Fork off a child process if necessary. */
- if (cmd->ncmd.backgnd
- || ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
+ if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
&& ((flags & EV_EXIT) == 0 || have_traps()))
|| ((flags & EV_BACKCMD) != 0
&& (cmdentry.cmdtype != CMDBUILTIN ||
!safe_builtin(cmdentry.u.index, argc, argv)))) {
jp = makejob(cmd, 1);
- mode = cmd->ncmd.backgnd;
+ mode = FORK_FG;
if (flags & EV_BACKCMD) {
mode = FORK_NOJOB;
if (pipe(pip) < 0)
@@ -902,6 +915,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
dup2(pip[1], 1);
close(pip[1]);
}
+ flags &= ~EV_BACKCMD;
}
flags |= EV_EXIT;
}
@@ -1053,8 +1067,7 @@ parent: /* parent process gets here (if we forked) */
backcmd->fd = pip[0];
close(pip[1]);
backcmd->jp = jp;
- } else
- exitstatus = 0;
+ }
out:
if (lastarg)
OpenPOWER on IntegriCloud