From 90c6dfa16cff8a70f27a867c3d97f6968384f755 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 30 Dec 2012 04:43:11 -0600 Subject: Getting the pwd -L behavior right is fiddly. --- toys/posix/pwd.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/toys/posix/pwd.c b/toys/posix/pwd.c index 5c543e87..32035924 100644 --- a/toys/posix/pwd.c +++ b/toys/posix/pwd.c @@ -2,9 +2,9 @@ * * Copyright 2006 Rob Landley * - * See http://opengroup.org/onlinepubs/9699919799/utilities/echo.html + * See http://opengroup.org/onlinepubs/9699919799/utilities/pwd.html -USE_PWD(NEWTOY(pwd, ">0LP[!LP]", TOYFLAG_BIN)) +USE_PWD(NEWTOY(pwd, ">0LP[-LP]", TOYFLAG_BIN)) config PWD bool "pwd" @@ -12,12 +12,10 @@ config PWD help usage: pwd [-L|-P] - The print working directory command prints the current directory. + Print working (current) directory. - -P Avoid all symlinks - -L Use the value of the environment variable "PWD" if valid - - The option "-L" is implied by default. + -L Use shell's path from $PWD (when applicable) + -P Print cannonical absolute path */ #define FOR_pwd @@ -25,12 +23,32 @@ config PWD void pwd_main(void) { - char *pwd = xgetcwd(), *env_pwd; - struct stat st[2]; + char *s, *pwd = getcwd(0, 0), *PWD; + + // Only use $PWD if it's an absolute path alias for cwd with no "." or ".." + if (!(toys.optflags & FLAG_P) && (s = PWD = getenv("PWD"))) { + struct stat st1, st2; + + while (*s == '/') { + if (*(++s) == '.') { + if (s[1] == '/' || !s[1]) break; + if (s[1] == '.' && (s[2] == '/' || !s[2])) break; + } + while (*s && *s != '/') s++; + } + if (!*s && s != PWD) s = PWD; + else s = NULL; + + // If current directory exists, make sure it matches. + if (s && pwd) + if (stat(pwd, &st1) || stat(PWD, &st2) || st1.st_ino != st2.st_ino || + st1.st_dev != st2.st_dev) s = NULL; + } else s = NULL; + + // If -L didn't give us a valid path, use cwd. + if (!s && !(s = pwd)) perror_exit("xgetcwd"); + + xprintf("%s\n", s); - if (!(toys.optflags & FLAG_P) && (env_pwd = getenv("PWD")) && - !stat(pwd, &st[0]) && !stat(env_pwd, &st[1]) && - (st[0].st_ino == st[1].st_ino)) xprintf("%s\n", env_pwd); - else xprintf("%s\n", pwd); if (CFG_TOYBOX_FREE) free(pwd); } -- cgit v1.2.3