Source-Changes-HG archive

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

[src/netbsd-9]: src/bin/sh Pull up following revision(s) (requested by kre in...



details:   https://anonhg.NetBSD.org/src/rev/d9ce34cacc12
branches:  netbsd-9
changeset: 991066:d9ce34cacc12
user:      martin <martin%NetBSD.org@localhost>
date:      Sat Nov 06 13:42:18 2021 +0000

description:
Pull up following revision(s) (requested by kre in ticket #1372):

        bin/sh/sh.1: revision 1.236 (patch)
        bin/sh/cd.c: revision 1.51

PR bin/45390 - fix for folly four

In the pwd builtin, verify that curdir names '.' before
simply printing it.   Never alter PWD or OLDPWD in the
pwd command.

Also while here, implement the (new: coming in POSIX, but has existed
for a while in several other shells) -e option to cd (with -e, cd -P
will exit(1) if the chdir() succeeds, but PWD cannot be discovered).
cd now prints the directory name used (if different from that given,
or cdprint is on) if interactive or (the new bit)in posix mode.

Some additional/changed comments added, and a DEBUG mode trace call
that was accidentally put inside an #if 0 block moved to where it
can do some good.

XXX pullup -9

PR bin/45390

Be explicit about what happens to PWD after a successful cd command.
Also be very clear  that "cd" and "cd -P" are the same thing, and
the only cd variant implemented.
Also, when it is appropriate to print the new directory after a cd
command, note that it happens if interactive (as it always has here)
and also if the posix option is set (for POSIX compat, where "interactive"
is irrelevant).  Mention that "cd -" is a case where the new directory
is printed (along with paths relative to a non-empty CDPATH entry,
and where the "cd old new" (string replacement in curdir) is used.

While here document the new -e option to cd.

XXX pullup -9

diffstat:

 bin/sh/cd.c |  100 ++++++++++++++++++++++++++++++++++++++++-------------------
 bin/sh/sh.1 |   80 +++++++++++++++++++++++++++++++++++------------
 2 files changed, 127 insertions(+), 53 deletions(-)

diffs (truncated from 366 to 300 lines):

diff -r c2de8d9762c6 -r d9ce34cacc12 bin/sh/cd.c
--- a/bin/sh/cd.c       Sat Nov 06 13:35:43 2021 +0000
+++ b/bin/sh/cd.c       Sat Nov 06 13:42:18 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cd.c,v 1.50 2017/07/05 20:00:27 kre Exp $      */
+/*     $NetBSD: cd.c,v 1.50.8.1 2021/11/06 13:42:18 martin Exp $       */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,12 +37,13 @@
 #if 0
 static char sccsid[] = "@(#)cd.c       8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: cd.c,v 1.50 2017/07/05 20:00:27 kre Exp $");
+__RCSID("$NetBSD: cd.c,v 1.50.8.1 2021/11/06 13:42:18 martin Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -67,10 +68,11 @@
 #include "show.h"
 #include "cd.h"
 
-STATIC int docd(const char *, int);
+STATIC int docd(const char *, bool, bool);
 STATIC char *getcomponent(void);
-STATIC void updatepwd(const char *);
+STATIC bool updatepwd(const char *);
 STATIC void find_curdir(int noerror);
+STATIC bool is_curdir(const char *);
 
 char *curdir = NULL;           /* current working directory */
 char *prevdir;                 /* previous working directory */
@@ -84,10 +86,13 @@
        char *p;
        char *d;
        struct stat statb;
+       char opt;
+       bool eopt = false;
        int print = cdprint;    /* set -o cdprint to enable */
 
-       while (nextopt("P") != '\0')
-               ;
+       while ((opt = nextopt("Pe")) != '\0')
+               if (opt == 'e')
+                       eopt = true;
 
        /*
         * Try (quite hard) to have 'curdir' defined, nothing has set
@@ -128,19 +133,13 @@
                stunalloc(p);
                if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
                        int dopr = print;
+                       int x;
 
-                       if (!print) {
-                               /*
-                                * XXX - rethink
-                                */
-                               if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
-                                       dopr = strcmp(p + 2, dest);
-                               else
-                                       dopr = strcmp(p, dest);
-                       }
-                       if (docd(p, dopr) >= 0)
-                               return 0;
+                       if (!print)
+                               dopr = strcmp(p, dest);
 
+                       if ((x = docd(p, dopr != 0, eopt)) >= 0)
+                               return x;
                }
        }
        error("can't cd to %s", dest);
@@ -154,8 +153,10 @@
  */
 
 STATIC int
-docd(const char *dest, int print)
+docd(const char *dest, bool print, bool eopt)
 {
+       bool gotpwd;
+
 #if 0          /* no "cd -L" (ever) so all this is just a waste of time ... */
        char *p;
        char *q;
@@ -164,8 +165,6 @@
        int first;
        int badstat;
 
-       CTRACE(DBG_CMDS, ("docd(\"%s\", %d) called\n", dest, print));
-
        /*
         *  Check each component of the path. If we find a symlink or
         *  something we can't stat, clear curdir to force a getcwd()
@@ -199,16 +198,19 @@
        }
 #endif
 
+       CTRACE(DBG_CMDS, ("docd(\"%s\", %s, %s) called\n", dest,
+           print ? "true" : "false", eopt ? "true" : "false"));
+
        INTOFF;
        if (chdir(dest) < 0) {
                INTON;
                return -1;
        }
-       updatepwd(NULL);        /* only do cd -P, no "pretend" -L mode */
+       gotpwd = updatepwd(NULL);   /* only do cd -P, no "pretend" -L mode */
        INTON;
-       if (print && iflag == 1 && curdir)
-               out1fmt("%s\n", curdir);
-       return 0;
+       if (print && (iflag || posix))
+               out1fmt("%s\n", gotpwd ? curdir : dest);
+       return gotpwd || !eopt ? 0 : 1;
 }
 
 
@@ -245,7 +247,7 @@
  * that the current directory has changed.
  */
 
-STATIC void
+STATIC bool
 updatepwd(const char *dir)
 {
        char *new;
@@ -256,7 +258,7 @@
        /*
         * If our argument is NULL, we don't know the current directory
         * any more because we traversed a symbolic link or something
-        * we couldn't stat().
+        * we couldn't stat().   Or we simply don't trust what we had.
         */
        if (dir == NULL || curdir == NULL)  {
                if (prevdir)
@@ -269,10 +271,14 @@
                if (curdir) {
                        setvar("OLDPWD", prevdir, VEXPORT);
                        setvar("PWD", curdir, VEXPORT);
+                       return true;
                } else
                        unsetvar("PWD", 0);
-               return;
+               return false;
        }
+
+       /* XXX none of the following code is ever executed any more */
+
        cdcomppath = stalloc(strlen(dir) + 1);
        scopy(dir, cdcomppath);
        STARTSTACKSTR(new);
@@ -303,6 +309,25 @@
        setvar("OLDPWD", prevdir, VEXPORT);
        setvar("PWD", curdir, VEXPORT);
        INTON;
+       return true;
+}
+
+/*
+ * Test whether we are currently in the direcory given
+ * (provided it is given, and is absolute)
+ * ie: determine if path is fully qualified pathname of "."
+ */
+STATIC bool
+is_curdir(const char *path)
+{
+       struct stat stdot, stpath;
+
+       return  path != NULL &&
+               *path == '/' &&
+               stat(".", &stdot) != -1 &&
+               stat(path, &stpath) != -1 &&
+               stdot.st_dev == stpath.st_dev &&
+               stdot.st_ino == stpath.st_ino;
 }
 
 /*
@@ -329,8 +354,16 @@
        else
                find_curdir(0);
 
+#if 0  /* posix has been changed to forbid this */
        setvar("OLDPWD", prevdir, VEXPORT);
        setvar("PWD", curdir, VEXPORT);
+#endif
+
+       if (!is_curdir(curdir)) {
+               find_curdir(1);
+               if (curdir == NULL)
+                       error("Unable to find current directory");
+       }
        out1str(curdir);
        out1c('\n');
        return 0;
@@ -358,7 +391,6 @@
 getpwd(int noerror)
 {
        char *pwd;
-       struct stat stdot, stpwd;
        static int first = 1;
 
        if (curdir)
@@ -367,10 +399,7 @@
        if (first) {
                first = 0;
                pwd = getenv("PWD");
-               if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
-                   stat(pwd, &stpwd) != -1 &&
-                   stdot.st_dev == stpwd.st_dev &&
-                   stdot.st_ino == stpwd.st_ino) {
+               if (is_curdir(pwd)) {
                        curdir = savestr(pwd);
                        return;
                }
@@ -392,6 +421,13 @@
         * getcwd, but traditionally getcwd is implemented using popen
         * to /bin/pwd. This creates a problem for us, since we cannot
         * keep track of the job if it is being ran behind our backs.
+        * XXX That's not actually the problem, a process created and
+        * XXX destroyed that we know nothing about is harmless.  The
+        * XXX problem is that old popen() implementations would use
+        * XXX wait(2) to await completion of the command, and that might
+        * XXX collect (and ignore) our children.   As long as we are
+        * XXX confident that popen() uses waitpid() (or the equv) there
+        * XXX would not be a problem.   But how do we know that?
         * So we re-implement getcwd(), and we suppress interrupts
         * throughout the process. This is not completely safe, since
         * the user can still break out of it by killing the pwd program.
diff -r c2de8d9762c6 -r d9ce34cacc12 bin/sh/sh.1
--- a/bin/sh/sh.1       Sat Nov 06 13:35:43 2021 +0000
+++ b/bin/sh/sh.1       Sat Nov 06 13:42:18 2021 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sh.1,v 1.223.2.1 2021/11/06 13:35:43 martin Exp $
+.\"    $NetBSD: sh.1,v 1.223.2.2 2021/11/06 13:42:18 martin Exp $
 .\" Copyright (c) 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,7 +31,7 @@
 .\"
 .\"    @(#)sh.1        8.6 (Berkeley) 5/4/95
 .\"
-.Dd October 25, 2021
+.Dd October 31, 2021
 .Dt SH 1
 .\" everything except c o and s (keep them ordered)
 .ds flags abCEeFfhIiLmnpquVvXx
@@ -83,10 +83,7 @@
 .Sh DESCRIPTION
 .Nm
 is the standard command interpreter for the system.
-The current version of
-.Nm
-is in the process of being changed to conform more closely to the
-POSIX 1003.2 and 1003.2a specifications for the shell.
+It is a re-implementation and extension of the Bourne shell.
 This version has many
 features which make it appear similar in some respects to the Korn shell,
 but it is not a Korn shell clone (see
@@ -2399,7 +2396,7 @@
 of utilities, the name for built-ins or the expansion of aliases.
 .El
 .\"
-.It Ic cd Oo Fl P Oc Op Ar directory Op Ar replace
+.It Ic cd Oo Fl Pe Oc Op Ar directory Op Ar replace
 Switch to the specified directory (default
 .Ev $HOME ) .
 If
@@ -2434,14 +2431,44 @@
 .Pp
 The
 .Fl P
-option instructs the shell to update
+option
+(which is the unalterable default in this
+.Nm )
+instructs the shell to
+change to the directory specified (or determined)
+and if successful
+update
+.Ev PWD
+with the new physical directory path.
+That is the path name, not traversing any symbolic links,
+of the altered working directory of the shell.
+.Pp
+The
+.Fl e
+option alters the interpretation of the exit status.
+.Ic cd
+will exit with status 0 if successful.
+If the directory was successfully changed, but
 .Ev PWD
-with the specified physical directory path and change to that directory.
-This is the default.



Home | Main Index | Thread Index | Old Index