summaryrefslogtreecommitdiff
path: root/bin/pwd
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2014-05-28 06:55:59 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2014-05-28 06:55:59 +0000
commit0ee5625ee86a297aa31a197b277373f3a1ef3119 (patch)
tree2b35b2e2998032debd23a8bf24b0698b1d5f9913 /bin/pwd
parentcaf0d951373c4d59747d489fef643c9a1100c456 (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.158
-rw-r--r--bin/pwd/pwd.c84
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);
}