From owner-svn-src-all@FreeBSD.ORG Fri May 20 22:55:19 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7AAAD106566C; Fri, 20 May 2011 22:55:19 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 326768FC13; Fri, 20 May 2011 22:55:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p4KMtJrq004290; Fri, 20 May 2011 22:55:19 GMT (envelope-from jilles@svn.freebsd.org) Received: (from jilles@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p4KMtJGY004285; Fri, 20 May 2011 22:55:19 GMT (envelope-from jilles@svn.freebsd.org) Message-Id: <201105202255.p4KMtJGY004285@svn.freebsd.org> From: Jilles Tjoelker Date: Fri, 20 May 2011 22:55:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r222154 - in head: bin/sh tools/regression/bin/sh/builtins X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 20 May 2011 22:55:19 -0000 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