Bug#315444: test case
On Wed, Jun 22, 2005 at 02:15:22PM -0400, Joey Hess wrote:
> joey@dragon:~>cat test
> set -e
> eval false || true
> exit 0
> joey@dragon:~>busybox sh test
> zsh: exit 1 busybox sh test
> joey@dragon:~>sh test
> joey@dragon:~>dash test
> joey@dragon:~>bash test
> joey@dragon:~>zsh test
> joey@dragon:~>
>
> Workarond is to enclose the eval statement in parens, so this will work in
> debootstrap:
>
> (eval $(eval echo \${EXIT_THING_$n})) 2>/dev/null || true
>
> Cloning the bug to busybox, I'm using 1.00 in the test above, though
> busybox-cvs must also have the bug.
This is a rather hacky patch against busybox-cvs (but should apply to
busybox without too much trouble) for this.
Unfortunately I had to take the approach of avoiding throwing the
exception in the first place, necessitating a static variable, rather
than catching the exception in evalbltin() if flags & EV_TESTED, which I
think would have been much neater. However, when I tried to take the
latter approach, I apparently didn't manage to restore all the
pre-exception state properly or something, because immediately after
evaluating 'eval false || true' the (interactive) shell decided it had
hit EOF on input and exited. Somebody who understands busybox ash better
might want to look into this.
I also haven't run this through a shell test suite to make sure I didn't
break anything else. That really needs to happen before applying this to
the Debian package.
diff -u busybox-cvs-20040623/shell/ash.c busybox-cvs-20040623/shell/ash.c
--- busybox-cvs-20040623/shell/ash.c
+++ busybox-cvs-20040623/shell/ash.c
@@ -1218,7 +1218,7 @@
-static void evalstring(char *);
+static void evalstring(char *, int);
union node; /* BLETCH for ansi C */
static void evaltree(union node *, int);
static void evalbackcmd(union node *, struct backcmd *);
@@ -1229,6 +1229,8 @@
static int skipcount; /* number of levels to skip */
static int funcnest; /* depth of function calls */
+static int bltintested = 0; /* builtin command tested; appease set -e */
+
/* reasons for skipping commands (see comment on breakcmd routine) */
#define SKIPBREAK 1
#define SKIPCONT 2
@@ -2692,7 +2694,7 @@
static void expredir(union node *);
static void evalpipe(union node *, int);
static void evalcommand(union node *, int);
-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 bltincmd(int, char **);
@@ -2732,7 +2734,7 @@
STPUTC('\0', concat);
p = grabstackstr(concat);
}
- evalstring(p);
+ evalstring(p, bltintested ? EV_TESTED : 0);
}
return exitstatus;
}
@@ -2743,7 +2745,7 @@
*/
static void
-evalstring(char *s)
+evalstring(char *s, int flags)
{
union node *n;
struct stackmark smark;
@@ -2752,7 +2754,7 @@
setinputstring(s);
while ((n = parsecmd(0)) != NEOF) {
- evaltree(n, 0);
+ evaltree(n, flags);
popstackmark(&smark);
if (evalskip)
break;
@@ -3387,7 +3389,7 @@
}
listsetvar(list, i);
}
- if (evalbltin(cmdentry.u.cmd, argc, argv)) {
+ if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
int exit_status;
int i, j;
@@ -3432,9 +3434,10 @@
}
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;
+ volatile int savebltintested;
struct jmploc jmploc;
int i;
@@ -3446,10 +3449,14 @@
commandname = argv[0];
argptr = argv + 1;
optptr = NULL; /* initialize nextopt */
+ savebltintested = bltintested;
+ if (flags & EV_TESTED)
+ bltintested = 1;
exitstatus = (*cmd->builtin)(argc, argv);
flushall();
cmddone:
exitstatus |= ferror(stdout);
+ bltintested = savebltintested;
commandname = savecmdname;
exsig = 0;
handler = savehandler;
@@ -7966,7 +7973,7 @@
state3:
state = 4;
if (minusc)
- evalstring(minusc);
+ evalstring(minusc, 0);
if (sflag || minusc == NULL) {
#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
@@ -11817,7 +11824,7 @@
p = trap[p - q + 1];
if (!p)
continue;
- evalstring(p);
+ evalstring(p, 0);
exitstatus = savestatus;
}
}
@@ -11910,7 +11917,7 @@
handler = &loc;
if ((p = trap[0]) != NULL && *p != '\0') {
trap[0] = NULL;
- evalstring(p);
+ evalstring(p, 0);
}
flushall();
#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
--
Colin Watson [cjwatson@debian.org]
Reply to: