aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c136
-rw-r--r--shell/ash_test/ash-misc/exitcode1.right2
-rwxr-xr-xshell/ash_test/ash-misc/exitcode1.tests2
-rw-r--r--shell/hush_test/hush-misc/exitcode1.right2
-rwxr-xr-xshell/hush_test/hush-misc/exitcode1.tests2
5 files changed, 89 insertions, 55 deletions
diff --git a/shell/ash.c b/shell/ash.c
index a113ff155..ec006af7d 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -5864,7 +5864,7 @@ struct backcmd { /* result of evalbackcmd */
5864/* These forward decls are needed to use "eval" code for backticks handling: */ 5864/* These forward decls are needed to use "eval" code for backticks handling: */
5865static uint8_t back_exitstatus; /* exit status of backquoted command */ 5865static uint8_t back_exitstatus; /* exit status of backquoted command */
5866#define EV_EXIT 01 /* exit after evaluating tree */ 5866#define EV_EXIT 01 /* exit after evaluating tree */
5867static void evaltree(union node *, int); 5867static int evaltree(union node *, int);
5868 5868
5869static void FAST_FUNC 5869static void FAST_FUNC
5870evalbackcmd(union node *n, struct backcmd *result) 5870evalbackcmd(union node *n, struct backcmd *result)
@@ -8412,13 +8412,13 @@ dotrap(void)
8412} 8412}
8413 8413
8414/* forward declarations - evaluation is fairly recursive business... */ 8414/* forward declarations - evaluation is fairly recursive business... */
8415static void evalloop(union node *, int); 8415static int evalloop(union node *, int);
8416static void evalfor(union node *, int); 8416static int evalfor(union node *, int);
8417static void evalcase(union node *, int); 8417static int evalcase(union node *, int);
8418static void evalsubshell(union node *, int); 8418static int evalsubshell(union node *, int);
8419static void expredir(union node *); 8419static void expredir(union node *);
8420static void evalpipe(union node *, int); 8420static int evalpipe(union node *, int);
8421static void evalcommand(union node *, int); 8421static int evalcommand(union node *, int);
8422static int evalbltin(const struct builtincmd *, int, char **); 8422static int evalbltin(const struct builtincmd *, int, char **);
8423static void prehash(union node *); 8423static void prehash(union node *);
8424 8424
@@ -8426,14 +8426,14 @@ static void prehash(union node *);
8426 * Evaluate a parse tree. The value is left in the global variable 8426 * Evaluate a parse tree. The value is left in the global variable
8427 * exitstatus. 8427 * exitstatus.
8428 */ 8428 */
8429static void 8429static int
8430evaltree(union node *n, int flags) 8430evaltree(union node *n, int flags)
8431{ 8431{
8432 struct jmploc *volatile savehandler = exception_handler; 8432 struct jmploc *volatile savehandler = exception_handler;
8433 struct jmploc jmploc; 8433 struct jmploc jmploc;
8434 int checkexit = 0; 8434 int checkexit = 0;
8435 void (*evalfn)(union node *, int); 8435 int (*evalfn)(union node *, int);
8436 int status; 8436 int status = 0;
8437 int int_level; 8437 int int_level;
8438 8438
8439 SAVE_INT(int_level); 8439 SAVE_INT(int_level);
@@ -8470,15 +8470,13 @@ evaltree(union node *n, int flags)
8470 break; 8470 break;
8471#endif 8471#endif
8472 case NNOT: 8472 case NNOT:
8473 evaltree(n->nnot.com, EV_TESTED); 8473 status = !evaltree(n->nnot.com, EV_TESTED);
8474 status = !exitstatus;
8475 goto setstatus; 8474 goto setstatus;
8476 case NREDIR: 8475 case NREDIR:
8477 expredir(n->nredir.redirect); 8476 expredir(n->nredir.redirect);
8478 status = redirectsafe(n->nredir.redirect, REDIR_PUSH); 8477 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8479 if (!status) { 8478 if (!status) {
8480 evaltree(n->nredir.n, flags & EV_TESTED); 8479 status = evaltree(n->nredir.n, flags & EV_TESTED);
8481 status = exitstatus;
8482 } 8480 }
8483 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */); 8481 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8484 goto setstatus; 8482 goto setstatus;
@@ -8518,27 +8516,24 @@ evaltree(union node *n, int flags)
8518#error NOR + 1 != NSEMI 8516#error NOR + 1 != NSEMI
8519#endif 8517#endif
8520 unsigned is_or = n->type - NAND; 8518 unsigned is_or = n->type - NAND;
8521 evaltree( 8519 status = evaltree(
8522 n->nbinary.ch1, 8520 n->nbinary.ch1,
8523 (flags | ((is_or >> 1) - 1)) & EV_TESTED 8521 (flags | ((is_or >> 1) - 1)) & EV_TESTED
8524 ); 8522 );
8525 if ((!exitstatus) == is_or) 8523 if (!status == is_or || evalskip)
8526 break; 8524 break;
8527 if (!evalskip) { 8525 n = n->nbinary.ch2;
8528 n = n->nbinary.ch2;
8529 evaln: 8526 evaln:
8530 evalfn = evaltree; 8527 evalfn = evaltree;
8531 calleval: 8528 calleval:
8532 evalfn(n, flags); 8529 status = evalfn(n, flags);
8533 break; 8530 goto setstatus;
8534 }
8535 break;
8536 } 8531 }
8537 case NIF: 8532 case NIF:
8538 evaltree(n->nif.test, EV_TESTED); 8533 status = evaltree(n->nif.test, EV_TESTED);
8539 if (evalskip) 8534 if (evalskip)
8540 break; 8535 break;
8541 if (exitstatus == 0) { 8536 if (!status) {
8542 n = n->nif.ifpart; 8537 n = n->nif.ifpart;
8543 goto evaln; 8538 goto evaln;
8544 } 8539 }
@@ -8546,11 +8541,14 @@ evaltree(union node *n, int flags)
8546 n = n->nif.elsepart; 8541 n = n->nif.elsepart;
8547 goto evaln; 8542 goto evaln;
8548 } 8543 }
8549 goto success; 8544 status = 0;
8545 goto setstatus;
8550 case NDEFUN: 8546 case NDEFUN:
8551 defun(n->narg.text, n->narg.next); 8547 defun(n->narg.text, n->narg.next);
8552 success: 8548 /* Not necessary. To test it:
8553 status = 0; 8549 * "false; f() { qwerty; }; echo $?" should print 0.
8550 */
8551 /* status = 0; */
8554 setstatus: 8552 setstatus:
8555 exitstatus = status; 8553 exitstatus = status;
8556 break; 8554 break;
@@ -8565,7 +8563,7 @@ evaltree(union node *n, int flags)
8565 */ 8563 */
8566 if (pending_sig && dotrap()) 8564 if (pending_sig && dotrap())
8567 goto exexit; 8565 goto exexit;
8568 if (checkexit & exitstatus) 8566 if (checkexit & status)
8569 evalskip |= SKIPEVAL; 8567 evalskip |= SKIPEVAL;
8570 8568
8571 if (flags & EV_EXIT) { 8569 if (flags & EV_EXIT) {
@@ -8575,14 +8573,16 @@ evaltree(union node *n, int flags)
8575 8573
8576 RESTORE_INT(int_level); 8574 RESTORE_INT(int_level);
8577 TRACE(("leaving evaltree (no interrupts)\n")); 8575 TRACE(("leaving evaltree (no interrupts)\n"));
8576
8577 return exitstatus;
8578} 8578}
8579 8579
8580#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) 8580#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8581static 8581static
8582#endif 8582#endif
8583void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__)); 8583int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8584 8584
8585static void 8585static int
8586evalloop(union node *n, int flags) 8586evalloop(union node *n, int flags)
8587{ 8587{
8588 int status; 8588 int status;
@@ -8593,7 +8593,7 @@ evalloop(union node *n, int flags)
8593 for (;;) { 8593 for (;;) {
8594 int i; 8594 int i;
8595 8595
8596 evaltree(n->nbinary.ch1, EV_TESTED); 8596 i = evaltree(n->nbinary.ch1, EV_TESTED);
8597 if (evalskip) { 8597 if (evalskip) {
8598 skipping: 8598 skipping:
8599 if (evalskip == SKIPCONT && --skipcount <= 0) { 8599 if (evalskip == SKIPCONT && --skipcount <= 0) {
@@ -8604,27 +8604,28 @@ evalloop(union node *n, int flags)
8604 evalskip = 0; 8604 evalskip = 0;
8605 break; 8605 break;
8606 } 8606 }
8607 i = exitstatus;
8608 if (n->type != NWHILE) 8607 if (n->type != NWHILE)
8609 i = !i; 8608 i = !i;
8610 if (i != 0) 8609 if (i != 0)
8611 break; 8610 break;
8612 evaltree(n->nbinary.ch2, flags); 8611 status = evaltree(n->nbinary.ch2, flags);
8613 status = exitstatus;
8614 if (evalskip) 8612 if (evalskip)
8615 goto skipping; 8613 goto skipping;
8616 } 8614 }
8617 loopnest--;
8618 exitstatus = status; 8615 exitstatus = status;
8616 loopnest--;
8617
8618 return status;
8619} 8619}
8620 8620
8621static void 8621static int
8622evalfor(union node *n, int flags) 8622evalfor(union node *n, int flags)
8623{ 8623{
8624 struct arglist arglist; 8624 struct arglist arglist;
8625 union node *argp; 8625 union node *argp;
8626 struct strlist *sp; 8626 struct strlist *sp;
8627 struct stackmark smark; 8627 struct stackmark smark;
8628 int status = 0;
8628 8629
8629 setstackmark(&smark); 8630 setstackmark(&smark);
8630 arglist.list = NULL; 8631 arglist.list = NULL;
@@ -8637,12 +8638,11 @@ evalfor(union node *n, int flags)
8637 } 8638 }
8638 *arglist.lastp = NULL; 8639 *arglist.lastp = NULL;
8639 8640
8640 exitstatus = 0;
8641 loopnest++; 8641 loopnest++;
8642 flags &= EV_TESTED; 8642 flags &= EV_TESTED;
8643 for (sp = arglist.list; sp; sp = sp->next) { 8643 for (sp = arglist.list; sp; sp = sp->next) {
8644 setvar0(n->nfor.var, sp->text); 8644 setvar0(n->nfor.var, sp->text);
8645 evaltree(n->nfor.body, flags); 8645 status = evaltree(n->nfor.body, flags);
8646 if (evalskip) { 8646 if (evalskip) {
8647 if (evalskip == SKIPCONT && --skipcount <= 0) { 8647 if (evalskip == SKIPCONT && --skipcount <= 0) {
8648 evalskip = 0; 8648 evalskip = 0;
@@ -8656,26 +8656,32 @@ evalfor(union node *n, int flags)
8656 loopnest--; 8656 loopnest--;
8657 out: 8657 out:
8658 popstackmark(&smark); 8658 popstackmark(&smark);
8659
8660 return status;
8659} 8661}
8660 8662
8661static void 8663static int
8662evalcase(union node *n, int flags) 8664evalcase(union node *n, int flags)
8663{ 8665{
8664 union node *cp; 8666 union node *cp;
8665 union node *patp; 8667 union node *patp;
8666 struct arglist arglist; 8668 struct arglist arglist;
8667 struct stackmark smark; 8669 struct stackmark smark;
8670 int status = 0;
8668 8671
8669 setstackmark(&smark); 8672 setstackmark(&smark);
8670 arglist.list = NULL; 8673 arglist.list = NULL;
8671 arglist.lastp = &arglist.list; 8674 arglist.lastp = &arglist.list;
8672 expandarg(n->ncase.expr, &arglist, EXP_TILDE); 8675 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8673 exitstatus = 0;
8674 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) { 8676 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8675 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) { 8677 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8676 if (casematch(patp, arglist.list->text)) { 8678 if (casematch(patp, arglist.list->text)) {
8677 if (evalskip == 0) { 8679 /* Ensure body is non-empty as otherwise
8678 evaltree(cp->nclist.body, flags); 8680 * EV_EXIT may prevent us from setting the
8681 * exit status.
8682 */
8683 if (evalskip == 0 && cp->nclist.body) {
8684 status = evaltree(cp->nclist.body, flags);
8679 } 8685 }
8680 goto out; 8686 goto out;
8681 } 8687 }
@@ -8683,12 +8689,14 @@ evalcase(union node *n, int flags)
8683 } 8689 }
8684 out: 8690 out:
8685 popstackmark(&smark); 8691 popstackmark(&smark);
8692
8693 return status;
8686} 8694}
8687 8695
8688/* 8696/*
8689 * Kick off a subshell to evaluate a tree. 8697 * Kick off a subshell to evaluate a tree.
8690 */ 8698 */
8691static void 8699static int
8692evalsubshell(union node *n, int flags) 8700evalsubshell(union node *n, int flags)
8693{ 8701{
8694 struct job *jp; 8702 struct job *jp;
@@ -8714,8 +8722,8 @@ evalsubshell(union node *n, int flags)
8714 status = 0; 8722 status = 0;
8715 if (!backgnd) 8723 if (!backgnd)
8716 status = waitforjob(jp); 8724 status = waitforjob(jp);
8717 exitstatus = status;
8718 INT_ON; 8725 INT_ON;
8726 return status;
8719} 8727}
8720 8728
8721/* 8729/*
@@ -8788,7 +8796,7 @@ expredir(union node *n)
8788 * of the shell, which make the last process in a pipeline the parent 8796 * of the shell, which make the last process in a pipeline the parent
8789 * of all the rest.) 8797 * of all the rest.)
8790 */ 8798 */
8791static void 8799static int
8792evalpipe(union node *n, int flags) 8800evalpipe(union node *n, int flags)
8793{ 8801{
8794 struct job *jp; 8802 struct job *jp;
@@ -8796,6 +8804,7 @@ evalpipe(union node *n, int flags)
8796 int pipelen; 8804 int pipelen;
8797 int prevfd; 8805 int prevfd;
8798 int pip[2]; 8806 int pip[2];
8807 int status = 0;
8799 8808
8800 TRACE(("evalpipe(0x%lx) called\n", (long)n)); 8809 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8801 pipelen = 0; 8810 pipelen = 0;
@@ -8838,10 +8847,12 @@ evalpipe(union node *n, int flags)
8838 close(pip[1]); 8847 close(pip[1]);
8839 } 8848 }
8840 if (n->npipe.pipe_backgnd == 0) { 8849 if (n->npipe.pipe_backgnd == 0) {
8841 exitstatus = waitforjob(jp); 8850 status = waitforjob(jp);
8842 TRACE(("evalpipe: job done exit status %d\n", exitstatus)); 8851 TRACE(("evalpipe: job done exit status %d\n", status));
8843 } 8852 }
8844 INT_ON; 8853 INT_ON;
8854
8855 return status;
8845} 8856}
8846 8857
8847/* 8858/*
@@ -9328,7 +9339,7 @@ bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9328 * as POSIX mandates */ 9339 * as POSIX mandates */
9329 return back_exitstatus; 9340 return back_exitstatus;
9330} 9341}
9331static void 9342static int
9332evalcommand(union node *cmd, int flags) 9343evalcommand(union node *cmd, int flags)
9333{ 9344{
9334 static const struct builtincmd null_bltin = { 9345 static const struct builtincmd null_bltin = {
@@ -9511,9 +9522,9 @@ evalcommand(union node *cmd, int flags)
9511 jp = makejob(/*cmd,*/ 1); 9522 jp = makejob(/*cmd,*/ 1);
9512 if (forkshell(jp, cmd, FORK_FG) != 0) { 9523 if (forkshell(jp, cmd, FORK_FG) != 0) {
9513 /* parent */ 9524 /* parent */
9514 exitstatus = waitforjob(jp); 9525 status = waitforjob(jp);
9515 INT_ON; 9526 INT_ON;
9516 TRACE(("forked child exited with %d\n", exitstatus)); 9527 TRACE(("forked child exited with %d\n", status));
9517 break; 9528 break;
9518 } 9529 }
9519 /* child */ 9530 /* child */
@@ -9559,7 +9570,7 @@ evalcommand(union node *cmd, int flags)
9559 } 9570 }
9560 FORCE_INT_ON; 9571 FORCE_INT_ON;
9561 } 9572 }
9562 break; 9573 goto readstatus;
9563 9574
9564 case CMDFUNCTION: 9575 case CMDFUNCTION:
9565 listsetvar(varlist.list, 0); 9576 listsetvar(varlist.list, 0);
@@ -9567,6 +9578,8 @@ evalcommand(union node *cmd, int flags)
9567 dowait(DOWAIT_NONBLOCK, NULL); 9578 dowait(DOWAIT_NONBLOCK, NULL);
9568 if (evalfun(cmdentry.u.func, argc, argv, flags)) 9579 if (evalfun(cmdentry.u.func, argc, argv, flags))
9569 goto raise; 9580 goto raise;
9581 readstatus:
9582 status = exitstatus;
9570 break; 9583 break;
9571 } /* switch */ 9584 } /* switch */
9572 9585
@@ -9580,6 +9593,8 @@ evalcommand(union node *cmd, int flags)
9580 setvar0("_", lastarg); 9593 setvar0("_", lastarg);
9581 } 9594 }
9582 popstackmark(&smark); 9595 popstackmark(&smark);
9596
9597 return status;
9583} 9598}
9584 9599
9585static int 9600static int
@@ -12205,13 +12220,18 @@ evalstring(char *s, int mask)
12205 union node *n; 12220 union node *n;
12206 struct stackmark smark; 12221 struct stackmark smark;
12207 int skip; 12222 int skip;
12223// int status;
12208 12224
12209 setinputstring(s); 12225 setinputstring(s);
12210 setstackmark(&smark); 12226 setstackmark(&smark);
12211 12227
12212 skip = 0; 12228 skip = 0;
12213 while ((n = parsecmd(0)) != NODE_EOF) { 12229 while ((n = parsecmd(0)) != NODE_EOF) {
12214 evaltree(n, 0); 12230 int i;
12231
12232 i = evaltree(n, 0);
12233// if (n)
12234// status = i;
12215 popstackmark(&smark); 12235 popstackmark(&smark);
12216 skip = evalskip; 12236 skip = evalskip;
12217 if (skip) 12237 if (skip)
@@ -12222,6 +12242,7 @@ evalstring(char *s, int mask)
12222 skip &= mask; 12242 skip &= mask;
12223 evalskip = skip; 12243 evalskip = skip;
12224 return skip; 12244 return skip;
12245// return status;
12225} 12246}
12226 12247
12227/* 12248/*
@@ -12264,6 +12285,7 @@ cmdloop(int top)
12264 union node *n; 12285 union node *n;
12265 struct stackmark smark; 12286 struct stackmark smark;
12266 int inter; 12287 int inter;
12288 int status = 0;
12267 int numeof = 0; 12289 int numeof = 0;
12268 12290
12269 TRACE(("cmdloop(%d) called\n", top)); 12291 TRACE(("cmdloop(%d) called\n", top));
@@ -12295,10 +12317,14 @@ cmdloop(int top)
12295 } 12317 }
12296 numeof++; 12318 numeof++;
12297 } else if (nflag == 0) { 12319 } else if (nflag == 0) {
12320 int i;
12321
12298 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */ 12322 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12299 job_warning >>= 1; 12323 job_warning >>= 1;
12300 numeof = 0; 12324 numeof = 0;
12301 evaltree(n, 0); 12325 i = evaltree(n, 0);
12326 if (n)
12327 status = i;
12302 } 12328 }
12303 popstackmark(&smark); 12329 popstackmark(&smark);
12304 skip = evalskip; 12330 skip = evalskip;
@@ -12308,7 +12334,7 @@ cmdloop(int top)
12308 return skip & SKIPEVAL; 12334 return skip & SKIPEVAL;
12309 } 12335 }
12310 } 12336 }
12311 return 0; 12337 return status;
12312} 12338}
12313 12339
12314/* 12340/*
diff --git a/shell/ash_test/ash-misc/exitcode1.right b/shell/ash_test/ash-misc/exitcode1.right
new file mode 100644
index 000000000..e5fefefda
--- /dev/null
+++ b/shell/ash_test/ash-misc/exitcode1.right
@@ -0,0 +1,2 @@
1One:1
2Zero:0
diff --git a/shell/ash_test/ash-misc/exitcode1.tests b/shell/ash_test/ash-misc/exitcode1.tests
new file mode 100755
index 000000000..dc8619d8b
--- /dev/null
+++ b/shell/ash_test/ash-misc/exitcode1.tests
@@ -0,0 +1,2 @@
1false || case a in a) echo One:$?;; esac
2echo Zero:$?
diff --git a/shell/hush_test/hush-misc/exitcode1.right b/shell/hush_test/hush-misc/exitcode1.right
new file mode 100644
index 000000000..e5fefefda
--- /dev/null
+++ b/shell/hush_test/hush-misc/exitcode1.right
@@ -0,0 +1,2 @@
1One:1
2Zero:0
diff --git a/shell/hush_test/hush-misc/exitcode1.tests b/shell/hush_test/hush-misc/exitcode1.tests
new file mode 100755
index 000000000..dc8619d8b
--- /dev/null
+++ b/shell/hush_test/hush-misc/exitcode1.tests
@@ -0,0 +1,2 @@
1false || case a in a) echo One:$?;; esac
2echo Zero:$?