aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-10-01 15:10:16 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-10-01 15:10:16 +0200
commit7b3fa1e441bbb34a9edccf17b71efc34499bde9f (patch)
tree55251915b1a6c268872ca69ae6cb0160a7ebe71c
parent08089c7c85a72d5eaf2bed22033098b263f58a3e (diff)
downloadbusybox-w32-7b3fa1e441bbb34a9edccf17b71efc34499bde9f.tar.gz
busybox-w32-7b3fa1e441bbb34a9edccf17b71efc34499bde9f.tar.bz2
busybox-w32-7b3fa1e441bbb34a9edccf17b71efc34499bde9f.zip
ash: [EVAL] Pass EV_TESTED into evalcmd
Upstream commit: Date: Tue Aug 11 20:48:15 2009 +1000 [EVAL] Pass EV_TESTED into evalcmd This patch fixes the case where the eval command is used with set -e and as part of a construct that should not cause the shell to abort, e.g., as part of the condition of an if statement. This is achieved by propagating the EV_TESTED flag into the evalstring function through evalcmd. As this alters the prototype of evalcmd it is now invoked explicitly by evalbltin. The built-in infrastructure has been changed to accomodate this special case. In order to ensure that the EXIT trap is properly executed this patch clears evalskip in exitshell. This wasn't needed before because of the broken way evalstring worked where it always clears evalskip when called by minusc. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Although, I failed to create a reproducer for this. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/shell/ash.c b/shell/ash.c
index c8dd9a5fe..d107fa1fd 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8414,7 +8414,7 @@ static int funcnest; /* depth of function calls */
8414static int loopnest; /* current loop nesting level */ 8414static int loopnest; /* current loop nesting level */
8415 8415
8416/* Forward decl way out to parsing code - dotrap needs it */ 8416/* Forward decl way out to parsing code - dotrap needs it */
8417static int evalstring(char *s, int mask); 8417static int evalstring(char *s, int flags);
8418 8418
8419/* Called to execute a trap. 8419/* Called to execute a trap.
8420 * Single callsite - at the end of evaltree(). 8420 * Single callsite - at the end of evaltree().
@@ -8450,7 +8450,7 @@ dotrap(void)
8450 *g = 0; 8450 *g = 0;
8451 if (!t) 8451 if (!t)
8452 continue; 8452 continue;
8453 evalstring(t, SKIPEVAL); 8453 evalstring(t, 0);
8454 exitstatus = savestatus; 8454 exitstatus = savestatus;
8455 if (evalskip) { 8455 if (evalskip) {
8456 TRACE(("dotrap returns %d\n", evalskip)); 8456 TRACE(("dotrap returns %d\n", evalskip));
@@ -8470,7 +8470,7 @@ static int evalsubshell(union node *, int);
8470static void expredir(union node *); 8470static void expredir(union node *);
8471static int evalpipe(union node *, int); 8471static int evalpipe(union node *, int);
8472static int evalcommand(union node *, int); 8472static int evalcommand(union node *, int);
8473static int evalbltin(const struct builtincmd *, int, char **); 8473static int evalbltin(const struct builtincmd *, int, char **, int);
8474static void prehash(union node *); 8474static void prehash(union node *);
8475 8475
8476/* 8476/*
@@ -9177,7 +9177,7 @@ returncmd(int argc UNUSED_PARAM, char **argv)
9177/* Forward declarations for builtintab[] */ 9177/* Forward declarations for builtintab[] */
9178static int breakcmd(int, char **) FAST_FUNC; 9178static int breakcmd(int, char **) FAST_FUNC;
9179static int dotcmd(int, char **) FAST_FUNC; 9179static int dotcmd(int, char **) FAST_FUNC;
9180static int evalcmd(int, char **) FAST_FUNC; 9180static int evalcmd(int, char **, int) FAST_FUNC;
9181static int exitcmd(int, char **) FAST_FUNC; 9181static int exitcmd(int, char **) FAST_FUNC;
9182static int exportcmd(int, char **) FAST_FUNC; 9182static int exportcmd(int, char **) FAST_FUNC;
9183#if ENABLE_ASH_GETOPTS 9183#if ENABLE_ASH_GETOPTS
@@ -9247,7 +9247,7 @@ static const struct builtincmd builtintab[] = {
9247#if ENABLE_ASH_BUILTIN_ECHO 9247#if ENABLE_ASH_BUILTIN_ECHO
9248 { BUILTIN_REGULAR "echo" , echocmd }, 9248 { BUILTIN_REGULAR "echo" , echocmd },
9249#endif 9249#endif
9250 { BUILTIN_SPEC_REG "eval" , evalcmd }, 9250 { BUILTIN_SPEC_REG "eval" , NULL }, /*evalcmd() has a differing prototype*/
9251 { BUILTIN_SPEC_REG "exec" , execcmd }, 9251 { BUILTIN_SPEC_REG "exec" , execcmd },
9252 { BUILTIN_SPEC_REG "exit" , exitcmd }, 9252 { BUILTIN_SPEC_REG "exit" , exitcmd },
9253 { BUILTIN_SPEC_REG_ASSG "export" , exportcmd }, 9253 { BUILTIN_SPEC_REG_ASSG "export" , exportcmd },
@@ -9567,7 +9567,7 @@ evalcommand(union node *cmd, int flags)
9567 * to reap the zombie and make kill detect that it's gone: */ 9567 * to reap the zombie and make kill detect that it's gone: */
9568 dowait(DOWAIT_NONBLOCK, NULL); 9568 dowait(DOWAIT_NONBLOCK, NULL);
9569 9569
9570 if (evalbltin(cmdentry.u.cmd, argc, argv)) { 9570 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9571 int exit_status; 9571 int exit_status;
9572 int i = exception_type; 9572 int i = exception_type;
9573 if (i == EXEXIT || i == EXEXEC) 9573 if (i == EXEXIT || i == EXEXEC)
@@ -9612,11 +9612,12 @@ evalcommand(union node *cmd, int flags)
9612} 9612}
9613 9613
9614static int 9614static int
9615evalbltin(const struct builtincmd *cmd, int argc, char **argv) 9615evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9616{ 9616{
9617 char *volatile savecmdname; 9617 char *volatile savecmdname;
9618 struct jmploc *volatile savehandler; 9618 struct jmploc *volatile savehandler;
9619 struct jmploc jmploc; 9619 struct jmploc jmploc;
9620 int status;
9620 int i; 9621 int i;
9621 9622
9622 savecmdname = commandname; 9623 savecmdname = commandname;
@@ -9628,10 +9629,14 @@ evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9628 commandname = argv[0]; 9629 commandname = argv[0];
9629 argptr = argv + 1; 9630 argptr = argv + 1;
9630 optptr = NULL; /* initialize nextopt */ 9631 optptr = NULL; /* initialize nextopt */
9631 exitstatus = (*cmd->builtin)(argc, argv); 9632 if (cmd == EVALCMD)
9633 status = evalcmd(argc, argv, flags);
9634 else
9635 status = (*cmd->builtin)(argc, argv);
9632 flush_stdout_stderr(); 9636 flush_stdout_stderr();
9637 status |= ferror(stdout);
9638 exitstatus = status;
9633 cmddone: 9639 cmddone:
9634 exitstatus |= ferror(stdout);
9635 clearerr(stdout); 9640 clearerr(stdout);
9636 commandname = savecmdname; 9641 commandname = savecmdname;
9637 exception_handler = savehandler; 9642 exception_handler = savehandler;
@@ -12241,7 +12246,7 @@ expandstr(const char *ps)
12241 * Execute a command or commands contained in a string. 12246 * Execute a command or commands contained in a string.
12242 */ 12247 */
12243static int 12248static int
12244evalstring(char *s, int mask) 12249evalstring(char *s, int flags)
12245{ 12250{
12246 union node *n; 12251 union node *n;
12247 struct stackmark smark; 12252 struct stackmark smark;
@@ -12255,7 +12260,7 @@ evalstring(char *s, int mask)
12255 while ((n = parsecmd(0)) != NODE_EOF) { 12260 while ((n = parsecmd(0)) != NODE_EOF) {
12256 int i; 12261 int i;
12257 12262
12258 i = evaltree(n, 0); 12263 i = evaltree(n, flags);
12259 if (n) 12264 if (n)
12260 status = i; 12265 status = i;
12261 popstackmark(&smark); 12266 popstackmark(&smark);
@@ -12266,7 +12271,6 @@ evalstring(char *s, int mask)
12266 popfile(); 12271 popfile();
12267 stunalloc(s); 12272 stunalloc(s);
12268 12273
12269 evalskip &= mask;
12270 return status; 12274 return status;
12271} 12275}
12272 12276
@@ -12274,7 +12278,7 @@ evalstring(char *s, int mask)
12274 * The eval command. 12278 * The eval command.
12275 */ 12279 */
12276static int FAST_FUNC 12280static int FAST_FUNC
12277evalcmd(int argc UNUSED_PARAM, char **argv) 12281evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12278{ 12282{
12279 char *p; 12283 char *p;
12280 char *concat; 12284 char *concat;
@@ -12294,7 +12298,7 @@ evalcmd(int argc UNUSED_PARAM, char **argv)
12294 STPUTC('\0', concat); 12298 STPUTC('\0', concat);
12295 p = grabstackstr(concat); 12299 p = grabstackstr(concat);
12296 } 12300 }
12297 return evalstring(p, ~SKIPEVAL); 12301 return evalstring(p, flags & EV_TESTED);
12298 } 12302 }
12299 return 0; 12303 return 0;
12300} 12304}
@@ -13112,6 +13116,7 @@ exitshell(void)
13112 p = trap[0]; 13116 p = trap[0];
13113 if (p) { 13117 if (p) {
13114 trap[0] = NULL; 13118 trap[0] = NULL;
13119 evalskip = 0;
13115 evalstring(p, 0); 13120 evalstring(p, 0);
13116 free(p); 13121 free(p);
13117 } 13122 }