aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2014-10-06 10:39:47 +0800
committerBen Hutchings <ben@decadent.org.uk>2020-03-28 21:42:54 +0000
commit85a5a4a9d96c0c680597432f1e4454718e7ad101 (patch)
tree1c19f13b2348c0503cab4dd9f502e7e71b7872cb
parente49a1160b58933c257c27603aa3d020daf8e0943 (diff)
downloadklibc-85a5a4a9d96c0c680597432f1e4454718e7ad101.tar.gz
[klibc] dash: [BUILTIN] Exit without arguments in a trap should use status outside traps
[ dash commit da30b4b787695fbf77e5d941ff350a66ca572bcb ] POSIX now requires that exit without arguments in a trap should return the last command status prior to executing traps. This patch implements this behaviour. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--usr/dash/eval.c5
-rw-r--r--usr/dash/eval.h1
-rw-r--r--usr/dash/main.c11
-rw-r--r--usr/dash/trap.c25
4 files changed, 29 insertions, 13 deletions
diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index 3e08e8252ef9b..1c76d4c519956 100644
--- a/usr/dash/eval.c
+++ b/usr/dash/eval.c
@@ -74,6 +74,7 @@ static int funcline; /* starting line number of current function, or 0 if not i
char *commandname;
int exitstatus; /* exit status of last command */
int back_exitstatus; /* exit status of backquoted command */
+int savestatus = -1; /* exit status of last command outside traps */
#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
@@ -114,6 +115,10 @@ INCLUDE "eval.h"
RESET {
evalskip = 0;
loopnest = 0;
+ if (savestatus >= 0) {
+ exitstatus = savestatus;
+ savestatus = -1;
+ }
}
#endif
diff --git a/usr/dash/eval.h b/usr/dash/eval.h
index dc8acd2a5c4a7..6e62137a5a26d 100644
--- a/usr/dash/eval.h
+++ b/usr/dash/eval.h
@@ -37,6 +37,7 @@
extern char *commandname; /* currently executing command */
extern int exitstatus; /* exit status of last command */
extern int back_exitstatus; /* exit status of backquoted command */
+extern int savestatus; /* exit status of last command outside traps */
struct backcmd { /* result of evalbackcmd */
diff --git a/usr/dash/main.c b/usr/dash/main.c
index f79ad7ddac111..29a258d3c89ec 100644
--- a/usr/dash/main.c
+++ b/usr/dash/main.c
@@ -339,8 +339,15 @@ exitcmd(int argc, char **argv)
{
if (stoppedjobs())
return 0;
- if (argc > 1)
- exitstatus = number(argv[1]);
+
+ if (argc > 1) {
+ int status = number(argv[1]);
+
+ exitstatus = status;
+ if (savestatus >= 0)
+ savestatus = status;
+ }
+
exraise(EXEXIT);
/* NOTREACHED */
}
diff --git a/usr/dash/trap.c b/usr/dash/trap.c
index 3ff45318eef32..7dd8342fb0da5 100644
--- a/usr/dash/trap.c
+++ b/usr/dash/trap.c
@@ -313,12 +313,17 @@ void dotrap(void)
char *p;
char *q;
int i;
- int savestatus;
+ int status, last_status;
if (!pendingsigs)
return;
- savestatus = exitstatus;
+ status = savestatus;
+ last_status = status;
+ if (likely(status < 0)) {
+ status = exitstatus;
+ savestatus = status;
+ }
pendingsigs = 0;
barrier();
@@ -337,8 +342,10 @@ void dotrap(void)
if (!p)
continue;
evalstring(p, 0);
- exitstatus = savestatus;
+ exitstatus = status;
}
+
+ savestatus = last_status;
}
@@ -372,18 +379,14 @@ exitshell(void)
{
struct jmploc loc;
char *p;
- volatile int status;
#ifdef HETIO
hetio_reset_term();
#endif
- status = exitstatus;
- TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
- if (setjmp(loc.loc)) {
- if (exception == EXEXIT)
- status = exitstatus;
+ savestatus = exitstatus;
+ TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
+ if (setjmp(loc.loc))
goto out;
- }
handler = &loc;
if ((p = trap[0])) {
trap[0] = NULL;
@@ -398,7 +401,7 @@ out:
if (likely(!setjmp(loc.loc)))
setjobctl(0);
flushall();
- _exit(status);
+ _exit(savestatus);
/* NOTREACHED */
}