From owner-svn-src-all@freebsd.org Sun Jul 15 21:55:19 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7EB95102BB84; Sun, 15 Jul 2018 21:55:19 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 317DC724F1; Sun, 15 Jul 2018 21:55:19 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 07CAF13B4C; Sun, 15 Jul 2018 21:55:19 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w6FLtIQp026936; Sun, 15 Jul 2018 21:55:18 GMT (envelope-from jilles@FreeBSD.org) Received: (from jilles@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w6FLtH0w026930; Sun, 15 Jul 2018 21:55:17 GMT (envelope-from jilles@FreeBSD.org) Message-Id: <201807152155.w6FLtH0w026930@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jilles set sender to jilles@FreeBSD.org using -f From: Jilles Tjoelker Date: Sun, 15 Jul 2018 21:55:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r336320 - in head/bin/sh: . tests/builtins X-SVN-Group: head X-SVN-Commit-Author: jilles X-SVN-Commit-Paths: in head/bin/sh: . tests/builtins X-SVN-Commit-Revision: 336320 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.27 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: Sun, 15 Jul 2018 21:55:19 -0000 Author: jilles Date: Sun Jul 15 21:55:17 2018 New Revision: 336320 URL: https://svnweb.freebsd.org/changeset/base/336320 Log: sh: Don't treat % specially in CDPATH Added: head/bin/sh/tests/builtins/cd11.0 (contents, props changed) Modified: head/bin/sh/cd.c head/bin/sh/exec.c head/bin/sh/exec.h head/bin/sh/main.c head/bin/sh/tests/builtins/Makefile Modified: head/bin/sh/cd.c ============================================================================== --- head/bin/sh/cd.c Sun Jul 15 21:10:19 2018 (r336319) +++ head/bin/sh/cd.c Sun Jul 15 21:55:17 2018 (r336320) @@ -120,7 +120,7 @@ cdcmd(int argc __unused, char **argv __unused) (dest[0] == '.' && dest[1] == '.' && (dest[2] == '/' || dest[2] == '\0')) || (path = bltinlookup("CDPATH", 1)) == NULL) path = ""; - while ((p = padvance(&path, dest)) != NULL) { + while ((p = padvance(&path, NULL, dest)) != NULL) { if (stat(p, &statb) < 0) { if (errno != ENOENT) errno1 = errno; Modified: head/bin/sh/exec.c ============================================================================== --- head/bin/sh/exec.c Sun Jul 15 21:10:19 2018 (r336319) +++ head/bin/sh/exec.c Sun Jul 15 21:55:17 2018 (r336320) @@ -113,6 +113,7 @@ void shellexec(char **argv, char **envp, const char *path, int idx) { char *cmdname; + const char *opt; int e; if (strchr(argv[0], '/') != NULL) { @@ -120,8 +121,8 @@ shellexec(char **argv, char **envp, const char *path, e = errno; } else { e = ENOENT; - while ((cmdname = padvance(&path, argv[0])) != NULL) { - if (--idx < 0 && pathopt == NULL) { + while ((cmdname = padvance(&path, &opt, argv[0])) != NULL) { + if (--idx < 0 && opt == NULL) { tryexec(cmdname, argv, envp); if (errno != ENOENT && errno != ENOTDIR) e = errno; @@ -174,16 +175,14 @@ tryexec(char *cmd, char **argv, char **envp) * Do a path search. The variable path (passed by reference) should be * set to the start of the path before the first call; padvance will update * this value as it proceeds. Successive calls to padvance will return - * the possible path expansions in sequence. If an option (indicated by - * a percent sign) appears in the path entry then the global variable - * pathopt will be set to point to it; otherwise pathopt will be set to - * NULL. + * the possible path expansions in sequence. If popt is not NULL, options + * are processed: if an option (indicated by a percent sign) appears in + * the path entry then *popt will be set to point to it; else *popt will be + * set to NULL. If popt is NULL, percent signs are not special. */ -const char *pathopt; - char * -padvance(const char **path, const char *name) +padvance(const char **path, const char **popt, const char *name) { const char *p, *start; char *q; @@ -192,8 +191,12 @@ padvance(const char **path, const char *name) if (*path == NULL) return NULL; start = *path; - for (p = start; *p && *p != ':' && *p != '%'; p++) - ; /* nothing */ + if (popt != NULL) + for (p = start; *p && *p != ':' && *p != '%'; p++) + ; /* nothing */ + else + for (p = start; *p && *p != ':'; p++) + ; /* nothing */ namelen = strlen(name); len = p - start + namelen + 2; /* "2" is for '/' and '\0' */ STARTSTACKSTR(q); @@ -204,10 +207,12 @@ padvance(const char **path, const char *name) *q++ = '/'; } memcpy(q, name, namelen + 1); - pathopt = NULL; - if (*p == '%') { - pathopt = ++p; - while (*p && *p != ':') p++; + if (popt != NULL) { + if (*p == '%') { + *popt = ++p; + while (*p && *p != ':') p++; + } else + *popt = NULL; } if (*p == ':') *path = p + 1; @@ -277,14 +282,14 @@ static void printentry(struct tblentry *cmdp, int verbose) { int idx; - const char *path; + const char *path, *opt; char *name; if (cmdp->cmdtype == CMDNORMAL) { idx = cmdp->param.index; path = pathval(); do { - name = padvance(&path, cmdp->cmdname); + name = padvance(&path, &opt, cmdp->cmdname); stunalloc(name); } while (--idx >= 0); out1str(name); @@ -321,6 +326,7 @@ find_command(const char *name, struct cmdentry *entry, { struct tblentry *cmdp, loc_cmd; int idx; + const char *opt; char *fullname; struct stat statb; int e; @@ -363,10 +369,11 @@ find_command(const char *name, struct cmdentry *entry, e = ENOENT; idx = -1; - for (;(fullname = padvance(&path, name)) != NULL; stunalloc(fullname)) { + for (;(fullname = padvance(&path, &opt, name)) != NULL; + stunalloc(fullname)) { idx++; - if (pathopt) { - if (strncmp(pathopt, "func", 4) == 0) { + if (opt) { + if (strncmp(opt, "func", 4) == 0) { /* handled below */ } else { continue; /* ignore unimplemented options */ @@ -382,7 +389,7 @@ find_command(const char *name, struct cmdentry *entry, e = EACCES; /* if we fail, this will be the error */ if (!S_ISREG(statb.st_mode)) continue; - if (pathopt) { /* this is a %func directory */ + if (opt) { /* this is a %func directory */ readcmdfile(fullname); if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION) error("%s not defined in %s", name, fullname); @@ -703,10 +710,11 @@ typecmd_impl(int argc, char **argv, int cmd, const cha case CMDNORMAL: { if (strchr(argv[i], '/') == NULL) { const char *path2 = path; + const char *opt2; char *name; int j = entry.u.index; do { - name = padvance(&path2, argv[i]); + name = padvance(&path2, &opt2, argv[i]); stunalloc(name); } while (--j >= 0); if (cmd == TYPECMD_SMALLV) Modified: head/bin/sh/exec.h ============================================================================== --- head/bin/sh/exec.h Sun Jul 15 21:10:19 2018 (r336319) +++ head/bin/sh/exec.h Sun Jul 15 21:55:17 2018 (r336320) @@ -61,11 +61,10 @@ struct cmdentry { #define DO_ERR 0x01 /* prints errors */ #define DO_NOFUNC 0x02 /* don't return shell functions, for command */ -extern const char *pathopt; /* set by padvance */ extern int exerrno; /* last exec error */ void shellexec(char **, char **, const char *, int) __dead2; -char *padvance(const char **, const char *); +char *padvance(const char **, const char **, const char *); void find_command(const char *, struct cmdentry *, int, const char *); int find_builtin(const char *, int *); void hashcd(void); Modified: head/bin/sh/main.c ============================================================================== --- head/bin/sh/main.c Sun Jul 15 21:10:19 2018 (r336319) +++ head/bin/sh/main.c Sun Jul 15 21:55:17 2018 (r336320) @@ -294,6 +294,7 @@ static char * find_dot_file(char *basename) { char *fullname; + const char *opt; const char *path = pathval(); struct stat statb; @@ -301,7 +302,7 @@ find_dot_file(char *basename) if( strchr(basename, '/')) return basename; - while ((fullname = padvance(&path, basename)) != NULL) { + while ((fullname = padvance(&path, &opt, basename)) != NULL) { if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { /* * Don't bother freeing here, since it will Modified: head/bin/sh/tests/builtins/Makefile ============================================================================== --- head/bin/sh/tests/builtins/Makefile Sun Jul 15 21:10:19 2018 (r336319) +++ head/bin/sh/tests/builtins/Makefile Sun Jul 15 21:55:17 2018 (r336320) @@ -53,6 +53,7 @@ ${PACKAGE}FILES+= cd7.0 ${PACKAGE}FILES+= cd8.0 ${PACKAGE}FILES+= cd9.0 cd9.0.stdout ${PACKAGE}FILES+= cd10.0 +${PACKAGE}FILES+= cd11.0 ${PACKAGE}FILES+= command1.0 ${PACKAGE}FILES+= command2.0 ${PACKAGE}FILES+= command3.0 Added: head/bin/sh/tests/builtins/cd11.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/builtins/cd11.0 Sun Jul 15 21:55:17 2018 (r336320) @@ -0,0 +1,24 @@ +# $FreeBSD$ + +set -e +T=$(mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXX") +trap 'rm -rf "$T"' 0 + +mkdir "$T/%?^&*" +cd -P "$T/%?^&*" +D=$(pwd) + +mkdir a a/1 b b/1 b/2 + +CDPATH=$D/a: +# Basic test. +cd 1 >/dev/null +[ "$(pwd)" = "$D/a/1" ] +# Test that the current directory is not checked before CDPATH. +cd "$D/b" +cd 1 >/dev/null +[ "$(pwd)" = "$D/a/1" ] +# Test not using a CDPATH entry. +cd "$D/b" +cd 2 +[ "$(pwd)" = "$D/b/2" ]