diff options
author | jilles <jilles@FreeBSD.org> | 2011-04-23 22:28:56 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2011-04-23 22:28:56 +0000 |
commit | f250dc2f449b2e81b05be3a09647011b8a783e81 (patch) | |
tree | 1769bded7ead74e70ac17d9570ffab4c573e0ade /bin/sh/eval.c | |
parent | d98bdded177a447c277598fa1add5fef3738ed9f (diff) | |
download | FreeBSD-src-f250dc2f449b2e81b05be3a09647011b8a783e81.zip FreeBSD-src-f250dc2f449b2e81b05be3a09647011b8a783e81.tar.gz |
sh: Allow EV_EXIT through function calls, make {...} <redir more consistent.
If EV_EXIT causes an exit, use the exception mechanism to unwind
redirections and local variables. This way, if the final command is a
redirected command, an EXIT trap now executes without the redirections.
Because of these changes, EV_EXIT can now be inherited by the body of a
function, so do so. This means that a function no longer prevents a fork
before an exec being skipped, such as in
f() { head -1 /etc/passwd; }; echo $(f)
Wrapping a single builtin in a function may still cause an otherwise
unnecessary fork with command substitution, however.
An exit command or -e failure still invokes the EXIT trap with the
original redirections and local variables in place.
Note: this depends on SHELLPROC being gone. A SHELLPROC depended on
keeping the redirections and local variables and only cleaning up the
state to restore them.
Diffstat (limited to 'bin/sh/eval.c')
-rw-r--r-- | bin/sh/eval.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 793248b..6f89041 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -179,7 +179,7 @@ evalstring(char *s, int flags) if (!any) exitstatus = 0; if (flags_exit) - exitshell(exitstatus); + exraise(EXEXIT); } @@ -285,8 +285,10 @@ evaltree(union node *n, int flags) out: if (pendingsigs) dotrap(); - if ((flags & EV_EXIT) || (eflag && exitstatus != 0 && do_etest)) + if (eflag && exitstatus != 0 && do_etest) exitshell(exitstatus); + if (flags & EV_EXIT) + exraise(EXEXIT); } @@ -440,8 +442,8 @@ evalredir(union node *n, int flags) handler = savehandler; e = exception; + popredir(); if (e == EXERROR || e == EXEXEC) { - popredir(); if (in_redirect) { exitstatus = 2; return; @@ -927,8 +929,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) if (setjmp(jmploc.loc)) { freeparam(&shellparam); shellparam = saveparam; - if (exception == EXERROR || exception == EXEXEC) - popredir(); + popredir(); unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; @@ -943,10 +944,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) for (sp = varlist.list ; sp ; sp = sp->next) mklocal(sp->text); exitstatus = oexitstatus; - if (flags & EV_TESTED) - evaltree(getfuncnode(cmdentry.u.func), EV_TESTED); - else - evaltree(getfuncnode(cmdentry.u.func), 0); + evaltree(getfuncnode(cmdentry.u.func), + flags & (EV_TESTED | EV_EXIT)); INTOFF; unreffunc(cmdentry.u.func); poplocalvars(); @@ -982,7 +981,10 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) savehandler = handler; if (setjmp(jmploc.loc)) { e = exception; - exitstatus = (e == EXINT)? SIGINT+128 : 2; + if (e == EXINT) + exitstatus = SIGINT+128; + else if (e != EXEXIT) + exitstatus = 2; goto cmddone; } handler = &jmploc; @@ -1018,8 +1020,7 @@ cmddone: backcmd->nleft = memout.nextc - memout.buf; memout.buf = NULL; } - if (cmdentry.u.index != EXECCMD && - (e == -1 || e == EXERROR || e == EXEXEC)) + if (cmdentry.u.index != EXECCMD) popredir(); if (e != -1) { if ((e != EXERROR && e != EXEXEC) |