xref: /illumos-gate/usr/src/test/os-tests/tests/execvpe/execvpe-test.c (revision a89c0811c892ec231725fe10817ef95dda813c06)
1*a89c0811SRobert Mustacchi /*
2*a89c0811SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*a89c0811SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*a89c0811SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*a89c0811SRobert Mustacchi  * 1.0 of the CDDL.
6*a89c0811SRobert Mustacchi  *
7*a89c0811SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*a89c0811SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*a89c0811SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*a89c0811SRobert Mustacchi  */
11*a89c0811SRobert Mustacchi 
12*a89c0811SRobert Mustacchi /*
13*a89c0811SRobert Mustacchi  * Copyright 2024 Oxide Computer Company
14*a89c0811SRobert Mustacchi  */
15*a89c0811SRobert Mustacchi 
16*a89c0811SRobert Mustacchi /*
17*a89c0811SRobert Mustacchi  * This tests various behaviors of execvpe to try and verify that it is working
18*a89c0811SRobert Mustacchi  * as expected.
19*a89c0811SRobert Mustacchi  */
20*a89c0811SRobert Mustacchi 
21*a89c0811SRobert Mustacchi #include <stdlib.h>
22*a89c0811SRobert Mustacchi #include <err.h>
23*a89c0811SRobert Mustacchi #include <unistd.h>
24*a89c0811SRobert Mustacchi #include <stdbool.h>
25*a89c0811SRobert Mustacchi #include <errno.h>
26*a89c0811SRobert Mustacchi #include <sys/sysmacros.h>
27*a89c0811SRobert Mustacchi #include <sys/fork.h>
28*a89c0811SRobert Mustacchi #include <sys/types.h>
29*a89c0811SRobert Mustacchi #include <sys/wait.h>
30*a89c0811SRobert Mustacchi #include <stdio.h>
31*a89c0811SRobert Mustacchi 
32*a89c0811SRobert Mustacchi typedef struct {
33*a89c0811SRobert Mustacchi 	const char *et_desc;
34*a89c0811SRobert Mustacchi 	const char *et_prog;
35*a89c0811SRobert Mustacchi 	const char *et_path;
36*a89c0811SRobert Mustacchi 	bool et_pass;
37*a89c0811SRobert Mustacchi 	int et_errno;
38*a89c0811SRobert Mustacchi } execvpe_test_t;
39*a89c0811SRobert Mustacchi 
40*a89c0811SRobert Mustacchi static const execvpe_test_t execvpe_tests[] = {
41*a89c0811SRobert Mustacchi 	{ .et_desc = "execute ls on default path", .et_prog = "ls",
42*a89c0811SRobert Mustacchi 	    .et_path = NULL, .et_pass = true },
43*a89c0811SRobert Mustacchi 	{ .et_desc = "execute ls on specified path (1)", .et_prog = "ls",
44*a89c0811SRobert Mustacchi 	    .et_path = "/usr/bin", .et_pass = true },
45*a89c0811SRobert Mustacchi 	{ .et_desc = "execute ls on specified path (2)", .et_prog = "ls",
46*a89c0811SRobert Mustacchi 	    .et_path = "/usr/lib/fm/topo/maps:/enoent:/usr/bin",
47*a89c0811SRobert Mustacchi 	    .et_pass = true },
48*a89c0811SRobert Mustacchi 	{ .et_desc = "fail to find ls on path", .et_prog = "ls",
49*a89c0811SRobert Mustacchi 	    .et_path = "/usr/lib/mdb/raw", .et_pass = false,
50*a89c0811SRobert Mustacchi 	    .et_errno = ENOENT },
51*a89c0811SRobert Mustacchi 	{ .et_desc = "fail to find program on default path",
52*a89c0811SRobert Mustacchi 	    .et_prog = "()theroadgoeseveronandon?!@#$%,downfromthedoor",
53*a89c0811SRobert Mustacchi 	    .et_path = NULL, .et_pass = false, .et_errno = ENOENT },
54*a89c0811SRobert Mustacchi 	{ .et_desc = "shell executes script without #!",
55*a89c0811SRobert Mustacchi 	    .et_prog = "execvpe-script",
56*a89c0811SRobert Mustacchi 	    .et_path = "/opt/os-tests/tests/execvpe", .et_pass = true },
57*a89c0811SRobert Mustacchi 	{ .et_desc = "properly fail with non-executable file",
58*a89c0811SRobert Mustacchi 	    .et_prog = "execvpe-noperm",
59*a89c0811SRobert Mustacchi 	    .et_path = "/opt/os-tests/tests/execvpe", .et_pass = false,
60*a89c0811SRobert Mustacchi 	    .et_errno = EACCES },
61*a89c0811SRobert Mustacchi 	{ .et_desc = "absolute path works if not in PATH",
62*a89c0811SRobert Mustacchi 	    .et_prog = "/usr/bin/true", .et_path = "/usr/lib", .et_pass = true }
63*a89c0811SRobert Mustacchi };
64*a89c0811SRobert Mustacchi 
65*a89c0811SRobert Mustacchi static bool
execvpe_test_one(const execvpe_test_t * test)66*a89c0811SRobert Mustacchi execvpe_test_one(const execvpe_test_t *test)
67*a89c0811SRobert Mustacchi {
68*a89c0811SRobert Mustacchi 	pid_t pid, wpid;
69*a89c0811SRobert Mustacchi 	int stat;
70*a89c0811SRobert Mustacchi 	const char *envp[4];
71*a89c0811SRobert Mustacchi 	const char *argv[2];
72*a89c0811SRobert Mustacchi 
73*a89c0811SRobert Mustacchi 	if (test->et_path != NULL) {
74*a89c0811SRobert Mustacchi 		if (setenv("PATH", test->et_path, 1) != 0) {
75*a89c0811SRobert Mustacchi 			err(EXIT_FAILURE, "TEST FAILED: %s: fatal error: "
76*a89c0811SRobert Mustacchi 			    "failed to set PATH", test->et_desc);
77*a89c0811SRobert Mustacchi 		}
78*a89c0811SRobert Mustacchi 	} else {
79*a89c0811SRobert Mustacchi 		if (unsetenv("PATH") != 0) {
80*a89c0811SRobert Mustacchi 			err(EXIT_FAILURE, "TEST FAILED: %s: fatal error: "
81*a89c0811SRobert Mustacchi 			    "failed to unset PATH", test->et_desc);
82*a89c0811SRobert Mustacchi 		}
83*a89c0811SRobert Mustacchi 	}
84*a89c0811SRobert Mustacchi 
85*a89c0811SRobert Mustacchi 	envp[0] = "PATH=/this/should/not/interfere:/with/the/test";
86*a89c0811SRobert Mustacchi 	envp[1] = "EXECVPE_TEST=Keep it secret, keep it safe!";
87*a89c0811SRobert Mustacchi 	envp[2] = "WHOAMI=gandalf";
88*a89c0811SRobert Mustacchi 	envp[3] = NULL;
89*a89c0811SRobert Mustacchi 
90*a89c0811SRobert Mustacchi 	argv[0] = test->et_prog;
91*a89c0811SRobert Mustacchi 	argv[1] = NULL;
92*a89c0811SRobert Mustacchi 
93*a89c0811SRobert Mustacchi 	pid = forkx(FORK_NOSIGCHLD | FORK_WAITPID);
94*a89c0811SRobert Mustacchi 	if (pid == 0) {
95*a89c0811SRobert Mustacchi 		int ret = EXIT_SUCCESS, e;
96*a89c0811SRobert Mustacchi 		(void) execvpe(test->et_prog, (char * const *)argv,
97*a89c0811SRobert Mustacchi 		    (char *const *)envp);
98*a89c0811SRobert Mustacchi 		e = errno;
99*a89c0811SRobert Mustacchi 		if (test->et_pass) {
100*a89c0811SRobert Mustacchi 			warnc(e, "TEST FAILED: %s: expected execvpe success, "
101*a89c0811SRobert Mustacchi 			    "but no such luck", test->et_desc);
102*a89c0811SRobert Mustacchi 			ret = EXIT_FAILURE;
103*a89c0811SRobert Mustacchi 		} else if (test->et_errno != e) {
104*a89c0811SRobert Mustacchi 			warnx("TEST FAILED: %s: execvpe failed with errno %d, "
105*a89c0811SRobert Mustacchi 			    "expected %d", test->et_desc, e, test->et_errno);
106*a89c0811SRobert Mustacchi 			ret = EXIT_FAILURE;
107*a89c0811SRobert Mustacchi 		}
108*a89c0811SRobert Mustacchi 		_exit(ret);
109*a89c0811SRobert Mustacchi 	}
110*a89c0811SRobert Mustacchi 
111*a89c0811SRobert Mustacchi 	wpid = waitpid(pid, &stat, 0);
112*a89c0811SRobert Mustacchi 	if (wpid != pid) {
113*a89c0811SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: %s: encountered fatal error "
114*a89c0811SRobert Mustacchi 		    "waitpid returned wrong pid: %" _PRIdID ", expected "
115*a89c0811SRobert Mustacchi 		    "%" _PRIdID, test->et_desc, wpid, pid);
116*a89c0811SRobert Mustacchi 	}
117*a89c0811SRobert Mustacchi 
118*a89c0811SRobert Mustacchi 	if (stat == EXIT_SUCCESS) {
119*a89c0811SRobert Mustacchi 		(void) printf("TEST PASSED: %s\n", test->et_desc);
120*a89c0811SRobert Mustacchi 		return (true);
121*a89c0811SRobert Mustacchi 	}
122*a89c0811SRobert Mustacchi 
123*a89c0811SRobert Mustacchi 	return (false);
124*a89c0811SRobert Mustacchi }
125*a89c0811SRobert Mustacchi 
126*a89c0811SRobert Mustacchi int
main(void)127*a89c0811SRobert Mustacchi main(void)
128*a89c0811SRobert Mustacchi {
129*a89c0811SRobert Mustacchi 	int ret = EXIT_SUCCESS;
130*a89c0811SRobert Mustacchi 
131*a89c0811SRobert Mustacchi 	for (size_t i = 0; i < ARRAY_SIZE(execvpe_tests); i++) {
132*a89c0811SRobert Mustacchi 		if (!execvpe_test_one(&execvpe_tests[i]))
133*a89c0811SRobert Mustacchi 			ret = EXIT_FAILURE;
134*a89c0811SRobert Mustacchi 	}
135*a89c0811SRobert Mustacchi 
136*a89c0811SRobert Mustacchi 	if (ret == EXIT_SUCCESS) {
137*a89c0811SRobert Mustacchi 		(void) printf("All tests passed successfully!\n");
138*a89c0811SRobert Mustacchi 	}
139*a89c0811SRobert Mustacchi 
140*a89c0811SRobert Mustacchi 	return (ret);
141*a89c0811SRobert Mustacchi }
142