diff options
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/eval.c | 2 | ||||
-rw-r--r-- | bin/sh/eval.h | 1 | ||||
-rw-r--r-- | bin/sh/trap.c | 33 |
3 files changed, 34 insertions, 2 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c index ea23a9d..f4f69d9 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -75,7 +75,7 @@ __FBSDID("$FreeBSD$"); int evalskip; /* set if we are skipping commands */ -static int skipcount; /* number of levels to skip */ +int skipcount; /* number of levels to skip */ MKINIT int loopnest; /* current loop nesting level */ int funcnest; /* depth of function calls */ static int builtin_flags; /* evalcommand flags for builtins */ diff --git a/bin/sh/eval.h b/bin/sh/eval.h index fba6f9a..724e157 100644 --- a/bin/sh/eval.h +++ b/bin/sh/eval.h @@ -60,6 +60,7 @@ void evalbackcmd(union node *, struct backcmd *); #define in_function() funcnest extern int funcnest; extern int evalskip; +extern int skipcount; /* reasons for skipping commands (see comment on breakcmd routine) */ #define SKIPBREAK 1 diff --git a/bin/sh/trap.c b/bin/sh/trap.c index a6f929d..834992f 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -412,7 +412,7 @@ void dotrap(void) { int i; - int savestatus; + int savestatus, prev_evalskip, prev_skipcount; in_dotrap++; for (;;) { @@ -427,10 +427,36 @@ dotrap(void) */ if (i == SIGCHLD) ignore_sigchld++; + + /* + * Backup current evalskip + * state and reset it before + * executing a trap, so that the + * trap is not disturbed by an + * ongoing break/continue/return + * statement. + */ + prev_evalskip = evalskip; + prev_skipcount = skipcount; + evalskip = 0; + last_trapsig = i; savestatus = exitstatus; evalstring(trap[i], 0); exitstatus = savestatus; + + /* + * If such a command was not + * already in progress, allow a + * break/continue/return in the + * trap action to have an effect + * outside of it. + */ + if (prev_evalskip != 0) { + evalskip = prev_evalskip; + skipcount = prev_skipcount; + } + if (i == SIGCHLD) ignore_sigchld--; } @@ -501,6 +527,11 @@ exitshell_savedstatus(void) } handler = &loc1; if ((p = trap[0]) != NULL && *p != '\0') { + /* + * Reset evalskip, or the trap on EXIT could be + * interrupted if the last command was a "return". + */ + evalskip = 0; trap[0] = NULL; evalstring(p, 0); } |