/bin/sh compatibility issue
Johannes Hofmann
Johannes.Hofmann at gmx.de
Wed May 17 10:53:59 PDT 2006
The commited patch fixes the problem.
Thanks,
Johannes
YONETANI Tomokazu <qhwt+dfly at xxxxxxxxxx> wrote:
> On Wed, May 10, 2006 at 05:59:05PM +0100, Steve O'Hara-Smith wrote:
>> On Wed, 10 May 2006 17:49:38 +0200
>> joerg at xxxxxxxxxxxxxxxxx wrote:
>>
>> > On Wed, May 10, 2006 at 03:39:53PM +0000, Johannes Hofmann wrote:
>> > > The following shell script outputs "false1" with all shells I tried
>> > > but with /bin/sh on DragonFly. Is this a known incompatibility?
>> >
>> > I have to read the POSIX definitions, but this doesn't look very wrong
>> > at least. Actually, I can understand this behaviour at the very least.
>>
>> It doesn't seem to be consistent with the description of -e
>> in the sh manpage.
>>
>> -e errexit
>> Exit immediately if any untested command fails in non-interactive mode.
>> The exit status of a command is considered to be explicitly tested if the
>> command is used to control an if, elif, while, or until; or if the command
>> is the left hand operand of an ``&&'' or ``||'' operator.
>>
>> I've quoted the script with added comments.
>>
>> #!/bin/sh
>> set -e
>> if true; then
>> false && echo "huh?" # This shouldn't exit because false is LHS of &&
>> fi
>> echo "false1"
>> false # This should exit because false is not explicitly tested
>> echo "false2"
>
> /bin/sh in FreeBSD-4.x has the same problem, but not in FreeBSD-5.x or later.
> The revisions 1.38,1.41 of eval.c fixes this behavior, but hasn't been MFC'ed
> to 4.x(therefore we don't have it either). The commitlog recommends
> that it should be MFC'ed after longer than usual, but I think two and a half
> year is long enough :)
> Revisions 1.44-1.46 also seem to be -e related fixes.
>
> diff -r 89a6bb686df8 bin/sh/eval.c
> --- bin/sh/eval.c Wed May 03 06:28:01 2006 +0000
> +++ bin/sh/eval.c Thu May 11 11:45:37 2006 +0900
> @@ -202,7 +202,6 @@ evaltree(union node *n, int flags)
> case NAND:
> evaltree(n->nbinary.ch1, EV_TESTED);
> if (evalskip || exitstatus != 0) {
> - flags |= EV_TESTED;
> goto out;
> }
> evaltree(n->nbinary.ch2, flags);
> @@ -243,25 +242,9 @@ evaltree(union node *n, int flags)
> break;
> case NFOR:
> evalfor(n);
> - /*
> - * The 'for' command does not set exitstatus, so the value
> - * now in exitstatus is from the last command executed in
> - * the 'for' loop. That exit value had been tested (wrt
> - * 'sh -e' checking) while processing that command, and
> - * it should not be re-tested here.
> - */
> - flags |= EV_TESTED;
> break;
> case NCASE:
> evalcase(n, flags);
> - /*
> - * The 'case' command does not set exitstatus, so the value
> - * now in exitstatus is from the last command executed in
> - * the 'case' block. That exit value had been tested (wrt
> - * 'sh -e' checking) while processing that command, and
> - * it should not be re-tested here.
> - */
> - flags |= EV_TESTED;
> break;
> case NDEFUN:
> defun(n->narg.text, n->narg.next);
> @@ -286,14 +269,9 @@ out:
> out:
> if (pendingsigs)
> dotrap();
> - /*
> - * XXX - Like "!(n->type == NSEMI)", more types will probably
> - * need to be excluded from this test. It's probably better
> - * to set or unset EV_TESTED in the loop above than to bloat
> - * the conditional here.
> - */
> if ((flags & EV_EXIT) || (eflag && exitstatus
> - && !(flags & EV_TESTED) && !(n->type == NSEMI)))
> + && !(flags & EV_TESTED) && (n->type == NCMD ||
> + n->type == NSUBSHELL)))
> exitshell(exitstatus);
> }
>
More information about the Users
mailing list