/* Functional tests for spawn() syscall invoked indirectly via posix_spawn() or system(). */ #include <assert.h> #include <fcntl.h> #include <spawn.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/wait.h> #define EXE_NAME "../../../tests/true" static volatile int sigchld_handled = 0; static void sigchld_handler(int sig, siginfo_t *sip, void *ucontext) { assert(sig == SIGCHLD); sigchld_handled = 1; } int main(int argc, char *const argv[], char *const envp[]) { int ret = system(EXE_NAME); if (ret != 0) perror("system"); /* system() */ ret = system(NULL); if (ret == 0) fprintf(stderr, "system() succeeded"); /* posix_spawn(), no file actions, no attrs */ char *const argv_exe[] = {"true", NULL}; pid_t child; ret = posix_spawn(&child, EXE_NAME, NULL, NULL, argv_exe, envp); if (ret != 0) perror("posix_spawn"); waitpid(child, NULL, 0); /* posix_spawn(), file actions, no attrs */ posix_spawn_file_actions_t fa; ret = posix_spawn_file_actions_init(&fa); if (ret != 0) perror("posix_spawn_file_actions_init"); ret = posix_spawn_file_actions_addopen(&fa, 10, "/dev/null", O_RDONLY, 0); if (ret != 0) perror("posix_spawn_file_actions_addopen"); ret = posix_spawn(&child, EXE_NAME, &fa, NULL, argv_exe, envp); if (ret != 0) perror("posix_spawn"); waitpid(child, NULL, 0); ret = posix_spawn_file_actions_destroy(&fa); if (ret != 0) perror("posix_spawn_file_actions_destroy"); /* posix_spawn(), no file actions, attrs */ posix_spawnattr_t spa; ret = posix_spawnattr_init(&spa); if (ret != 0) perror("posix_spawnattr_init"); ret = posix_spawnattr_setflags(&spa, POSIX_SPAWN_RESETIDS); if (ret != 0) perror("posix_spawnattr_setflags"); ret = posix_spawn(&child, EXE_NAME, NULL, &spa, argv_exe, envp); if (ret != 0) perror("posix_spawn"); waitpid(child, NULL, 0); ret = posix_spawnattr_destroy(&spa); if (ret != 0) perror("posix_spawnattr_destroy"); /* posix_spawn(), no file actions, no attrs, test SIGCHLD delivery */ struct sigaction act; bzero(&act, sizeof(act)); act.sa_sigaction = sigchld_handler; act.sa_flags = SA_SIGINFO; ret = sigaction(SIGCHLD, &act, NULL); if (ret != 0) perror("sigaction"); sigchld_handled = 0; ret = posix_spawn(&child, EXE_NAME, NULL, NULL, argv_exe, envp); if (ret != 0) perror("posix_spawn"); waitpid(child, NULL, 0); if (sigchld_handled == 1) { printf("PASS\n"); } else { printf("FAIL\n"); } /* posix_spawn(), no file actions, attrs, test *no* SIGCHLD delivery */ ret = posix_spawnattr_init(&spa); if (ret != 0) perror("posix_spawnattr_init"); ret = posix_spawnattr_setflags(&spa, POSIX_SPAWN_NOSIGCHLD_NP); if (ret != 0) perror("posix_spawnattr_setflags"); sigchld_handled = 0; ret = posix_spawn(&child, EXE_NAME, NULL, &spa, argv_exe, envp); if (ret != 0) perror("posix_spawn"); waitpid(child, NULL, 0); if (sigchld_handled == 0) { printf("PASS\n"); } else { printf("FAIL\n"); } ret = posix_spawnattr_destroy(&spa); if (ret != 0) perror("posix_spawnattr_destroy"); return 0; }