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).
This commit is contained in:
kre 2021-11-16 11:28:29 +00:00
parent b65a5b9068
commit 8ea2ac47d5
2 changed files with 193 additions and 43 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec.c,v 1.56 2021/10/10 08:19:02 rillig Exp $ */
/* $NetBSD: exec.c,v 1.57 2021/11/16 11:28:29 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
#else
__RCSID("$NetBSD: exec.c,v 1.56 2021/10/10 08:19:02 rillig Exp $");
__RCSID("$NetBSD: exec.c,v 1.57 2021/11/16 11:28:29 kre Exp $");
#endif
#endif /* not lint */
@ -360,18 +360,25 @@ hashcmd(int argc, char **argv)
struct cmdentry entry;
char *name;
int allopt=0, bopt=0, fopt=0, ropt=0, sopt=0, uopt=0, verbose=0;
int errs=1, emsg=DO_ERR;
int status = 0;
while ((c = nextopt("bcfrsuv")) != '\0')
while ((c = nextopt("bcefqrsuv")) != '\0')
switch (c) {
case 'b': bopt = 1; break;
case 'c': uopt = 1; break; /* c == u */
case 'e': errs = 0; break;
case 'f': fopt = 1; break;
case 'q': emsg = 0; break;
case 'r': ropt = 1; break;
case 's': sopt = 1; break;
case 'u': uopt = 1; break;
case 'v': verbose = 1; break;
}
if (!errs)
emsg ^= DO_ERR;
if (ropt)
clearcmdentry(0);
@ -406,6 +413,11 @@ hashcmd(int argc, char **argv)
printentry(cmdp, verbose);
}
}
flushout(out1);
if (io_err(out1)) {
out2str("hash: I/O error writing to standard output\n");
return 1;
}
return 0;
}
@ -433,7 +445,9 @@ hashcmd(int argc, char **argv)
break;
}
}
find_command(name, &entry, DO_ERR, pathval());
find_command(name, &entry, emsg, pathval());
if (errs && entry.cmdtype == CMDUNKNOWN)
status = 1;
if (verbose) {
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
cmdp = cmdlookup(name, 0);
@ -443,7 +457,7 @@ hashcmd(int argc, char **argv)
flushall();
}
}
return 0;
return status;
}
STATIC void

View File

@ -1,4 +1,4 @@
.\" $NetBSD: sh.1,v 1.236 2021/10/31 02:12:08 kre Exp $
.\" $NetBSD: sh.1,v 1.237 2021/11/16 11:28:29 kre Exp $
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@ -2356,7 +2356,7 @@ last, in the character class.
.\"
.Ss Built-ins
.\"
This section lists the built-in commands which are built-in because they
This section lists the built-in commands which are built in because they
need to perform some operation that can't be performed by a separate
process.
Or just because they traditionally are.
@ -2366,11 +2366,16 @@ be built in for efficiency (e.g.
.Xr echo 1 ,
.Xr test 1 ,
etc).
Most built-in commands will exit with status 2 if used incorrectly
(bad options, excess or insufficient number of args, etc).
Otherwise, unless stated differently, the built-in commands exit with status 0,
unless some error occurs, which would be reported to standard error.
.Bl -tag -width 5n -compact
.Pp
.It Ic \&: Op Ar arg ...
A null command that returns a 0 (true) exit value.
Any arguments or redirects are evaluated, then ignored.
Any arguments or redirects are evaluated just as for any other command,
then ignored.
.\"
.Pp
.It Ic \&. Ar file
@ -2427,18 +2432,24 @@ have a shell function with the same name as a command.)
.It Fl p
search for command using a
.Ev PATH
that guarantees to find all the standard utilities.
that guarantees to find all the standard utilities,
but not necessarily any others.
.It Fl V
Do not execute the command but
search for the command and print the resolution of the
command search.
Do not execute the
.Ar command
but search for the
.Ar command
and print the resolution of the command search.
This is the same as the
.Ic type
built-in.
.It Fl v
Do not execute the command but
search for the command and print the absolute pathname
of utilities, the name for built-ins or the expansion of aliases.
Do not execute the
.Ar command
but search for the
.Ar command
and print the absolute pathname of utilities,
the name for built-ins or the expansion of aliases.
.El
.\"
.Pp
@ -2450,7 +2461,7 @@ If
is specified, then the new directory name is generated by replacing
the first occurrence of the string
.Ar directory
in the current directory name with
in the current working directory name with
.Ar replace .
Otherwise if
.Ar directory
@ -2465,11 +2476,14 @@ appears in the environment of the
.Ic cd
command or the shell variable
.Ev CDPATH
is set and the directory name does not begin with a slash,
is set and the
.Ar directory
name does not begin with a slash,
and its first (or only) component isn't dot or dot dot,
then the directories listed in
.Ev CDPATH
will be searched for the specified directory.
will be searched for the specified
.Ar directory .
The format of
.Ev CDPATH
is the same as that of
@ -2520,8 +2534,8 @@ Some shells also support a
.Fl L
option, which instructs the shell to update
.Ev PWD
with the logical path and to change the current directory
accordingly.
with the logical path using string manipulation,
and then to change the current directory accordingly.
This is not supported.
.Pp
In an interactive shell, or if the
@ -2529,7 +2543,7 @@ In an interactive shell, or if the
option is set, the
.Ic cd
command will print out the name of the
directory that it actually switched to
directory that it actually switched to;
.Po that is, the pathname passed to the successful
.Xr chdir 2
.No system call Pc
@ -2542,7 +2556,7 @@ The destination may be different because
a non-empty element of the
.Ev CDPATH
mechanism was used,
.\" or because a symbolic link was crossed. XXX Definitively not.
.\" or because a symbolic link was crossed. XXX Definitively not (not even -L)
or because the
.Ar replace
argument was used,
@ -2553,8 +2567,13 @@ parameter was specified as
.\"
.Pp
.It Ic eval Ar string ...
Concatenate all the arguments with spaces.
Then re-parse and execute the command.
Concatenate all the
.Ar string
arguments with intervening spaces.
Then parse and execute the command resulting.
The exit status from
.Ic eval
is the exit status of the command executed, or 0 if there was none.
.\"
.Pp
.It Ic exec Op Ar command Op Ar arg ...
@ -2590,9 +2609,9 @@ redirect the descriptor to (or from) itself,
either when invoking a command for which the descriptor is wanted open,
or by using
.Ic exec
(perhaps the same
.Po perhaps the same
.Ic exec
as opened it, after the open)
.No as opened it, after the open Pc
to leave the descriptor open in the shell
and pass it to all commands invoked subsequently.
Alternatively, see the
@ -2624,7 +2643,8 @@ Variables can also be un-exported using the
built in command.
With
.Fl x
(exclude) the specified names are marked not to be exported,
.Pq exclude
the specified names are marked not to be exported,
and any that had been exported, will be un-exported.
Later attempts to export the variable will be refused.
Note this does not prevent explicitly exporting a variable
@ -2633,11 +2653,14 @@ command invocation by a variable assignment to that variable,
provided the variable is not also read-only.
That is
.Bd -literal -offset indent
export -x FOO # FOO will now not be exported by default
export -x FOO # FOO will now not be able to be exported
export FOO # this command will fail (non-fatally)
.Ed
But with
.Bd -literal -offset indent -compact
FOO=some_value my_command
.Ed
.Pp
.Nm
still passes the value
.Pq Li FOO=some_value
to
@ -2964,29 +2987,145 @@ cmd \-a \-carg \-\- file file
.Ed
.\"
.Pp
.It Ic hash Oo Fl rv Oc Op Ar command ...
.It Ic hash Oo Fl befqrsuv Oc Op Ar command ...
The shell maintains a hash table which remembers the
locations of commands.
With no arguments whatsoever,
locations and types of commands.
With the
.Fl r
option given,
the
.Ic hash
command prints out the contents of this table.
Entries which have not been looked at since the last
command begins by clearing all commands,
except special built-in commands and functions,
from this table.
Commands, other than functions, are added to the table as
described below, or as they are encountered
through normal execution, or for functions,
when they are defined.
Functions are removed with the
.Ic unset
built-in command.
Special built-in commands are added at shell startup,
and never removed.
Utilities can also be removed when
.Ev PATH
is altered.
.Pp
With no
.Ar command
arguments
the
.Ic hash
command then prints out the contents of this table.
Note that this is a hash table, the order of the
contents is unpredictable, and meaningless.
.Pp
The
.Fl b ,
.Fl f ,
.Fl s ,
and
.Fl u
oprions control which entries are printed.
With
.Fl f
functions are printed; with
.Fl b
or
.Fl s
regular, or special, built-in commands are listed;
and with
.Fl u
normal utilities (those commands found in the filesystem
by searching
.Ev PATH )
are printed.
For compatibility with some older versions of the
.Ic hash
command,
.Fl c
is accepted as an alternative of
.Fl u .
.Pp
Some normal command entries which have not been verified since the last
.Ic cd
command are marked with an asterisk; it is possible for these entries
to be invalid.
.Pp
With arguments, the
The
.Fl v
option causes more verbose output to be included, indicating the
type of the command, rather than simply its name.
For functions, the body of the function is included.
.Pp
If none of the above options is given, the default is to
show normal commands only.
With
.Fl v
and no other options, the whole table (all types) will be shown.
.Pp
Unless there is an error writing the output, the
.Ic hash
command will exit with status 0 in this usage.
.Pp
With
.Ar command
arguments, the
.Ic hash
command removes the specified commands from the hash table (unless
they are functions) and then locates them.
they are functions or special built-in commands) and then locates
and reinstalls them.
With the
.Fl v
option, hash prints the locations of the commands as it finds them.
option,
.Ic hash
prints the locations of the commands as it finds them.
The
.Fl r
option causes the hash command to delete all the entries in the hash table
except for functions.
.Fl bfsu
options control which types of commands will be affected.
If any of those options is given, and a command found to
already be in the hash table is not one of the designated types,
that entry, and the
.Ar command
argument, will simply be silently skipped.
If none of those flags is given, any command type can be affected.
.Pp
If a
.Ar command
is not located, then unless
.Fl q
was given, a
.Dq not found
error message will be printed.
.Pp
The
.Fl e
option implies
.Fl q
if that option was not given, and also causes the exit status
of the
.Ic hash
command to ignore the unfound
.Ar command .
Otherwise if any
.Ar command
is not found, the
.Ic hash
command will exit with status 1.
.Pp
To allow a method to premit backwards compatability with the way
that the
.Ic hash
command worked before
.Nx 10
if both the
.Fl e
and
.Fl q
options are given, then an error message will be printed about
.Ar command Ns No s
unable to be found, but the exit status will remain 0.
This is not considered useful.
.\"
.Pp
.It Ic inputrc Ar file
@ -3310,9 +3449,6 @@ is checked to see if it refers to the current directory; if it does
the value is printed.
Otherwise the current directory name is found using
.Xr getcwd 3 .
The environment variable
.Ev PWD
is set to the printed value.
.Pp
The default is
.Ic pwd