Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh PR bin/56491



details:   https://anonhg.NetBSD.org/src/rev/495af84690c9
branches:  trunk
changeset: 1026286:495af84690c9
user:      kre <kre%NetBSD.org@localhost>
date:      Tue Nov 16 11:28:29 2021 +0000

description:
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).

diffstat:

 bin/sh/exec.c |   24 +++++-
 bin/sh/sh.1   |  212 +++++++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 193 insertions(+), 43 deletions(-)

diffs (truncated from 422 to 300 lines):

diff -r 9334f4310b1e -r 495af84690c9 bin/sh/exec.c
--- a/bin/sh/exec.c     Tue Nov 16 11:27:50 2021 +0000
+++ b/bin/sh/exec.c     Tue Nov 16 11:28:29 2021 +0000
@@ -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 @@
        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 @@
                                        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 @@
                                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 @@
                        flushall();
                }
        }
-       return 0;
+       return status;
 }
 
 STATIC void
diff -r 9334f4310b1e -r 495af84690c9 bin/sh/sh.1
--- a/bin/sh/sh.1       Tue Nov 16 11:27:50 2021 +0000
+++ b/bin/sh/sh.1       Tue Nov 16 11:28:29 2021 +0000
@@ -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 @@
 .\"
 .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 @@
 .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 @@
 .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 @@
 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 @@
 .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 @@
 .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 @@
 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 @@
 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 @@
 .\"
 .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 @@
 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 @@
 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 @@
 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 @@
 .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 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 prints out the contents of this table.
-Entries which have not been looked at since the last
+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 ,



Home | Main Index | Thread Index | Old Index