The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2df923c5d2d02350abc29f61b603c5b9615b225c

commit 2df923c5d2d02350abc29f61b603c5b9615b225c
Author:     Dag-Erling Smørgrav <[email protected]>
AuthorDate: 2026-02-10 14:29:04 +0000
Commit:     Dag-Erling Smørgrav <[email protected]>
CommitDate: 2026-02-10 14:29:04 +0000

    pwd: Clean up and adopt POSIX semantics
    
    According to POSIX, the default should be -L.  Based on code history,
    whoever first wrote BSD pwd(1) could not figure out how to implement
    -L and therefore made -P the default (and only) option. Support for -L
    was later added, but the default was never changed.
    
    Clean up the code, make -L the default, and rewrite getcwd_logical() to
    reject paths that contain dot or dot-dot, as required by POSIX.
    
    MFC after:      1 week
    Reviewed by:    olce
    Differential Revision:  https://reviews.freebsd.org/D55146
---
 bin/pwd/pwd.1 |  4 +--
 bin/pwd/pwd.c | 99 +++++++++++++++++++++++++++++++----------------------------
 2 files changed, 54 insertions(+), 49 deletions(-)

diff --git a/bin/pwd/pwd.1 b/bin/pwd/pwd.1
index ce81e443d98e..8b03d060bc8e 100644
--- a/bin/pwd/pwd.1
+++ b/bin/pwd/pwd.1
@@ -29,7 +29,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 22, 2023
+.Dd Februrary 6, 2026
 .Dt PWD 1
 .Os
 .Sh NAME
@@ -60,7 +60,7 @@ Display the physical current working directory (all symbolic 
links resolved).
 .El
 .Pp
 If no options are specified, the
-.Fl P
+.Fl L
 option is assumed.
 .Sh ENVIRONMENT
 Environment variables used by
diff --git a/bin/pwd/pwd.c b/bin/pwd/pwd.c
index a49c638b1dee..f626a2236c02 100644
--- a/bin/pwd/pwd.c
+++ b/bin/pwd/pwd.c
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 1991, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2026 Dag-Erling Smørgrav
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,40 +32,74 @@
 
 #include <sys/param.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 
 #include <err.h>
-#include <errno.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
-static char *getcwd_logical(void);
-void usage(void);
+static char *
+getcwd_logical(void)
+{
+       struct stat log, phy;
+       char *pwd, *p, *q;
+
+       /* $PWD is set and absolute */
+       if ((pwd = getenv("PWD")) == NULL || *pwd != '/')
+               return (NULL);
+       /* $PWD does not contain /./ or /../ */
+       for (p = pwd; *p; p = q) {
+               for (q = ++p; *q && *q != '/'; q++)
+                       /* nothing */;
+               if ((*p == '.' && q == ++p) ||
+                   (*p == '.' && q == ++p))
+                       return (NULL);
+       }
+       /* $PWD refers to the current directory */
+       if (stat(pwd, &log) != 0 || stat(".", &phy) != 0 ||
+           log.st_dev != phy.st_dev || log.st_ino != phy.st_ino)
+               return (NULL);
+       return (pwd);
+}
+
+static char *
+getcwd_physical(void)
+{
+       static char pwd[MAXPATHLEN];
+
+       return (getcwd(pwd, sizeof(pwd)));
+}
+
+static void
+usage(void)
+{
+       (void)fprintf(stderr, "usage: pwd [-L | -P]\n");
+       exit(1);
+}
 
 int
 main(int argc, char *argv[])
 {
-       int physical;
-       int ch;
-       char *p;
+       char *pwd;
+       int opt;
+       bool logical;
 
-       physical = 1;
-       while ((ch = getopt(argc, argv, "LP")) != -1)
-               switch (ch) {
+       logical = true;
+       while ((opt = getopt(argc, argv, "LP")) != -1) {
+               switch (opt) {
                case 'L':
-                       physical = 0;
+                       logical = true;
                        break;
                case 'P':
-                       physical = 1;
+                       logical = false;
                        break;
-               case '?':
                default:
                        usage();
                }
+       }
        argc -= optind;
        argv += optind;
-
        if (argc != 0)
                usage();
 
@@ -72,40 +107,10 @@ main(int argc, char *argv[])
         * If we're trying to find the logical current directory and that
         * fails, behave as if -P was specified.
         */
-       if ((!physical && (p = getcwd_logical()) != NULL) ||
-           (p = getcwd(NULL, 0)) != NULL)
-               printf("%s\n", p);
+       if ((logical && (pwd = getcwd_logical()) != NULL) ||
+           (pwd = getcwd_physical()) != NULL)
+               printf("%s\n", pwd);
        else
                err(1, ".");
-
        exit(0);
 }
-
-void __dead2
-usage(void)
-{
-
-       (void)fprintf(stderr, "usage: pwd [-L | -P]\n");
-       exit(1);
-}
-
-static char *
-getcwd_logical(void)
-{
-       struct stat lg, phy;
-       char *pwd;
-
-       /*
-        * Check that $PWD is an absolute logical pathname referring to
-        * the current working directory.
-        */
-       if ((pwd = getenv("PWD")) != NULL && *pwd == '/') {
-               if (stat(pwd, &lg) == -1 || stat(".", &phy) == -1)
-                       return (NULL);
-               if (lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino)
-                       return (pwd);
-       }
-
-       errno = ENOENT;
-       return (NULL);
-}

Reply via email to