Subject: bin/36435: sh(1) bug with exit status of negated pipelines
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <giles.lean@pobox.com>
List: netbsd-bugs
Date: 06/04/2007 01:50:00
>Number: 36435
>Category: bin
>Synopsis: sh -c 'true && ! true | false' returns non-zero status
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Jun 04 01:50:00 +0000 2007
>Originator: Giles Lean
>Release: NetBSD 4.0_BETA2
>Organization:
>Environment:
System: NetBSD amethyst.netherstone.net 4.0_BETA2 NetBSD 4.0_BETA2 (AMETHYST) #12: Tue May 29 08:01:56 EST 2007 unpriv@amethyst.netherstone.net:/usr/local/NetBSD/netbsd-4/obj/sys/arch/i386/compile/AMETHYST i386
Architecture: i386
Machine: i386
>Description:
The following command has an exit status of one but should have zero:
$ sh -c 'true && ! true | false'
$ echo $?
1
In comparison, ksh returns zero:
$ ksh -c 'true && ! true | false'
$ echo $?
0
The Shell Command Language standard (from "The Open Group
Base Specifications Issue 6", a.k.a. "IEEE Std 1003.1-2001")
says:
| Exit Status
|
| If the reserved word ! does not precede the pipeline, the
| exit status shall be the exit status of the last command
| specified in the pipeline. Otherwise, the exit status shall
| be the logical NOT of the exit status of the last command.
| That is, if the last command returns zero, the exit status
| shall be 1; if the last command returns greater than zero,
| the exit status shall be zero.
I interpret this to mean that NetBSD's sh(1) is wrong, and
that ksh(1) is right. I tested on the (limited) platforms
available to me with the following results:
Problematic behaviour: NetBSD 4.0_BETA2 sh(1)
FreeBSD 4.8 sh(1)
Expected behaviour: NetBSD 4.0_BETA2 ksh(1)
FreeBSD 4.8 ksh(1)
OS/X 10.4.9 sh(1), ksh(1), bash(1)
For background and future searching, I found this while building
git-1.5.2. Some tests such as this one failed in t3700-add.sh:
git-add . &&
! git-ls-files | grep "\\.ig"
In this test the grep pattern should not matc, so the overall
result should be grep's non-zero exit status negated by '!'.
>How-To-Repeat:
$ sh -c 'true && ! true | false'
$ echo $?
1
>Fix:
>Unformatted: