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) \
11do { \
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
22void 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(msg: "fork failed: %s\n", msg);
29 return;
30 }
31 if (waitpid(pid, &wstatus, 0) < 0) {
32 perror("# waitpid");
33 ksft_test_result_fail(msg: "waitpid failed: %s\n", msg);
34 return;
35 }
36 if (!WIFEXITED(wstatus)) {
37 ksft_test_result_fail(msg: "child did not exit: %s\n", msg);
38 return;
39 }
40 if (WEXITSTATUS(wstatus) != 0) {
41 ksft_test_result_fail(msg: "non-zero exit: %s\n", msg);
42 return;
43 }
44 ksft_test_result_pass(msg: "%s\n", msg);
45}
46
47int 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(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

source code of linux/tools/testing/selftests/exec/null-argv.c