| /* 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; |
| } |