Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Jan 2002 18:16:38 +1100
From:      "Tim J. Robbins" <tim@robbins.dropbear.id.au>
To:        freebsd-standards@FreeBSD.ORG
Subject:   pwd -L option
Message-ID:  <20020130181638.A8510@descent.robbins.dropbear.id.au>

next in thread | raw e-mail | index | archive | help

--7AUc2qLy4jB3hD7Z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

This patch adds the -L option to pwd; most of the source changes were taken
from NetBSD, but adapted so as not to break FreeBSD's realpath utility.
I added an info line in usage() for realpath while I was at it.

It uses the PWD environment variable that sh, ksh93, etc. export and checks
to make sure it "points" to the physical CWD.


Tim

--7AUc2qLy4jB3hD7Z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="pwd.diff"

Index: pwd/pwd.1
===================================================================
RCS file: /home/ncvs/src/bin/pwd/pwd.1,v
retrieving revision 1.15
diff -u -r1.15 pwd.1
--- pwd/pwd.1	2001/08/15 09:09:36	1.15
+++ pwd/pwd.1	2002/01/30 07:18:10
@@ -43,6 +43,7 @@
 .Nd return working directory name
 .Sh SYNOPSIS
 .Nm
+.Op Fl LP
 .Sh DESCRIPTION
 .Nm Pwd
 writes the absolute pathname of the current working directory to
@@ -54,17 +55,28 @@
 Consult the
 .Xr builtin 1
 manual page.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl L
+Display the logical current working directory.
+.It Fl P
+Display the physical current working directory (all symbolic links resolved)
+(default).
 .Sh DIAGNOSTICS
 .Ex -std
+.Sh ENVIRONMENT
+Environment variables used by
+.Nm :
+.Bl -tag -width PWD
+.It Ev PWD
+Logical current working directory.
 .Sh STANDARDS
 The
 .Nm
 utility is expected to be
 .St -p1003.2
 compatible.
-The
-.Fl L
-flag is not supported.
 .Sh SEE ALSO
 .Xr builtin 1 ,
 .Xr cd 1 ,
@@ -80,3 +92,9 @@
 However, 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.
+.Pp
+The
+.Fl L
+option does not work unless the
+.Ev PWD
+variable is exported by the shell.
Index: pwd/pwd.c
===================================================================
RCS file: /home/ncvs/src/bin/pwd/pwd.c,v
retrieving revision 1.13
diff -u -r1.13 pwd.c
--- pwd/pwd.c	2001/05/30 03:28:29	1.13
+++ pwd/pwd.c	2002/01/30 07:18:11
@@ -45,13 +45,18 @@
   "$FreeBSD: src/bin/pwd/pwd.c,v 1.13 2001/05/30 03:28:29 imp Exp $";
 #endif /* not lint */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include <err.h>
+#include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/param.h>
 
+static char *getcwd_logical __P((char *, size_t));
 int main __P((int, char *[]));
 void usage __P((void));
 
@@ -63,16 +68,15 @@
 	int ch;
 	char *p;
 	char buf[PATH_MAX];
+	int lflag = 0;
 
-	/*
-	 * 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.
-	 */
-	while ((ch = getopt(argc, argv, "P")) != -1)
+	while ((ch = getopt(argc, argv, "LP")) != -1)
 		switch (ch) {
+		case 'L':
+			lflag = 1;
+			break;
 		case 'P':
+			lflag = 0;
 			break;
 		case '?':
 		default:
@@ -87,7 +91,8 @@
 			err(1, "%s", argv[0]);
 		(void)printf("%s\n", p);
 	} else  if (argc == 0) {
-		p = getcwd(NULL, (size_t)0);
+		p = lflag ? getcwd_logical(NULL, (size_t)0) :
+			getcwd(NULL, (size_t)0);
 		if (p == NULL)
 			err(1, ".");
 		(void)printf("%s\n", p);
@@ -98,10 +103,51 @@
 	exit(0);
 }
 
+static char *
+getcwd_logical(char *pt, size_t size)
+{
+	char *pwd;
+	size_t pwdlen;
+	dev_t dev;
+	ino_t ino;
+	struct stat s;
+
+	/* Check $PWD -- if it's right, it's fast. */
+	if ((pwd = getenv("PWD")) != NULL && pwd[0] == '/') {
+		if (stat(pwd, &s) != -1) {
+			dev = s.st_dev;
+			ino = s.st_ino;
+			if (stat(".", &s) != -1 && dev == s.st_dev &&
+			    ino == s.st_ino) {
+				pwdlen = strlen(pwd);
+				if (pt) {
+					if (!size) {
+						errno = EINVAL;
+						return (NULL);
+					}
+					if (pwdlen + 1 > size) {
+						errno = ERANGE;
+						return (NULL);
+					}
+				} else if ((pt = malloc(pwdlen + 1)) == NULL)
+					return (NULL);
+				(void)memmove(pt, pwd, pwdlen);
+				pt[pwdlen] = '\0';
+				return (pt);
+			}
+		}
+	} else
+		errno = ENOENT;
+
+	return (NULL);
+}
+
+
 void
 usage()
 {
 
-	(void)fprintf(stderr, "usage: pwd\n");
+	(void)fprintf(stderr, "usage: pwd [-LP]\n");
+	(void)fprintf(stderr, "       realpath [file ...]\n");
 	exit(1);
 }

--7AUc2qLy4jB3hD7Z--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-standards" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020130181638.A8510>