summaryrefslogtreecommitdiffstats
path: root/bin/sh/eval.c
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2011-06-12 23:06:04 +0000
committerjilles <jilles@FreeBSD.org>2011-06-12 23:06:04 +0000
commit91789615b49a87147298eee12c9b111d8c1b64c9 (patch)
treeb1cbd950b159dbb3fa6211ba5a7f7fb7709a612e /bin/sh/eval.c
parent5f2600c6a978923a3904716ce73814baca63fd0f (diff)
downloadFreeBSD-src-91789615b49a87147298eee12c9b111d8c1b64c9.zip
FreeBSD-src-91789615b49a87147298eee12c9b111d8c1b64c9.tar.gz
sh: Save/restore changed variables in optimized command substitution.
In optimized command substitution, save and restore any variables changed by expansions (${var=value} and $((var=assigned))), instead of trying to determine if an expansion may cause such changes. If $! is referenced in optimized command substitution, do not cause jobs to be remembered longer. This fixes $(jobs $!) again, simplifies the man page and shortens the code.
Diffstat (limited to 'bin/sh/eval.c')
-rw-r--r--bin/sh/eval.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 92a18e4..9d67b9e 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -571,14 +571,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);
}
/*
@@ -596,6 +590,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;
@@ -608,12 +603,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 {
@@ -621,6 +622,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)
OpenPOWER on IntegriCloud