Loading...
sys/posix_spawn.c Libc-1725.40.4 Libc-997.90.3
--- Libc/Libc-1725.40.4/sys/posix_spawn.c
+++ Libc/Libc-997.90.3/sys/posix_spawn.c
@@ -73,55 +73,48 @@
 		char *const argv[ __restrict], char *const envp[ __restrict])
 {
 	const char *env_path;
-	char path_buf[PATH_MAX];
-	char *bp, *np, *op, *p;
+	char *bp;
+	char *cur;
+	char *p;
 	char **memp;
-	size_t ln, lp;
+	int lp;
+	int ln;
 	int cnt;
 	int err = 0;
 	int eacces = 0;
 	struct stat sb;
-
-	/* If it's an absolute or relative path name, it's easy. */
-	if (strchr(file, '/')) {
-		bp = (char *)file;
-		env_path = op = NULL;
-		goto retry;
-	}
+	char path_buf[PATH_MAX];
 
 	if ((env_path = getenv("PATH")) == NULL)
 		env_path = _PATH_DEFPATH;
 
+	/* If it's an absolute or relative path name, it's easy. */
+	if (index(file, '/')) {
+		bp = (char *)file;
+		cur = NULL;
+		goto retry;
+	}
 	bp = path_buf;
 
 	/* If it's an empty path name, fail in the usual POSIX way. */
 	if (*file == '\0')
 		return (ENOENT);
 
-	op = env_path;
-	ln = strlen(file);
-	while (op != NULL) {
-		np = strchrnul(op, ':');
-
+	if ((cur = alloca(strlen(env_path) + 1)) == NULL)
+		return ENOMEM;
+	strcpy(cur, env_path);
+	while ((p = strsep(&cur, ":")) != NULL) {
 		/*
 		 * It's a SHELL path -- double, leading and trailing colons
 		 * mean the current directory.
 		 */
-		if (np == op) {
-			/* Empty component. */
+		if (*p == '\0') {
 			p = ".";
 			lp = 1;
 		} else {
-			/* Non-empty component. */
-			p = op;
-			lp = np - op;
+			lp = strlen(p);
 		}
-
-		/* Advance to the next component or terminate after this. */
-		if (*np == '\0')
-			op = NULL;
-		else
-			op = np + 1;
+		ln = strlen(file);
 
 		/*
 		 * If the path is too long complain.  This is a possible
@@ -151,28 +144,14 @@
 		case ENOEXEC:
 			for (cnt = 0; argv[cnt]; ++cnt)
 				;
-
-			/*
-			 * cnt may be 0 above; always allocate at least
-			 * 3 entries so that we can at least fit "sh", bp, and
-			 * the NULL terminator.  We can rely on cnt to take into
-			 * account the NULL terminator in all other scenarios,
-			 * as we drop argv[0].
-			 */
-			memp = alloca(MAX(3, cnt + 2) * sizeof(char *));
+			memp = alloca((cnt + 2) * sizeof(char *));
 			if (memp == NULL) {
 				/* errno = ENOMEM; XXX override ENOEXEC? */
 				goto done;
 			}
-			if (cnt > 0) {
-				memp[0] = argv[0];
-				memp[1] = bp;
-				bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
-			} else {
-				memp[0] = "sh";
-				memp[1] = bp;
-				memp[2] = NULL;
-			}
+			memp[0] = "sh";
+			memp[1] = bp;
+			bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
 			err = posix_spawn(pid, _PATH_BSHELL, file_actions, attrp, memp, envp);
 			goto done;
 		default:
@@ -194,13 +173,7 @@
 	}
 	if (eacces)
 		err = EACCES;
-	/*
-	 * Preserve errno from posix_spawn(3) if it wasn't a PATH search, or
-	 * if it was a PATH search and we bailed out early.  Note that every
-	 * branch in the loop jumps to the `done` label to preserve errno, so
-	 * this is more of a defensive check.
-	 */
-	else if (env_path != NULL && op == NULL)
+	else
 		err = ENOENT;
 done:
 	return (err);