xref: /openbmc/linux/tools/testing/selftests/exec/null-argv.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1*9132c394SKees Cook // SPDX-License-Identifier: GPL-2.0-only
2*9132c394SKees Cook /* Test that empty argvs are swapped out for a single empty string. */
3*9132c394SKees Cook #include <stdio.h>
4*9132c394SKees Cook #include <unistd.h>
5*9132c394SKees Cook #include <sys/types.h>
6*9132c394SKees Cook #include <sys/wait.h>
7*9132c394SKees Cook 
8*9132c394SKees Cook #include "../kselftest.h"
9*9132c394SKees Cook 
10*9132c394SKees Cook #define FORK(exec)				\
11*9132c394SKees Cook do {						\
12*9132c394SKees Cook 	pid = fork();				\
13*9132c394SKees Cook 	if (pid == 0) {				\
14*9132c394SKees Cook 		/* Child */			\
15*9132c394SKees Cook 		exec; /* Some kind of exec */	\
16*9132c394SKees Cook 		perror("# " #exec);		\
17*9132c394SKees Cook 		return 1;			\
18*9132c394SKees Cook 	}					\
19*9132c394SKees Cook 	check_result(pid, #exec);		\
20*9132c394SKees Cook } while (0)
21*9132c394SKees Cook 
check_result(pid_t pid,const char * msg)22*9132c394SKees Cook void check_result(pid_t pid, const char *msg)
23*9132c394SKees Cook {
24*9132c394SKees Cook 	int wstatus;
25*9132c394SKees Cook 
26*9132c394SKees Cook 	if (pid == (pid_t)-1) {
27*9132c394SKees Cook 		perror("# fork");
28*9132c394SKees Cook 		ksft_test_result_fail("fork failed: %s\n", msg);
29*9132c394SKees Cook 		return;
30*9132c394SKees Cook 	}
31*9132c394SKees Cook 	if (waitpid(pid, &wstatus, 0) < 0) {
32*9132c394SKees Cook 		perror("# waitpid");
33*9132c394SKees Cook 		ksft_test_result_fail("waitpid failed: %s\n", msg);
34*9132c394SKees Cook 		return;
35*9132c394SKees Cook 	}
36*9132c394SKees Cook 	if (!WIFEXITED(wstatus)) {
37*9132c394SKees Cook 		ksft_test_result_fail("child did not exit: %s\n", msg);
38*9132c394SKees Cook 		return;
39*9132c394SKees Cook 	}
40*9132c394SKees Cook 	if (WEXITSTATUS(wstatus) != 0) {
41*9132c394SKees Cook 		ksft_test_result_fail("non-zero exit: %s\n", msg);
42*9132c394SKees Cook 		return;
43*9132c394SKees Cook 	}
44*9132c394SKees Cook 	ksft_test_result_pass("%s\n", msg);
45*9132c394SKees Cook }
46*9132c394SKees Cook 
main(int argc,char * argv[],char * envp[])47*9132c394SKees Cook int main(int argc, char *argv[], char *envp[])
48*9132c394SKees Cook {
49*9132c394SKees Cook 	pid_t pid;
50*9132c394SKees Cook 	static char * const args[] = { NULL };
51*9132c394SKees Cook 	static char * const str[] = { "", NULL };
52*9132c394SKees Cook 
53*9132c394SKees Cook 	/* argc counting checks */
54*9132c394SKees Cook 	if (argc < 1) {
55*9132c394SKees Cook 		fprintf(stderr, "# FAIL: saw argc == 0 (old kernel?)\n");
56*9132c394SKees Cook 		return 1;
57*9132c394SKees Cook 	}
58*9132c394SKees Cook 	if (argc != 1) {
59*9132c394SKees Cook 		fprintf(stderr, "# FAIL: unknown argc (%d)\n", argc);
60*9132c394SKees Cook 		return 1;
61*9132c394SKees Cook 	}
62*9132c394SKees Cook 	if (argv[0][0] == '\0') {
63*9132c394SKees Cook 		/* Good, we found a NULL terminated string at argv[0]! */
64*9132c394SKees Cook 		return 0;
65*9132c394SKees Cook 	}
66*9132c394SKees Cook 
67*9132c394SKees Cook 	/* Test runner. */
68*9132c394SKees Cook 	ksft_print_header();
69*9132c394SKees Cook 	ksft_set_plan(5);
70*9132c394SKees Cook 
71*9132c394SKees Cook 	FORK(execve(argv[0], str, NULL));
72*9132c394SKees Cook 	FORK(execve(argv[0], NULL, NULL));
73*9132c394SKees Cook 	FORK(execve(argv[0], NULL, envp));
74*9132c394SKees Cook 	FORK(execve(argv[0], args, NULL));
75*9132c394SKees Cook 	FORK(execve(argv[0], args, envp));
76*9132c394SKees Cook 
77*9132c394SKees Cook 	ksft_exit(ksft_cnt.ksft_pass == ksft_plan);
78*9132c394SKees Cook }
79