ash: eval: Only restore exit status on exit/return
No binary (build failed)
—
(log yok)
| @@ -404,11 +404,11 @@ struct globals_misc { | |
| volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */ | |
| volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */ | |
| volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */ | |
| - | smallint exception_type; /* kind of exception (0..5) */ |
| - | /* exceptions */ |
| + | smallint exception_type; /* kind of exception: */ |
| #define EXINT 0 /* SIGINT received */ | |
| #define EXERROR 1 /* a generic error */ | |
| - | #define EXEXIT 4 /* exit the shell */ |
| + | #define EXEND 3 /* exit the shell */ |
| + | #define EXEXIT 4 /* exit the shell via exitcmd */ |
| char nullstr[1]; /* zero length string */ | |
| @@ -8237,7 +8237,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) | |
| exitstatus = exerrno; | |
| TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n", | |
| prog, e, suppress_int)); | |
| - | ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found")); |
| + | ash_msg_and_raise(EXEND, "%s: %s", prog, errmsg(e, "not found")); |
| /* NOTREACHED */ | |
| } | |
| @@ -9291,9 +9291,9 @@ evaltree(union node *n, int flags) | |
| dotrap(); | |
| if (checkexit & status) | |
| - | raise_exception(EXEXIT); |
| + | raise_exception(EXEND); |
| if (flags & EV_EXIT) | |
| - | raise_exception(EXEXIT); |
| + | raise_exception(EXEND); |
| popstackmark(&smark); | |
| TRACE(("leaving evaltree (no interrupts)\n")); | |
| @@ -14146,6 +14146,47 @@ ulimitcmd(int argc UNUSED_PARAM, char **argv) | |
| /* ============ main() and helpers */ | |
| + | /* |
| + | * This routine is called when an error or an interrupt occurs in an |
| + | * interactive shell and control is returned to the main command loop |
| + | * but prior to exitshell. |
| + | */ |
| + | static void |
| + | exitreset(void) |
| + | { |
| + | /* from eval.c: */ |
| + | if (savestatus >= 0) { |
| + | if (exception_type == EXEXIT || evalskip == SKIPFUNCDEF) |
| + | exitstatus = savestatus; |
| + | savestatus = -1; |
| + | } |
| + | evalskip = 0; |
| + | loopnest = 0; |
| + | |
| + | /* from expand.c: */ |
| + | ifsfree(); |
| + | |
| + | /* from redir.c: */ |
| + | unwindredir(NULL); |
| + | } |
| + | |
| + | /* |
| + | * This routine is called when an error or an interrupt occurs in an |
| + | * interactive shell and control is returned to the main command loop. |
| + | * (In dash, this function is auto-generated by build machinery). |
| + | */ |
| + | static void |
| + | reset(void) |
| + | { |
| + | /* from input.c: */ |
| + | g_parsefile->left_in_buffer = 0; |
| + | g_parsefile->left_in_line = 0; /* clear input buffer */ |
| + | popallfiles(); |
| + | |
| + | /* from var.c: */ |
| + | unwindlocalvars(NULL); |
| + | } |
| + | |
| /* | |
| * Called to exit the shell. | |
| */ | |
| @@ -14169,15 +14210,17 @@ exitshell(void) | |
| trap[0] = NULL; | |
| evalskip = 0; | |
| evalstring(p, 0); | |
| + | evalskip = SKIPFUNCDEF; |
| /*free(p); - we'll exit soon */ | |
| } | |
| out: | |
| + | exitreset(); |
| /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}". | |
| * our setjobctl(0) does not panic if tcsetpgrp fails inside it. | |
| */ | |
| setjobctl(0); | |
| flush_stdout_stderr(); | |
| - | _exit(savestatus); |
| + | _exit(exitstatus); |
| /* NOTREACHED */ | |
| } | |
| @@ -14337,46 +14380,6 @@ read_profile(const char *name) | |
| popfile(); | |
| } | |
| - | /* |
| - | * This routine is called when an error or an interrupt occurs in an |
| - | * interactive shell and control is returned to the main command loop |
| - | * but prior to exitshell. |
| - | */ |
| - | static void |
| - | exitreset(void) |
| - | { |
| - | /* from eval.c: */ |
| - | evalskip = 0; |
| - | loopnest = 0; |
| - | if (savestatus >= 0) { |
| - | exitstatus = savestatus; |
| - | savestatus = -1; |
| - | } |
| - | |
| - | /* from expand.c: */ |
| - | ifsfree(); |
| - | |
| - | /* from redir.c: */ |
| - | unwindredir(NULL); |
| - | } |
| - | |
| - | /* |
| - | * This routine is called when an error or an interrupt occurs in an |
| - | * interactive shell and control is returned to the main command loop. |
| - | * (In dash, this function is auto-generated by build machinery). |
| - | */ |
| - | static void |
| - | reset(void) |
| - | { |
| - | /* from input.c: */ |
| - | g_parsefile->left_in_buffer = 0; |
| - | g_parsefile->left_in_line = 0; /* clear input buffer */ |
| - | popallfiles(); |
| - | |
| - | /* from var.c: */ |
| - | unwindlocalvars(NULL); |
| - | } |
| - | |
| #if PROFILE | |
| static short profile_buf[16384]; | |
| extern int etext(); | |
| @@ -14424,7 +14427,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |
| e = exception_type; | |
| s = state; | |
| - | if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) { |
| + | if (e == EXEND || e == EXEXIT || s == 0 || iflag == 0 || shlvl) { |
| exitshell(); | |
| } | |