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