162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* Test that empty argvs are swapped out for a single empty string. */
362306a36Sopenharmony_ci#include <stdio.h>
462306a36Sopenharmony_ci#include <unistd.h>
562306a36Sopenharmony_ci#include <sys/types.h>
662306a36Sopenharmony_ci#include <sys/wait.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "../kselftest.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define FORK(exec)				\
1162306a36Sopenharmony_cido {						\
1262306a36Sopenharmony_ci	pid = fork();				\
1362306a36Sopenharmony_ci	if (pid == 0) {				\
1462306a36Sopenharmony_ci		/* Child */			\
1562306a36Sopenharmony_ci		exec; /* Some kind of exec */	\
1662306a36Sopenharmony_ci		perror("# " #exec);		\
1762306a36Sopenharmony_ci		return 1;			\
1862306a36Sopenharmony_ci	}					\
1962306a36Sopenharmony_ci	check_result(pid, #exec);		\
2062306a36Sopenharmony_ci} while (0)
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_civoid check_result(pid_t pid, const char *msg)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	int wstatus;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	if (pid == (pid_t)-1) {
2762306a36Sopenharmony_ci		perror("# fork");
2862306a36Sopenharmony_ci		ksft_test_result_fail("fork failed: %s\n", msg);
2962306a36Sopenharmony_ci		return;
3062306a36Sopenharmony_ci	}
3162306a36Sopenharmony_ci	if (waitpid(pid, &wstatus, 0) < 0) {
3262306a36Sopenharmony_ci		perror("# waitpid");
3362306a36Sopenharmony_ci		ksft_test_result_fail("waitpid failed: %s\n", msg);
3462306a36Sopenharmony_ci		return;
3562306a36Sopenharmony_ci	}
3662306a36Sopenharmony_ci	if (!WIFEXITED(wstatus)) {
3762306a36Sopenharmony_ci		ksft_test_result_fail("child did not exit: %s\n", msg);
3862306a36Sopenharmony_ci		return;
3962306a36Sopenharmony_ci	}
4062306a36Sopenharmony_ci	if (WEXITSTATUS(wstatus) != 0) {
4162306a36Sopenharmony_ci		ksft_test_result_fail("non-zero exit: %s\n", msg);
4262306a36Sopenharmony_ci		return;
4362306a36Sopenharmony_ci	}
4462306a36Sopenharmony_ci	ksft_test_result_pass("%s\n", msg);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciint main(int argc, char *argv[], char *envp[])
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	pid_t pid;
5062306a36Sopenharmony_ci	static char * const args[] = { NULL };
5162306a36Sopenharmony_ci	static char * const str[] = { "", NULL };
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	/* argc counting checks */
5462306a36Sopenharmony_ci	if (argc < 1) {
5562306a36Sopenharmony_ci		fprintf(stderr, "# FAIL: saw argc == 0 (old kernel?)\n");
5662306a36Sopenharmony_ci		return 1;
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci	if (argc != 1) {
5962306a36Sopenharmony_ci		fprintf(stderr, "# FAIL: unknown argc (%d)\n", argc);
6062306a36Sopenharmony_ci		return 1;
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci	if (argv[0][0] == '\0') {
6362306a36Sopenharmony_ci		/* Good, we found a NULL terminated string at argv[0]! */
6462306a36Sopenharmony_ci		return 0;
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	/* Test runner. */
6862306a36Sopenharmony_ci	ksft_print_header();
6962306a36Sopenharmony_ci	ksft_set_plan(5);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	FORK(execve(argv[0], str, NULL));
7262306a36Sopenharmony_ci	FORK(execve(argv[0], NULL, NULL));
7362306a36Sopenharmony_ci	FORK(execve(argv[0], NULL, envp));
7462306a36Sopenharmony_ci	FORK(execve(argv[0], args, NULL));
7562306a36Sopenharmony_ci	FORK(execve(argv[0], args, envp));
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	ksft_exit(ksft_cnt.ksft_pass == ksft_plan);
7862306a36Sopenharmony_ci}
79