Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 May 2011 22:55:19 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222154 - in head: bin/sh tools/regression/bin/sh/builtins
Message-ID:  <201105202255.p4KMtJGY004285@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Fri May 20 22:55:18 2011
New Revision: 222154
URL: http://svn.freebsd.org/changeset/base/222154

Log:
  sh: Implement the cd -e flag proposed for the next POSIX issue.
  
  This reflects failure to determine the pathname of the new directory in the
  exit status (1). Normally, cd returns successfully if it did chdir() and the
  call was successful.
  
  In POSIX, -e only has meaning with -P; because our -L is not entirely
  compliant and may fall back to -P mode, -e has some effect with -L as well.

Added:
  head/tools/regression/bin/sh/builtins/cd3.0   (contents, props changed)
  head/tools/regression/bin/sh/builtins/cd4.0   (contents, props changed)
Modified:
  head/bin/sh/cd.c
  head/bin/sh/sh.1

Modified: head/bin/sh/cd.c
==============================================================================
--- head/bin/sh/cd.c	Fri May 20 22:38:02 2011	(r222153)
+++ head/bin/sh/cd.c	Fri May 20 22:55:18 2011	(r222154)
@@ -84,12 +84,16 @@ cdcmd(int argc, char **argv)
 	const char *path;
 	char *p;
 	struct stat statb;
-	int ch, phys, print = 0;
+	int ch, phys, print = 0, getcwderr = 0;
+	int rc;
 
 	optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
 	phys = Pflag;
-	while ((ch = getopt(argc, argv, "LP")) != -1) {
+	while ((ch = getopt(argc, argv, "eLP")) != -1) {
 		switch (ch) {
+		case 'e':
+			getcwderr = 1;
+			break;
 		case 'L':
 			phys = 0;
 			break;
@@ -131,8 +135,9 @@ cdcmd(int argc, char **argv)
 				else
 					print = strcmp(p, dest);
 			}
-			if (docd(p, print, phys) >= 0)
-				return 0;
+			rc = docd(p, print, phys);
+			if (rc >= 0)
+				return getcwderr ? rc : 0;
 		}
 	}
 	error("can't cd to %s", dest);
@@ -148,17 +153,18 @@ cdcmd(int argc, char **argv)
 static int
 docd(char *dest, int print, int phys)
 {
+	int rc;
 
 	TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys));
 
 	/* If logical cd fails, fall back to physical. */
-	if ((phys || cdlogical(dest) < 0) && cdphysical(dest) < 0)
+	if ((phys || (rc = cdlogical(dest)) < 0) && (rc = cdphysical(dest)) < 0)
 		return (-1);
 
 	if (print && iflag && curdir)
 		out1fmt("%s\n", curdir);
 
-	return 0;
+	return (rc);
 }
 
 static int
@@ -216,6 +222,7 @@ static int
 cdphysical(char *dest)
 {
 	char *p;
+	int rc = 0;
 
 	INTOFF;
 	if (chdir(dest) < 0) {
@@ -223,11 +230,13 @@ cdphysical(char *dest)
 		return (-1);
 	}
 	p = findcwd(NULL);
-	if (p == NULL)
+	if (p == NULL) {
 		warning("warning: failed to get name of current directory");
+		rc = 1;
+	}
 	updatepwd(p);
 	INTON;
-	return (0);
+	return (rc);
 }
 
 /*

Modified: head/bin/sh/sh.1
==============================================================================
--- head/bin/sh/sh.1	Fri May 20 22:38:02 2011	(r222153)
+++ head/bin/sh/sh.1	Fri May 20 22:55:18 2011	(r222154)
@@ -32,7 +32,7 @@
 .\"	from: @(#)sh.1	8.6 (Berkeley) 5/4/95
 .\" $FreeBSD$
 .\"
-.Dd May 8, 2011
+.Dd May 20, 2011
 .Dt SH 1
 .Os
 .Sh NAME
@@ -1729,7 +1729,7 @@ Execute the specified built-in command,
 .Ar cmd .
 This is useful when the user wishes to override a shell function
 with the same name as a built-in command.
-.It Ic cd Oo Fl L | P Oc Op Ar directory
+.It Ic cd Oo Fl L | P Oc Oo Fl e Oc Op Ar directory
 Switch to the specified
 .Ar directory ,
 or to the directory specified in the
@@ -1778,6 +1778,15 @@ option is specified,
 .Pa ..
 is handled logically.
 This is the default.
+.Pp
+The
+.Fl e
+option causes
+.Ic cd
+to return exit status 1 if the full pathname of the new directory
+cannot be determined reliably or at all.
+Normally this is not considered an error,
+although a warning is printed.
 .It Ic chdir
 A synonym for the
 .Ic cd

Added: head/tools/regression/bin/sh/builtins/cd3.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/builtins/cd3.0	Fri May 20 22:55:18 2011	(r222154)
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+# If fully successful, cd -Pe must be like cd -P.
+
+set -e
+
+cd "${TMPDIR:-/tmp}"
+cd -Pe /
+[ "$PWD" = / ]
+[ "$(pwd)" = / ]
+cd "${TMPDIR:-/tmp}"
+cd -eP /
+[ "$PWD" = / ]
+[ "$(pwd)" = / ]
+
+set +e
+
+# If cd -Pe cannot chdir, the exit status must be greater than 1.
+
+v=$( (cd -Pe /var/empty/nonexistent) 2>&1 >/dev/null)
+[ $? -gt 1 ] && [ -n "$v" ]

Added: head/tools/regression/bin/sh/builtins/cd4.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/builtins/cd4.0	Fri May 20 22:55:18 2011	(r222154)
@@ -0,0 +1,38 @@
+# $FreeBSD$
+
+# This test assumes that whatever mechanism cd -P uses to determine the
+# pathname to the current directory if it is longer than PATH_MAX requires
+# read permission on all parent directories. It also works if this
+# requirement always applies.
+
+set -e
+L=$(getconf PATH_MAX / 2>/dev/null) || L=4096
+[ "$L" -lt 100000 ] 2>/dev/null || L=4096
+L=$((L+100))
+T=$(mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX)
+trap 'chmod u+r ${T}; rm -rf ${T}' 0
+cd -Pe $T
+D=$(pwd)
+chmod u-r "$D"
+if [ -r "$D" ]; then
+	# Running as root, cannot test.
+	exit 0
+fi
+set +e
+while [ ${#D} -lt $L ]; do
+	mkdir veryverylongdirectoryname || exit
+	cd -Pe veryverylongdirectoryname 2>/dev/null
+	r=$?
+	[ $r -gt 1 ] && exit $r
+	if [ $r -eq 1 ]; then
+		# Verify that the directory was changed correctly.
+		cd -Pe .. || exit
+		[ "$(pwd)" = "$D" ] || exit
+		# Verify that omitting -e results in success.
+		cd -P veryverylongdirectoryname 2>/dev/null || exit
+		exit 0
+	fi
+	D=$D/veryverylongdirectoryname
+done
+echo "cd -Pe never returned 1"
+exit 0



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