Loading...
tests/execvp.c Libc-1725.40.4 /dev/null
--- Libc/Libc-1725.40.4/tests/execvp.c
+++ /dev/null
@@ -1,646 +0,0 @@
-#include <sys/wait.h>
-#include <assert.h>
-#include <copyfile.h>
-#include <paths.h>
-#include <unistd.h>
-
-#include <darwintest.h>
-#include <darwintest_utils.h>
-#include <darwintest_posix.h>
-
-T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
-
-/*
- * Create copy of a program in the given directory.  Returns an open
- * descriptor to the newly created program.  Any error other than a
- * failure to create the file results in SIGABRT.
- */
-static int
-_copy_program_impl(const char *template, int dd, const char *name, mode_t perm)
-{
-	int pd, td;
-	int serrno;
-
-	(void)unlinkat(dd, name, 0);
-	pd = openat(dd, name, O_RDWR|O_CREAT|O_TRUNC, 0600);
-	if (pd < 0) {
-		serrno = errno;
-		(void)close(dd);
-		errno = serrno;
-		return (pd);
-	}
-	assert(fchmod(pd, perm) == 0);
-	assert((td = open(template, O_RDONLY)) >= 0);
-	assert(fcopyfile(td, pd, NULL, COPYFILE_DATA) == 0);
-	assert(close(td) == 0);
-	return (pd);
-}
-static int
-_copy_program(const char *template, const char *dir, const char *name, mode_t perm)
-{
-	int dd, pd, serrno;
-
-	assert((dd = open(dir, O_RDONLY)) >= 0);
-	pd = _copy_program_impl(template, dd, name, perm);
-	serrno = errno;
-	assert(close(dd) == 0);
-	errno = serrno;
-
-	return (pd);
-}
-
-/*
- * Fork a child which invokes execvp() with the arguments provided by the
- * caller.  The provided search path, if not NULL, is used instead of
- * $PATH.  If the call fails, the child reports the outcome by writing the
- * return value and the value of errno to a pipe to the parent.  The
- * parent sets errno to the reported value and returns the reported return
- * value.  If the call succeeds, the parent sets errno to 0 and returns 0.
- * If statusp is not NULL, it will contain the child's wait status.  Any
- * unexpected situation (failure to set up the reporting pipe, failure to
- * fork, unexpected return value from waitpid(), etc.) results in SIGABRT.
- */
-static int
-_fork_execvp(const char *name, char *const args[], const char *search_path,
-    int *statusp)
-{
-	struct { int ret, err; } report;
-	ssize_t sz;
-	pid_t pid;
-	int p[2], status;
-
-	if (search_path == NULL)
-		search_path = getenv("PATH");
-	if (search_path == NULL)
-		search_path = _PATH_DEFPATH;
-	report.ret = report.err = status = 0;
-	assert(pipe(p) == 0);
-	assert(fcntl(p[0], F_SETFD, FD_CLOEXEC) == 0);
-	assert(fcntl(p[1], F_SETFD, FD_CLOEXEC) == 0);
-	assert((pid = fork()) >= 0);
-	if (pid == 0) {
-		/* child */
-		errno = 0;
-		report.ret = execvP(name, search_path, args);
-		report.err = errno;
-		(void)write(p[1], &report, sizeof(report));
-		_exit(0);
-	}
-	/* parent */
-	assert(close(p[1]) == 0);
-	assert((sz = read(p[0], &report, sizeof(report))) >= 0);
-	assert(close(p[0]) == 0);
-	/* sz should be 0 if execvp() succeeded, sizeof(report) otherwise */
-	assert(sz == 0 || sz == sizeof(report));
-	assert(waitpid(pid, &status, 0) == pid);
-	if (statusp != NULL)
-		*statusp = status;
-	errno = report.err;
-	return (report.ret);
-}
-
-static int
-_fork_spawnp(const char *name, char *const args[], const char *search_path,
-    int *statusp)
-{
-	char *envp[2] = { NULL, NULL };
-	char *restore_path = NULL;
-	pid_t pid;
-	int ret, serrno, status;
-	bool need_restore = false;
-
-	if (search_path != NULL) {
-		need_restore = true;
-		restore_path = getenv("PATH");
-		if (restore_path != NULL) {
-			restore_path = strdup(restore_path);
-			assert(restore_path != NULL);
-		}
-
-		ret = setenv("PATH", search_path, 1);
-		assert(ret == 0);
-	} else {
-		search_path = getenv("PATH");
-		if (search_path == NULL)
-			search_path = _PATH_DEFPATH;
-	}
-
-	ret = asprintf(&envp[0], "PATH=%s", search_path);
-	assert(ret != -1);
-
-	ret = posix_spawnp(&pid, name, NULL, NULL, args, envp);
-	serrno = ret;
-	free(envp[0]);
-
-	if (ret == 0) {
-		assert(waitpid(pid, &status, 0) == pid);
-	} else {
-		ret = -1;
-		status = 0;
-	}
-
-	if (statusp != NULL)
-		*statusp = status;
-
-	if (need_restore) {
-		int sret = ret;
-
-		if (restore_path != NULL)
-			ret = setenv("PATH", restore_path, 1);
-		else
-			ret = unsetenv("PATH");
-
-		assert(ret == 0);
-		free(restore_path);
-		ret = sret;
-	}
-
-	errno = serrno;
-	return (ret);
-}
-
-/*
- * Simple successful execvp() case using an absolute path and an empty
- * search path.
- */
-T_DECL(execvp_success_absolute, "Success case (absolute)")
-{
-	char *name = "/bin/echo";
-	char *args[] = { name, "Hello, world!", NULL };
-	int status;
-
-	T_EXPECT_POSIX_SUCCESS(_fork_execvp(name, args, "", &status),
-	    "Executing a program successfully");
-	if (T_RESULT == T_RESULT_PASS) {
-		T_EXPECT_TRUE(WIFEXITED(status), "Checking termination");
-		T_EXPECT_EQ(WEXITSTATUS(status), 0, "Checking exit code");
-	}
-}
-
-/*
- * Simple successful posix_spawnp() case using an absolute path and an empty
- * search path.
- */
-T_DECL(spawnp_success_absolute, "Success case (absolute)")
-{
-	char *name = "/bin/echo";
-	char *args[] = { name, "Hello, world!", NULL };
-	int status;
-
-	T_EXPECT_POSIX_SUCCESS(_fork_spawnp(name, args, "", &status),
-	    "Executing a program successfully");
-	if (T_RESULT == T_RESULT_PASS) {
-		T_EXPECT_TRUE(WIFEXITED(status), "Checking termination");
-		T_EXPECT_EQ(WEXITSTATUS(status), 0, "Checking exit code");
-	}
-}
-
-/*
- * Simple successful execvp() case using a relative path.
- */
-T_DECL(execvp_success_relative, "Success case (relative)")
-{
-	char *name = "echo";
-	char *args[] = { name, "Hello, world!", NULL };
-	char *search_path = _PATH_DEFPATH;
-	int status;
-
-	T_EXPECT_POSIX_SUCCESS(_fork_execvp(name, args, search_path, &status),
-	    "Executing a program successfully");
-	if (T_RESULT == T_RESULT_PASS) {
-		T_EXPECT_TRUE(WIFEXITED(status), "Checking termination");
-		T_EXPECT_EQ(WEXITSTATUS(status), 0, "Checking exit code");
-	}
-}
-
-/*
- * Simple successful posix_spawnp() case using a relative path.
- */
-T_DECL(spawnp_success_relative, "Success case (relative)")
-{
-	char *name = "echo";
-	char *args[] = { name, "Hello, world!", NULL };
-	char *search_path = _PATH_DEFPATH;
-	int status;
-
-	T_EXPECT_POSIX_SUCCESS(_fork_spawnp(name, args, search_path, &status),
-	    "Executing a program successfully");
-	if (T_RESULT == T_RESULT_PASS) {
-		T_EXPECT_TRUE(WIFEXITED(status), "Checking termination");
-		T_EXPECT_EQ(WEXITSTATUS(status), 0, "Checking exit code");
-	}
-}
-
-/*
- * Successful execvp() of a program which is a shell script lacking a
- * shebang, thus relying on execvp()'s ENOEXEC fallback logic.
- */
-T_DECL(execvp_success_ENOEXEC, "Script without shebang")
-{
-	const char *dir = dt_tmpdir();
-	char *name = "success_ENOEXEC";
-	char *args[] = { name, NULL };
-	char *script = "exec true";
-	int dd, pd;
-
-	T_SETUPBEGIN;
-	T_ASSERT_POSIX_SUCCESS(dd = open(dir, O_RDONLY),
-	    "Opening directory %s", dir);
-	T_ASSERT_POSIX_SUCCESS(pd = openat(dd, name, O_RDWR|O_TRUNC|O_CREAT),
-	    "Creating program %s in %s", name, dir);
-	T_ASSERT_POSIX_SUCCESS(fchmod(pd, 0755),
-	    "Changing program permissions");
-	T_ASSERT_POSIX_SUCCESS(write(pd, script, strlen(script)),
-	    "Writing code to program");
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program");
-	T_SETUPEND;
-
-	T_EXPECT_POSIX_SUCCESS(_fork_execvp(name, args, dir, NULL),
-	    "Executing a shell script that lacks a shebang");
-
-	T_SETUPBEGIN;
-	T_EXPECT_POSIX_SUCCESS(unlinkat(dd, name, 0),
-	    "Deleting program");
-	T_EXPECT_POSIX_SUCCESS(close(dd),
-	    "Closing temporary directory");
-	T_SETUPEND;
-}
-
-/*
- * Attempt to invoke a program which is a shell script lacking a shebang,
- * thus relying on execvp()'s ENOEXEC fallback logic, but with an empty
- * argument list, which trips the bug described in rdar://107951804.
- *
- * In theory this is nondeterministic and the odds of the test passing
- * even when the bug is present are good.  In practice we seem to reliably
- * get an EFAULT.
- */
-T_DECL(execvp_rdar_107951804, "Script without shebang with empty argv")
-{
-	const char *dir = dt_tmpdir();
-	char *name = "rdar_107951804";
-	char *args[] = { NULL };
-	char *script = "test $# -eq 0";
-	int dd, pd;
-	int status;
-
-	T_SETUPBEGIN;
-	T_ASSERT_POSIX_SUCCESS(dd = open(dir, O_RDONLY),
-	    "Opening directory %s", dir);
-	T_ASSERT_POSIX_SUCCESS(pd = openat(dd, name, O_RDWR|O_TRUNC|O_CREAT),
-	    "Creating program %s in %s", name, dir);
-	T_ASSERT_POSIX_SUCCESS(fchmod(pd, 0755),
-	    "Changing program permissions");
-	T_ASSERT_POSIX_SUCCESS(write(pd, script, strlen(script)),
-	    "Writing code to program");
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program");
-	T_SETUPEND;
-
-	T_EXPECT_POSIX_SUCCESS(_fork_execvp(name, args, dir, &status),
-	    "Executing a shell script that lacks a shebang with an empty argument list");
-	if (T_RESULT == T_RESULT_PASS) {
-		T_EXPECT_TRUE(WIFEXITED(status), "Checking termination");
-		T_EXPECT_EQ(WEXITSTATUS(status), 0, "Checking exit code");
-	}
-
-	T_SETUPBEGIN;
-	T_EXPECT_POSIX_SUCCESS(unlinkat(dd, name, 0),
-	    "Deleting program");
-	T_EXPECT_POSIX_SUCCESS(close(dd),
-	    "Closing temporary directory");
-	T_SETUPEND;
-}
-
-/*
- * Attempt to execute a program which does not exist (absolute case).
- */
-T_DECL(execvp_failure_ENOENT_absolute, "Failure case (ENOENT, absolute)")
-{
-	char *name = "/path/to/this!program?does#not@exist";
-	char *args[] = { name, NULL };
-
-	T_ASSERT_POSIX_FAILURE(_fork_execvp(name, args, "", NULL), ENOENT,
-	    "Trying to execute a program that does not exist");
-}
-
-/*
- * Attempt to execute a program which does not exist (relative case).
- */
-T_DECL(execvp_failure_ENOENT_relative, "Failure case (ENOENT, relative)")
-{
-	const char *dir = dt_tmpdir();
-	char *name = "this!program?does#not@exist";
-	char *args[] = { name, NULL };
-
-	T_ASSERT_POSIX_FAILURE(_fork_execvp(name, args, dir, NULL), ENOENT,
-	    "Trying to execute a program that does not exist");
-}
-
-/*
- * Attempt to execute a program which is not executable.
- */
-T_DECL(execvp_failure_EACCES, "Failure case (EACCES)")
-{
-	const char *dir = dt_tmpdir();
-	const char *template = "/usr/bin/true";
-	char *name = "program_EACCES";
-	char *args[] = { name, NULL };
-	int pd;
-
-	T_SETUPBEGIN;
-	T_ASSERT_POSIX_SUCCESS(pd = _copy_program(template, dir, name, 0444),
-	    "Creating program %s in %s", name, dir);
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program");
-	T_SETUPEND;
-
-	T_EXPECT_POSIX_FAILURE(_fork_execvp(name, args, dir, NULL), EACCES,
-	    "Trying to execute a program which is not executable");
-}
-
-/*
- * Attempt to execute a program which is executable, but not by us.
- */
-T_DECL(execvp_failure_EPERM, "Failure case (EPERM)", T_META_ASROOT(false),
-    T_META_CHECK_LEAKS(false))
-{
-	const char *dir = dt_tmpdir();
-	const char *template = "/usr/bin/true";
-	char *name = "program_EPERM";
-	char *args[] = { name, NULL };
-	int pd;
-
-	T_SETUPBEGIN;
-	T_ASSERT_POSIX_SUCCESS(pd = _copy_program(template, dir, name, 0445),
-	    "Creating program %s in %s", name, dir);
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program");
-	T_SETUPEND;
-
-	T_EXPECT_POSIX_FAILURE(_fork_execvp(name, args, dir, NULL), EACCES,
-	    "Trying to execute a program which is executable but not by us");
-}
-
-/*
- * Attempt to execute a binary program while it is open for writing.
- */
-T_DECL(execvp_failure_ETXTBSY, "Failure case (ETXTBSY)")
-{
-	const char *dir = dt_tmpdir();
-	const char *template = "/usr/bin/true";
-	char *name = "program_ETXTBSY";
-	char *args[] = { name, NULL };
-	int pd;
-
-	T_SETUPBEGIN;
-	T_ASSERT_POSIX_SUCCESS(pd = _copy_program(template, dir, name, 0555),
-	    "Creating program %s in %s", name, dir);
-	T_SETUPEND;
-
-	/*
-	 * This should fail, but doesn't.  May be filesystem-dependent.
-	 */
-	T_EXPECTFAIL;
-	T_EXPECT_POSIX_FAILURE(_fork_execvp(name, args, dir, NULL), ETXTBSY,
-	    "Trying to execute a program which is open for writing");
-
-	T_SETUPBEGIN;
-	T_EXPECT_POSIX_SUCCESS(close(pd),
-	    "Closing program");
-	T_SETUPEND;
-}
-
-/*
- * Attempt to execute a program by absolute path which is too long.  We
- * achieve this by creating a symlink that points to its containing
- * directory so we can craft arbitrarily long paths to any file contained
- * in that directory.
- */
-T_DECL(execvp_failure_ENAMETOOLONG_absolute, "Failure case (ENAMETOOLONG, absolute)")
-{
-	const char *dir = dt_tmpdir();
-	const char *template = "/usr/bin/true";
-	char *linkname = "link_ENAMETOOLONG_absolute";
-	char *name = "program_ENAMETOOLONG_absolute";
-	char *args[] = { name, NULL };
-	char *full_path;
-	size_t name_max, path_max;
-	size_t len;
-	int dd, pd;
-	int ret;
-
-	T_SETUPBEGIN;
-	T_ASSERT_POSIX_SUCCESS(dd = open(dir, O_RDONLY),
-	    "Opening directory %s", dir);
-	(void)unlinkat(dd, linkname, 0);
-	T_ASSERT_POSIX_SUCCESS(symlinkat(".", dd, linkname),
-	    "Creating loopback symlink");
-	name_max = (size_t)fpathconf(dd, _PC_NAME_MAX);
-	T_LOG("NAME_MAX = %zu", name_max);
-	path_max = (size_t)fpathconf(dd, _PC_PATH_MAX);
-	T_LOG("PATH_MAX = %zu", path_max);
-	T_ASSERT_NOTNULL(full_path = malloc(path_max + name_max),
-	    "Allocating space for full path");
-	ret = snprintf(full_path, path_max + name_max, "%s", dir);
-	assert(ret >= 0);
-	len = (size_t)ret;
-	while (len + 1 + strlen(name) < path_max) {
-		ret = snprintf(full_path + len, path_max + name_max - len,
-		    "%s/", linkname);
-		assert(ret >= 0);
-		len += (size_t)ret;
-	}
-	ret = snprintf(full_path + len, path_max + name_max - len,
-	    "%s", name);
-	assert(ret >= 0);
-	len += (size_t)ret;
-	T_LOG("full path will be %s", full_path);
-	T_ASSERT_POSIX_SUCCESS(pd = _copy_program(template, dir, name, 0555),
-	    "Creating program %s in %s", name, dir);
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program");
-	T_EXPECT_POSIX_SUCCESS(close(dd),
-	    "Closing temporary directory");
-	T_SETUPEND;
-
-	T_EXPECT_POSIX_FAILURE(_fork_execvp(full_path, args, NULL, NULL), ENAMETOOLONG,
-	    "Trying to execute a program whose name is too long (absolute)");
-}
-
-/*
- * Attempt to execute a program by relative path which is too long.  We
- * achieve this by creating a symlink that points to its containing
- * directory so we can craft arbitrarily long paths to any file contained
- * in that directory.  We then craft a search path such that the requested
- * program exists in the search path but the combined path is too long.
- */
-T_DECL(execvp_failure_ENAMETOOLONG_relative, "Failure case (ENAMETOOLONG, relative)")
-{
-	const char *dir = dt_tmpdir();
-	const char *template = "/usr/bin/true";
-	char *linkname = "link_ENAMETOOLONG_relative";
-	char *name = "program_ENAMETOOLONG_relative";
-	char *args[] = { name, NULL };
-	char *relative_path;
-	size_t name_max, path_max;
-	size_t len;
-	int dd, pd;
-	int ret;
-
-	T_SETUPBEGIN;
-	T_ASSERT_POSIX_SUCCESS(dd = open(dir, O_RDONLY),
-	    "Opening directory %s", dir);
-	(void)unlinkat(dd, linkname, 0);
-	T_ASSERT_POSIX_SUCCESS(symlinkat(".", dd, linkname),
-	    "Creating loopback symlink");
-	name_max = (size_t)fpathconf(dd, _PC_NAME_MAX);
-	T_LOG("NAME_MAX = %zu", name_max);
-	path_max = (size_t)fpathconf(dd, _PC_PATH_MAX);
-	T_LOG("PATH_MAX = %zu", path_max);
-
-	/*
-	 * Add some extra space to make sure we thoroughly pass PATH_MAX,
-	 * regardless of the tmpdir length.
-	 */
-	path_max += strlen(linkname) + strlen(name) + 2;
-
-	T_ASSERT_NOTNULL(relative_path = malloc(path_max),
-	    "Allocating space for large relative path");
-	/* dt_tmpdir() won't normalize TMPDIR. */
-	ret = snprintf(relative_path, path_max, "%s%s", dir,
-	    dir[strlen(dir) - 1] == '/' ? "" : "/");
-	assert(ret >= 0);
-	len = (size_t)ret;
-	while (len + strlen(linkname) + 1 + strlen(name) < path_max) {
-		ret = snprintf(relative_path + len, path_max - len, "%s/",
-		    linkname);
-		assert(ret >= 0);
-		len += (size_t)ret;
-	}
-	snprintf(relative_path + len, path_max - len, "%s", name);
-	T_LOG("relative path will be %s", relative_path);
-	T_ASSERT_POSIX_SUCCESS(pd = _copy_program(template, dir, name, 0555),
-	    "Creating program %s in %s", name, dir);
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program");
-	T_EXPECT_POSIX_SUCCESS(close(dd),
-	    "Closing temporary directory");
-	T_SETUPEND;
-
-	T_EXPECT_POSIX_FAILURE(_fork_execvp(relative_path, args, NULL, NULL), ENAMETOOLONG,
-	    "Trying to execute a program whose name is too long (relative)");
-}
-
-static void
-setup_spawn_dirs(const char *dir)
-{
-	const char *template = "/usr/bin/true";
-	int dfd, pd, ret;
-
-	dfd = open(dir, O_DIRECTORY);
-	T_ASSERT_GE(dfd, 0, "Opening %s", dir);
-
-	ret = mkdirat(dfd, "dir1", 0755);
-	if (ret == -1 && errno != EEXIST)
-		T_ASSERT_POSIX_SUCCESS(ret, "Creating %s/dir1", dir);
-
-	ret = mkdirat(dfd, "dir2", 0755);
-	if (ret == -1 && errno != EEXIST)
-		T_ASSERT_POSIX_SUCCESS(ret, "Creating %s/dir2", dir);
-
-	T_ASSERT_POSIX_SUCCESS(pd = _copy_program_impl(template, dfd,
-	    "dir1/program1", 0755), "Creating program1 in %s/dir1", dir);
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program1");
-	T_ASSERT_POSIX_SUCCESS(pd = _copy_program_impl(template, dfd,
-	    "dir2/program2", 0755), "Creating program2 in %s/dir2", dir);
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program2");
-	T_ASSERT_POSIX_SUCCESS(pd = _copy_program_impl(template, dfd,
-	    "program3", 0755), "Creating program3 in %s", dir);
-	T_ASSERT_POSIX_SUCCESS(close(pd),
-	    "Closing program3");
-	T_ASSERT_POSIX_SUCCESS(close(dfd),
-	    "Closing tempdir dirfd");
-}
-
-/*
- * Simple successful execvp() cases relying on PATH searching.
- */
-T_DECL(execvp_success_searching, "Success case (searching)")
-{
-	const char *dir = dt_tmpdir();
-	char *search_path;
-	const char *name1 = "program1", *name2 = "program2";
-	const char *name3 = "program3";
-	char *args[2] = { NULL, NULL };
-	int ret;
-
-	T_SETUPBEGIN;
-	setup_spawn_dirs(dir);
-	T_SETUPEND;
-
-	ret = asprintf(&search_path, "%s/dir1:%s/dir2:", dir, dir);
-	T_ASSERT_GE(ret, 0, "Constructing search PATH");
-	T_LOG("search_path = %s", search_path);
-
-	args[0] = __DECONST(char *, name1);
-	T_EXPECT_POSIX_SUCCESS(_fork_execvp(name1, args, search_path, NULL),
-	    "Trying to execute a program in initial PATH");
-	args[0] = __DECONST(char *, name2);
-	T_EXPECT_POSIX_SUCCESS(_fork_execvp(name2, args, search_path, NULL),
-	    "Trying to execute a program in another part of PATH");
-
-	/* Implied CWD from component of PATH being empty */
-	args[0] = __DECONST(char *, name3);
-	T_EXPECT_POSIX_FAILURE(_fork_execvp(name3, args, search_path, NULL),
-	    ENOENT,
-	    "Trying to execute a program in empty part of PATH (wrong PWD)");
-	T_EXPECT_POSIX_SUCCESS(chdir(dir), "%s: chdir", dir);
-	T_EXPECT_POSIX_SUCCESS(_fork_execvp(name3, args, search_path, NULL),
-	    "Trying to execute a program in empty part of PATH (correct PWD)");
-
-	free(search_path);
-}
-
-/*
- * Simple successful spawnp() cases relying on PATH searching.
- */
-T_DECL(spawnp_success_searching, "Success case (searching)")
-{
-	const char *dir = dt_tmpdir();
-	char *search_path;
-	const char *name1 = "program1", *name2 = "program2";
-	const char *name3 = "program3";
-	char *args[2] = { NULL, NULL };
-	int ret;
-
-	T_SETUPBEGIN;
-	/* Ensure we're not in our tempdir. */
-	setup_spawn_dirs(dir);
-	T_SETUPEND;
-
-	ret = asprintf(&search_path, "%s/dir1:%s/dir2:", dir, dir);
-	T_ASSERT_GE(ret, 0, "Constructing search PATH");
-	T_LOG("search_path = %s", search_path);
-
-	args[0] = __DECONST(char *, name1);
-	T_EXPECT_POSIX_SUCCESS(_fork_spawnp(name1, args, search_path, NULL),
-	    "Trying to execute a program in initial PATH");
-	args[0] = __DECONST(char *, name2);
-	T_EXPECT_POSIX_SUCCESS(_fork_spawnp(name2, args, search_path, NULL),
-	    "Trying to execute a program in another part of PATH");
-
-	/* Implied CWD from component of PATH being empty */
-	args[0] = __DECONST(char *, name3);
-	T_EXPECT_POSIX_FAILURE(_fork_spawnp(name3, args, search_path, NULL),
-	    ENOENT,
-	    "Trying to execute a program in empty part of PATH (wrong PWD)");
-	T_EXPECT_POSIX_SUCCESS(chdir(dir), "%s: chdir", dir);
-	T_EXPECT_POSIX_SUCCESS(_fork_spawnp(name3, args, search_path, NULL),
-	    "Trying to execute a program in empty part of PATH (correct PWD)");
-
-	free(search_path);
-}