aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-08-11 20:48:15 +1000
committermaximilian attems <max@stro.at>2010-03-22 00:29:17 +0100
commitc9c9390fbea8cd7dfe15188632cc17b0a45b76fe (patch)
treef8b63233ecd0acbcaae891ba43f3572e30c7f0e5
parent96ecdb25ae8951c5a0720f38cc5b8322681b2eaf (diff)
downloadklibc-c9c9390fbea8cd7dfe15188632cc17b0a45b76fe.tar.gz
[klibc] [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> Signed-off-by: maximilian attems <max@stro.at>
-rw-r--r--usr/dash/builtins.def.in3
-rw-r--r--usr/dash/eval.c26
-rw-r--r--usr/dash/histedit.c4
-rw-r--r--usr/dash/mkbuiltins3
-rw-r--r--usr/dash/trap.c3
5 files changed, 23 insertions, 16 deletions
diff --git a/usr/dash/builtins.def.in b/usr/dash/builtins.def.in
index cfb69d78c20a1..7f5f0b568f4b6 100644
--- a/usr/dash/builtins.def.in
+++ b/usr/dash/builtins.def.in
@@ -40,6 +40,7 @@
* The -a flag specifies that this is a posix 'assignment builtin' command.
* The -s flag specifies that this is a posix 'special builtin' command.
* The -u flag specifies that this is a posix 'standard utility'.
+ * The -n flag specifies that this command has a special entry point.
* The rest of the line specifies the command name or names used to run
* the command.
*/
@@ -62,7 +63,7 @@ cdcmd -u cd chdir
commandcmd -u command
dotcmd -s .
echocmd echo
-evalcmd -s eval
+evalcmd -ns eval
execcmd -s exec
exitcmd -s exit
exportcmd -as export -as readonly
diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index e353ed11a68e2..b462b0fb5146a 100644
--- a/usr/dash/eval.c
+++ b/usr/dash/eval.c
@@ -97,7 +97,7 @@ STATIC void evalcommand(union node *, int, struct backcmd *);
#else
STATIC void evalcommand(union node *, int);
#endif
-STATIC int evalbltin(const struct builtincmd *, int, char **);
+STATIC int evalbltin(const struct builtincmd *, int, char **, int);
STATIC int evalfun(struct funcnode *, int, char **, int);
STATIC void prehash(union node *);
STATIC int eprintlist(struct output *, struct strlist *, int);
@@ -129,8 +129,7 @@ RESET {
* The eval commmand.
*/
-int
-evalcmd(int argc, char **argv)
+static int evalcmd(int argc, char **argv, int flags)
{
char *p;
char *concat;
@@ -150,7 +149,7 @@ evalcmd(int argc, char **argv)
STPUTC('\0', concat);
p = grabstackstr(concat);
}
- return evalstring(p, ~SKIPEVAL);
+ return evalstring(p, flags & EV_TESTED);
}
return 0;
}
@@ -161,7 +160,7 @@ evalcmd(int argc, char **argv)
*/
int
-evalstring(char *s, int mask)
+evalstring(char *s, int flags)
{
union node *n;
struct stackmark smark;
@@ -172,7 +171,7 @@ evalstring(char *s, int mask)
status = 0;
while ((n = parsecmd(0)) != NEOF) {
- evaltree(n, 0);
+ evaltree(n, flags);
status = exitstatus;
popstackmark(&smark);
if (evalskip)
@@ -180,7 +179,6 @@ evalstring(char *s, int mask)
}
popfile();
- evalskip &= mask;
return status;
}
@@ -861,7 +859,7 @@ bail:
}
listsetvar(list, i);
}
- if (evalbltin(cmdentry.u.cmd, argc, argv)) {
+ if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
int status;
int i;
@@ -899,10 +897,12 @@ out:
}
STATIC int
-evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
+evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
+{
char *volatile savecmdname;
struct jmploc *volatile savehandler;
struct jmploc jmploc;
+ int status;
int i;
savecmdname = commandname;
@@ -913,10 +913,14 @@ evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
commandname = argv[0];
argptr = argv + 1;
optptr = NULL; /* initialize nextopt */
- exitstatus = (*cmd->builtin)(argc, argv);
+ if (cmd == EVALCMD)
+ status = evalcmd(argc, argv, flags);
+ else
+ status = (*cmd->builtin)(argc, argv);
flushall();
+ status |= outerr(out1);
+ exitstatus = status;
cmddone:
- exitstatus |= outerr(out1);
freestdout();
commandname = savecmdname;
handler = savehandler;
diff --git a/usr/dash/histedit.c b/usr/dash/histedit.c
index 36d79377e6c48..9a1e533f7d9e2 100644
--- a/usr/dash/histedit.c
+++ b/usr/dash/histedit.c
@@ -371,7 +371,7 @@ histcmd(int argc, char **argv)
}
evalstring(strcpy(stalloc(strlen(s) + 1), s),
- ~0);
+ 0);
if (displayhist && hist) {
/*
* XXX what about recursive and
@@ -396,7 +396,7 @@ histcmd(int argc, char **argv)
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
sprintf(editcmd, "%s %s", editor, editfile);
/* XXX - should use no JC command */
- evalstring(editcmd, ~0);
+ evalstring(editcmd, 0);
INTON;
readcmdfile(editfile); /* XXX - should read back - quick tst */
unlink(editfile);
diff --git a/usr/dash/mkbuiltins b/usr/dash/mkbuiltins
index dc0212bd73c55..6f9b0f3bc0003 100644
--- a/usr/dash/mkbuiltins
+++ b/usr/dash/mkbuiltins
@@ -71,7 +71,8 @@ awk '{ for (i = 2 ; i <= NF ; i++) {
opt = substr($2, 2)
$2 = $3
}
- printf "\t{ \"%s\", %s, %d },\n", $1, $2,
+ printf "\t{ \"%s\", %s, %d },\n", $1,
+ (opt ~ /n/) ? "NULL" : $2,
(opt ~ /s/) + (opt ~ /[su]/) * 2 + (opt ~ /a/) * 4
}'
echo '};'
diff --git a/usr/dash/trap.c b/usr/dash/trap.c
index 08c3317fc9279..e7a35d4aa0c20 100644
--- a/usr/dash/trap.c
+++ b/usr/dash/trap.c
@@ -309,7 +309,7 @@ dotrap(void)
p = trap[i + 1];
if (!p)
continue;
- evalstring(p, SKIPEVAL);
+ evalstring(p, 0);
exitstatus = savestatus;
if (evalskip)
return evalskip;
@@ -364,6 +364,7 @@ exitshell(void)
handler = &loc;
if ((p = trap[0])) {
trap[0] = NULL;
+ evalskip = 0;
evalstring(p, 0);
}
out: