NetBSD Problem Report #56491
From kre@munnari.OZ.AU Tue Nov 9 15:16:12 2021
Return-Path: <kre@munnari.OZ.AU>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 62C961A9239
for <gnats-bugs@gnats.NetBSD.org>; Tue, 9 Nov 2021 15:16:12 +0000 (UTC)
Message-Id: <202111091516.1A9FG6qE003112@jinx.noi.kre.to>
Date: Tue, 9 Nov 2021 22:16:06 +0700 (+07)
From: kre@munnari.OZ.AU
To: gnats-bugs@NetBSD.org
Subject: /bin/sh hash command "hash foobar" says foobar not found, and exit(0)
X-Send-Pr-Version: 3.95
>Number: 56491
>Category: bin
>Synopsis: /bin/sh hash command "hash foobar" says foobar not found, and exit(0)
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kre
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Nov 09 15:20:01 +0000 2021
>Closed-Date: Tue Nov 16 11:49:56 +0000 2021
>Last-Modified: Tue Nov 16 11:49:56 +0000 2021
>Originator: Robert Elz
>Release: NetBSD 9.99.88
>Organization:
>Environment:
System: NetBSD jinx.noi.kre.to 9.99.88 NetBSD 9.99.88 (1.1-20210916) #60: Thu Sep 16 23:18:32 UTC 2021 root@agate.noi.kre.to:/usr/obj/HEAD/kernels/amd64/JINX amd64
Architecture: x86_64
Machine: amd64
>Description:
The hash builtin utiliity in /bin/sh when run naming a utility
to be added to the hash table, and the utility is not found,
writes an error message to stderr indicating that the utility
was not found, but goes on to exit(0).
POSIX (for most standard utilities, including this one) specifies that
when stderr is used, the utility must not exit(0) (sometimes more
specific exit status conditions, but never 0 in that case.
It isn't clear (yet) whether the correct fix is to exit(1) when
a utility was not found, or to suppress the error message.
All ksh variants simply ignore "not found" - no error message,
and the exit status is 0. All other (known and relevant) shells
(bash dash, freebsd, yash, zsh, bosh) write an error message,
and eventually exit(1).
>How-To-Repeat:
Assuming there is o foobar command in any directory in PATH
hash foobar
echo $?
>Fix:
TBD (either way is a trivial change).
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: bin-bug-people->kre
Responsible-Changed-By: kre@NetBSD.org
Responsible-Changed-When: Tue, 09 Nov 2021 15:21:44 +0000
Responsible-Changed-Why:
Mine.
From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/56491: /bin/sh hash command "hash foobar" says foobar not found, and exit(1)
Date: Sun, 14 Nov 2021 08:41:20 +0700
For this (see the original PR for the details) I am considering having
the best of all worlds (since it is so simple - the change is truly trivial).
That is, make the default be like bash/dash/ ... (everything
not a ksh variant) which makes "hash foobar" generate an error
just like now, but will exit 1 instead of 0 if any command to
be added to the hash table is not found. That takes adding
one test to see if the command was found, and making the return
value be a variable rather than const 0.
Then add a -e option (no errors) to make it work the ksh way,
which means suppressing the error message (one arg to the lookup
routine changes value), and continue to exit(0).
And since all this is so easy, add a -q (quiet) option which will
suppress the "not found" error message, but still result in an
exit(1) in the case that a command named was not found. This is
similar to hash command 2>/dev/null except that any other errors would
still appear on stderr, only the "command not found" would be skipped.
Then, just because it is so simple, make -e invert the sense of
whatever -q gets set to, then use just -q to decide whether to suppress
the error message internally (and -e just for the exit status).
This makes hash -e do what we want (-q is implicitly set to suppress
the error), and hash -eq return to what NetBSD "hash" command has been
doing forever (generate the not found error message (as -q gets inverted
by -e), but exit(0)). I don't see this being very useful, but it does
provide a backwards compat variant, and is cost free.
The most difficult part of all of this is the man page update - and not to
document these new options, but, to document the other options that the
hash command has had for quite a while now, but never got documented.
Any comments before I commit this?
kre
From: "Robert Elz" <kre@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/56491 CVS commit: src/bin/sh
Date: Tue, 16 Nov 2021 11:28:29 +0000
Module Name: src
Committed By: kre
Date: Tue Nov 16 11:28:29 UTC 2021
Modified Files:
src/bin/sh: exec.c sh.1
Log Message:
PR bin/56491
Make "hash" exit(!=0) (ie: exit(1)) if it writes an error message to
stderr as required by POSIX (it was writing "not found" errors, yet
still doing exit(0)).
Whether, when doing "hash foobar", and "foobar" is not found as a command
(not a built-in, not a function, and not found via a PATH search), that
should be considered an error differs between shells. All of the ksh
descendant shells say "no", write no error message in this case, and
exit(0) if no other errors occur. Other shells (essentially all) do
consider it an error, write a message to stderr, and exit(1) when this happens.
POSIX isn't clear, the bug report:
https://austingroupbugs.net/view.php?id=1460
which is not yet resolved, suggests that the outcome will be that
this is to be unspecified. Given the diversity, there might be no
other choice.
Have a foot in both camps - default to the "other shell" behaviour,
but add a -e option (no errors ... applies only to these "not found"
errors) to generate the ksh behaviour. Without other errors (like an
unknown option, etc) "hash -e anyname" will always exit(0).
See the PR for details on how it all works now, or read the updated man page.
While here, when hash is in its other mode (reporting what is in the
table) check for I/O errors on stdout, and exit(1) (with an error
message!) if any occurred. This does not apply to output generated
by the -v option when command names are given (that output is incidental).
In sh.1 document all of this. Also add documentation for a bunch of
other options the hash command has had for years, but which were never
documented. And while there, clean up some other sections I noticed
needed improving (either formatting or content or both).
To generate a diff of this commit:
cvs rdiff -u -r1.56 -r1.57 src/bin/sh/exec.c
cvs rdiff -u -r1.236 -r1.237 src/bin/sh/sh.1
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
State-Changed-From-To: open->closed
State-Changed-By: kre@NetBSD.org
State-Changed-When: Tue, 16 Nov 2021 11:49:56 +0000
State-Changed-Why:
Problem fixed
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.46 2020/01/03 16:35:01 leot Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2020
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.