On Wed, Jun 22, 2005 at 02:15:22PM -0400, Joey Hess wrote:
> [EMAIL PROTECTED]:~>cat test
> set -e
> eval false || true
> exit 0
> [EMAIL PROTECTED]:~>busybox sh test
> zsh: exit 1     busybox sh test
> [EMAIL PROTECTED]:~>sh test
> [EMAIL PROTECTED]:~>dash test
> [EMAIL PROTECTED]:~>bash test
> [EMAIL PROTECTED]:~>zsh test   
> [EMAIL PROTECTED]:~>
> 
> 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                                       [EMAIL PROTECTED]


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to