diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2014-05-28 06:55:59 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2014-05-28 06:55:59 +0000 |
commit | 0ee5625ee86a297aa31a197b277373f3a1ef3119 (patch) | |
tree | 2b35b2e2998032debd23a8bf24b0698b1d5f9913 /bin/pwd | |
parent | caf0d951373c4d59747d489fef643c9a1100c456 (diff) |
In his continuing quest to improve our documentation, jmc@ noticed that
we didn't support the -L option required by POSIX, and didn't
document the -P option that we did support. Fix that with code and
doc bits from NetBSD, but correcting a minor noncompliance in the
-L support and applying the jmc@ and sobrado@ magic to the manpage.
This commit does not change the default behavior.
ok jmc@ millert@ sobrado@
Diffstat (limited to 'bin/pwd')
-rw-r--r-- | bin/pwd/pwd.1 | 58 | ||||
-rw-r--r-- | bin/pwd/pwd.c | 84 |
2 files changed, 107 insertions, 35 deletions
diff --git a/bin/pwd/pwd.1 b/bin/pwd/pwd.1 index 4d84c32df53..c9dda30bc88 100644 --- a/bin/pwd/pwd.1 +++ b/bin/pwd/pwd.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pwd.1,v 1.19 2010/09/03 09:53:20 jmc Exp $ +.\" $OpenBSD: pwd.1,v 1.20 2014/05/28 06:55:58 guenther Exp $ .\" $NetBSD: pwd.1,v 1.10 1995/09/07 06:47:30 jtc Exp $ .\" .\" Copyright (c) 1990, 1993 @@ -33,7 +33,7 @@ .\" .\" @(#)pwd.1 8.2 (Berkeley) 4/28/95 .\" -.Dd $Mdocdate: September 3 2010 $ +.Dd $Mdocdate: May 28 2014 $ .Dt PWD 1 .Os .Sh NAME @@ -41,14 +41,47 @@ .Nd return working directory name .Sh SYNOPSIS .Nm pwd +.Op Fl LP .Sh DESCRIPTION The .Nm utility prints the absolute pathname of the current working directory to the standard output. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl L +If the +.Ev PWD +environment variable is an absolute pathname that references the +current directory and doesn't contain path components of "." or "..", +then +.Ev PWD +is printed as the name of the current directory. +Otherwise, act as if the +.Fl P +option was given. +.It Fl P +Print the physical path to the current working directory, with symbolic +links in the path resolved. +.El +.Pp +The +.Fl L +and +.Fl P +options override each other and the command's actions are determined +by the last one specified. +The default if no options are given is +.Fl P . +.Pp For an explanation of the directory hierarchy, see .Xr hier 7 . +.Sh ENVIRONMENT +.Bl -tag -width PWD +.It Ev PWD +The presumptive logical path to the current working directory. .Sh EXIT STATUS .Ex -std pwd .Sh SEE ALSO @@ -61,16 +94,17 @@ The utility is compliant with the .St -p1003.1-2008 specification. -.Pp +.Sh HISTORY +An +.Nm +utility appeared in +.At v5 . +Support for the +.Fl L +option was added in +.Ox 5.6 . +.Sh CAVEATS .Nm also exists as a built-in to .Xr ksh 1 , -though with a different syntax. -.Sh BUGS -In -.Xr csh 1 , -the command -.Ic dirs -is always faster (although it can give a different answer in the rare case -that the current directory or a containing directory was moved after -the shell descended into it). +which may have a different default behavior. diff --git a/bin/pwd/pwd.c b/bin/pwd/pwd.c index fd6078408a1..0009669645b 100644 --- a/bin/pwd/pwd.c +++ b/bin/pwd/pwd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pwd.c,v 1.11 2009/10/27 23:59:22 deraadt Exp $ */ -/* $NetBSD: pwd.c,v 1.7 1995/03/21 09:08:18 cgd Exp $ */ +/* $OpenBSD: pwd.c,v 1.12 2014/05/28 06:55:58 guenther Exp $ */ +/* $NetBSD: pwd.c,v 1.22 2011/08/29 14:51:19 joerg Exp $ */ /* * Copyright (c) 1991, 1993, 1994 @@ -30,50 +30,88 @@ * SUCH DAMAGE. */ +#include <sys/stat.h> + #include <err.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> -extern char *__progname; - -void usage(void); +extern char *__progname; +static char *getcwd_logical(void); +__dead static void usage(void); int main(int argc, char *argv[]) { - int ch; - char *p; - - /* - * Flags for pwd are a bit strange. The POSIX 1003.2B/D9 document - * has an optional -P flag for physical, which is what this program - * will produce by default. The logical flag, -L, should fail, as - * there's no way to display a logical path after forking. We don't - * document either flag, only adding -P for future portability. - */ - while ((ch = getopt(argc, argv, "P")) != -1) + int ch, lFlag = 0; + const char *p; + + while ((ch = getopt(argc, argv, "LP")) != -1) { switch (ch) { + case 'L': + lFlag = 1; + break; case 'P': + lFlag = 0; break; default: usage(); } + } argc -= optind; argv += optind; if (argc != 0) usage(); - if ((p = getcwd(NULL, (size_t)0)) == NULL) - err(1, "getcwd"); - (void)printf("%s\n", p); - exit(0); + if (lFlag) + p = getcwd_logical(); + else + p = NULL; + if (p == NULL) + p = getcwd(NULL, 0); + + if (p == NULL) + err(EXIT_FAILURE, NULL); + + puts(p); + + exit(EXIT_SUCCESS); +} + +static char * +getcwd_logical(void) +{ + char *pwd, *p; + struct stat s_pwd, s_dot; + + /* Check $PWD -- if it's right, it's fast. */ + pwd = getenv("PWD"); + if (pwd == NULL) + return NULL; + if (pwd[0] != '/') + return NULL; + + /* check for . or .. components, including trailing ones */ + for (p = pwd; *p != '\0'; p++) + if (p[0] == '/' && p[1] == '.') { + if (p[2] == '.') + p++; + if (p[2] == '\0' || p[2] == '/') + return NULL; + } + + if (stat(pwd, &s_pwd) == -1 || stat(".", &s_dot) == -1) + return NULL; + if (s_pwd.st_dev != s_dot.st_dev || s_pwd.st_ino != s_dot.st_ino) + return NULL; + return pwd; } -void +static void usage(void) { - (void)fprintf(stderr, "usage: %s\n", __progname); - exit(1); + fprintf(stderr, "usage: %s [-LP]\n", __progname); + exit(EXIT_FAILURE); } |