diff options
Diffstat (limited to 'Src')
-rw-r--r-- | Src/exec.c | 41 | ||||
-rw-r--r-- | Src/init.c | 4 | ||||
-rw-r--r-- | Src/loop.c | 9 | ||||
-rw-r--r-- | Src/signals.c | 2 | ||||
-rw-r--r-- | Src/zsh.h | 11 |
5 files changed, 48 insertions, 19 deletions
diff --git a/Src/exec.c b/Src/exec.c index 9996dffed..cd99733f1 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -41,12 +41,15 @@ enum { ADDVAR_RESTORE = 1 << 2 }; -/* used to suppress ERREXIT and trapping of SIGZERR, SIGEXIT. */ +/* + * used to suppress ERREXIT and trapping of SIGZERR, SIGEXIT. + * Bits from noerrexit_bits. + */ /**/ int noerrexit; -/* used to suppress ERREXIT for one occurrence */ +/* used to suppress ERREXIT or ERRRETURN for one occurrence: 0 or 1 */ /**/ int this_noerrexit; @@ -1299,7 +1302,7 @@ execlist(Estate state, int dont_change_job, int exiting) int oerrexit_opt = opts[ERREXIT]; Param pm; opts[ERREXIT] = 0; - noerrexit = 1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN; if (ltype & Z_SIMPLE) /* skip the line number */ pc2++; pm = setsparam("ZSH_DEBUG_CMD", getpermtext(state->prog, pc2, 0)); @@ -1351,13 +1354,13 @@ execlist(Estate state, int dont_change_job, int exiting) int isend = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END); next = state->pc + WC_SUBLIST_SKIP(code); if (!oldnoerrexit) - noerrexit = !isend; + noerrexit = isend ? 0 : NOERREXIT_EXIT | NOERREXIT_RETURN; if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT) { /* suppress errexit for "! this_command" */ if (isend) this_noerrexit = 1; /* suppress errexit for ! <list-of-shell-commands> */ - noerrexit = 1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN; } switch (WC_SUBLIST_TYPE(code)) { case WC_SUBLIST_END: @@ -1444,11 +1447,11 @@ sublist_done: /* * See hairy code near the end of execif() for the - * following. "noerrexit == 2" only applies until + * following. "noerrexit " only applies until * we hit execcmd on the way down. We're now * on the way back up, so don't restore it. */ - if (oldnoerrexit != 2) + if (!(oldnoerrexit & NOERREXIT_UNTIL_EXEC)) noerrexit = oldnoerrexit; if (sigtrapped[SIGDEBUG] && !isset(DEBUGBEFORECMD) && !donedebug) { @@ -1458,7 +1461,7 @@ sublist_done: */ int oerrexit_opt = opts[ERREXIT]; opts[ERREXIT] = 0; - noerrexit = 1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN; exiting = donetrap; ret = lastval; dotrap(SIGDEBUG); @@ -1474,16 +1477,19 @@ sublist_done: /* Check whether we are suppressing traps/errexit * * (typically in init scripts) and if we haven't * * already performed them for this sublist. */ - if (!noerrexit && !this_noerrexit && !donetrap && !this_donetrap) { - if (sigtrapped[SIGZERR] && lastval) { + if (!this_noerrexit && !donetrap && !this_donetrap) { + if (sigtrapped[SIGZERR] && lastval && + !(noerrexit & NOERREXIT_EXIT)) { dotrap(SIGZERR); donetrap = 1; } if (lastval) { int errreturn = isset(ERRRETURN) && - (isset(INTERACTIVE) || locallevel || sourcelevel); - int errexit = isset(ERREXIT) || - (isset(ERRRETURN) && !errreturn); + (isset(INTERACTIVE) || locallevel || sourcelevel) && + !(noerrexit & NOERREXIT_RETURN); + int errexit = (isset(ERREXIT) || + (isset(ERRRETURN) && !errreturn)) && + !(noerrexit & NOERREXIT_EXIT); if (errexit) { if (sigtrapped[SIGEXIT]) dotrap(SIGEXIT); @@ -3019,7 +3025,7 @@ execcmd_exec(Estate state, Execcmd_params eparams, preargs = NULL; /* if we get this far, it is OK to pay attention to lastval again */ - if (noerrexit == 2 && !is_shfunc) + if ((noerrexit & NOERREXIT_UNTIL_EXEC) && !is_shfunc) noerrexit = 0; /* Do prefork substitutions. @@ -5462,6 +5468,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) char saveopts[OPT_SIZE], *oldscriptname = scriptname; char *name = shfunc->node.nam; int flags = shfunc->node.flags, ooflags; + int savnoerrexit; char *fname = dupstring(name); int obreaks, ocontflag, oloops, saveemulation, restore_sticky; Eprog prog; @@ -5484,6 +5491,11 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) trap_return--; oldlastval = lastval; oldnumpipestats = numpipestats; + savnoerrexit = noerrexit; + /* + * Suppression of ERR_RETURN is turned off in function scope. + */ + noerrexit &= ~NOERREXIT_RETURN; if (noreturnval) { /* * Easiest to use the heap here since we're bracketed @@ -5702,6 +5714,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) if (trap_state == TRAP_STATE_PRIMED) trap_return++; ret = lastval; + noerrexit = savnoerrexit; if (noreturnval) { lastval = oldlastval; numpipestats = oldnumpipestats; diff --git a/Src/init.c b/Src/init.c index d8c26aca2..87dd2e26d 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1070,7 +1070,7 @@ setupvals(char *cmd, char *runscript, char *zsh_name) sfcontext = SFC_NONE; trap_return = 0; trap_state = TRAP_STATE_INACTIVE; - noerrexit = -1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL; nohistsave = 1; dirstack = znewlinklist(); bufstack = znewlinklist(); @@ -1199,7 +1199,7 @@ init_signals(void) void run_init_scripts(void) { - noerrexit = -1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL; if (EMULATION(EMULATE_KSH|EMULATE_SH)) { if (islogin) diff --git a/Src/loop.c b/Src/loop.c index f7eae307b..4859c976b 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -542,7 +542,7 @@ execif(Estate state, int do_exec) end = state->pc + WC_IF_SKIP(code); if (!noerrexit) - noerrexit = 1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN; while (state->pc < end) { code = *state->pc++; if (wc_code(code) != WC_IF || @@ -567,7 +567,12 @@ execif(Estate state, int do_exec) if (run) { /* we need to ignore lastval until we reach execcmd() */ - noerrexit = olderrexit ? olderrexit : lastval ? 2 : 0; + if (olderrexit) + noerrexit = olderrexit; + else if (lastval) + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_UNTIL_EXEC; + else + noerrexit = 0; cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN)); execlist(state, 1, do_exec); cmdpop(); diff --git a/Src/signals.c b/Src/signals.c index cad40f4eb..94f379e72 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -652,7 +652,7 @@ zhandler(int sig) case SIGINT: if (!handletrap(SIGINT)) { if ((isset(PRIVILEGED) || isset(RESTRICTED)) && - isset(INTERACTIVE) && noerrexit < 0) + isset(INTERACTIVE) && (noerrexit & NOERREXIT_SIGNAL)) zexit(SIGINT, 1); if (list_pipe || chline || simple_pline) { breaks = loops; diff --git a/Src/zsh.h b/Src/zsh.h index 91e8d7f8c..abe9a9c82 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2122,6 +2122,17 @@ enum source_return { SOURCE_ERROR = 2 }; +enum noerrexit_bits { + /* Suppress ERR_EXIT and traps: global */ + NOERREXIT_EXIT = 1, + /* Suppress ERR_RETURN: per function call */ + NOERREXIT_RETURN = 2, + /* NOERREXIT only needed on way down */ + NOERREXIT_UNTIL_EXEC = 4, + /* Force exit on SIGINT */ + NOERREXIT_SIGNAL = 8 +}; + /***********************************/ /* Definitions for history control */ /***********************************/ |