aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-10-01 19:56:52 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-10-01 19:56:52 +0200
commit35ec818fa23b9c68572f871da5c325101009939a (patch)
tree9ca295a470f2faa930771242aee09718abf3b925 /shell/ash.c
parent1b8e0e8adfc28c0b2472121c22f61e1d032805c8 (diff)
downloadbusybox-w32-35ec818fa23b9c68572f871da5c325101009939a.tar.gz
busybox-w32-35ec818fa23b9c68572f871da5c325101009939a.tar.bz2
busybox-w32-35ec818fa23b9c68572f871da5c325101009939a.zip
ash: fix "return N" not setting $? in loop conditionals
Upstream commit 1: Date: Mon, 6 Oct 2014 20:45:04 +0800 [EVAL] Move common skipcount logic into skiploop The functions evalloop and evalfor share the logic on checking and updating skipcount. This patch moves that into the helper function skiploop. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Upstream commit 2: Date: Mon, 6 Oct 2014 21:22:43 +0800 [BUILTIN] Allow return in loop conditional to set exit status https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=332954 When return is used in a loop conditional the exit status will be lost because we always set the exit status at the end of the loop to that of the last command executed in the body. This is counterintuitive and contrary to what most other shells do. This patch fixes this by always preserving the exit status of return when it is used in a loop conditional. The patch was originally written by Gerrit Pape <pape@smarden.org>. Reported-by: Stephane Chazelas <stephane_chazelas@yahoo.fr> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 06df07d06..e4349ccad 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8632,37 +8632,50 @@ static
8632#endif 8632#endif
8633int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__)); 8633int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8634 8634
8635static int skiploop(void)
8636{
8637 int skip = evalskip;
8638
8639 switch (skip) {
8640 case 0:
8641 break;
8642 case SKIPBREAK:
8643 case SKIPCONT:
8644 if (--skipcount <= 0) {
8645 evalskip = 0;
8646 break;
8647 }
8648 skip = SKIPBREAK;
8649 break;
8650 }
8651 return skip;
8652}
8653
8635static int 8654static int
8636evalloop(union node *n, int flags) 8655evalloop(union node *n, int flags)
8637{ 8656{
8657 int skip;
8638 int status; 8658 int status;
8639 8659
8640 loopnest++; 8660 loopnest++;
8641 status = 0; 8661 status = 0;
8642 flags &= EV_TESTED; 8662 flags &= EV_TESTED;
8643 for (;;) { 8663 do {
8644 int i; 8664 int i;
8645 8665
8646 i = evaltree(n->nbinary.ch1, EV_TESTED); 8666 i = evaltree(n->nbinary.ch1, EV_TESTED);
8647 if (evalskip) { 8667 skip = skiploop();
8648 skipping: 8668 if (skip == SKIPFUNC)
8649 if (evalskip == SKIPCONT && --skipcount <= 0) { 8669 status = i;
8650 evalskip = 0; 8670 if (skip)
8651 continue; 8671 continue;
8652 }
8653 if (evalskip == SKIPBREAK && --skipcount <= 0)
8654 evalskip = 0;
8655 break;
8656 }
8657 if (n->type != NWHILE) 8672 if (n->type != NWHILE)
8658 i = !i; 8673 i = !i;
8659 if (i != 0) 8674 if (i != 0)
8660 break; 8675 break;
8661 status = evaltree(n->nbinary.ch2, flags); 8676 status = evaltree(n->nbinary.ch2, flags);
8662 if (evalskip) 8677 skip = skiploop();
8663 goto skipping; 8678 } while (!(skip & ~SKIPCONT));
8664 }
8665 exitstatus = status;
8666 loopnest--; 8679 loopnest--;
8667 8680
8668 return status; 8681 return status;
@@ -8682,9 +8695,6 @@ evalfor(union node *n, int flags)
8682 arglist.lastp = &arglist.list; 8695 arglist.lastp = &arglist.list;
8683 for (argp = n->nfor.args; argp; argp = argp->narg.next) { 8696 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8684 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 8697 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8685 /* XXX */
8686 if (evalskip)
8687 goto out;
8688 } 8698 }
8689 *arglist.lastp = NULL; 8699 *arglist.lastp = NULL;
8690 8700
@@ -8693,18 +8703,10 @@ evalfor(union node *n, int flags)
8693 for (sp = arglist.list; sp; sp = sp->next) { 8703 for (sp = arglist.list; sp; sp = sp->next) {
8694 setvar0(n->nfor.var, sp->text); 8704 setvar0(n->nfor.var, sp->text);
8695 status = evaltree(n->nfor.body, flags); 8705 status = evaltree(n->nfor.body, flags);
8696 if (evalskip) { 8706 if (skiploop() & ~SKIPCONT)
8697 if (evalskip == SKIPCONT && --skipcount <= 0) {
8698 evalskip = 0;
8699 continue;
8700 }
8701 if (evalskip == SKIPBREAK && --skipcount <= 0)
8702 evalskip = 0;
8703 break; 8707 break;
8704 }
8705 } 8708 }
8706 loopnest--; 8709 loopnest--;
8707 out:
8708 popstackmark(&smark); 8710 popstackmark(&smark);
8709 8711
8710 return status; 8712 return status;