Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Jul 2018 21:55:17 +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: r336320 - in head/bin/sh: . tests/builtins
Message-ID:  <201807152155.w6FLtH0w026930@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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" ]



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