1 /* Functional tests for spawn() syscall invoked indirectly via posix_spawn()
2    or system(). */
3 
4 #include <assert.h>
5 #include <fcntl.h>
6 #include <spawn.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <strings.h>
10 #include <sys/wait.h>
11 
12 
13 #define EXE_NAME "../../../tests/true"
14 
15 static volatile int sigchld_handled = 0;
sigchld_handler(int sig,siginfo_t * sip,void * ucontext)16 static void sigchld_handler(int sig, siginfo_t *sip, void *ucontext) {
17    assert(sig == SIGCHLD);
18    sigchld_handled = 1;
19 }
20 
main(int argc,char * const argv[],char * const envp[])21 int main(int argc, char *const argv[], char *const envp[]) {
22    int ret = system(EXE_NAME);
23    if (ret != 0)
24       perror("system");
25 
26    /* system() */
27    ret = system(NULL);
28    if (ret == 0)
29       fprintf(stderr, "system() succeeded");
30 
31    /* posix_spawn(), no file actions, no attrs */
32    char *const argv_exe[] = {"true", NULL};
33    pid_t child;
34    ret = posix_spawn(&child, EXE_NAME, NULL, NULL, argv_exe, envp);
35    if (ret != 0)
36       perror("posix_spawn");
37    waitpid(child, NULL, 0);
38 
39    /* posix_spawn(), file actions, no attrs */
40    posix_spawn_file_actions_t fa;
41    ret = posix_spawn_file_actions_init(&fa);
42    if (ret != 0)
43       perror("posix_spawn_file_actions_init");
44    ret = posix_spawn_file_actions_addopen(&fa, 10, "/dev/null", O_RDONLY, 0);
45    if (ret != 0)
46       perror("posix_spawn_file_actions_addopen");
47    ret = posix_spawn(&child, EXE_NAME, &fa, NULL, argv_exe, envp);
48    if (ret != 0)
49       perror("posix_spawn");
50    waitpid(child, NULL, 0);
51    ret = posix_spawn_file_actions_destroy(&fa);
52    if (ret != 0)
53       perror("posix_spawn_file_actions_destroy");
54 
55    /* posix_spawn(), no file actions, attrs */
56    posix_spawnattr_t spa;
57    ret = posix_spawnattr_init(&spa);
58    if (ret != 0)
59       perror("posix_spawnattr_init");
60    ret = posix_spawnattr_setflags(&spa, POSIX_SPAWN_RESETIDS);
61    if (ret != 0)
62       perror("posix_spawnattr_setflags");
63    ret = posix_spawn(&child, EXE_NAME, NULL, &spa, argv_exe, envp);
64    if (ret != 0)
65       perror("posix_spawn");
66    waitpid(child, NULL, 0);
67    ret = posix_spawnattr_destroy(&spa);
68    if (ret != 0)
69       perror("posix_spawnattr_destroy");
70 
71    /* posix_spawn(), no file actions, no attrs, test SIGCHLD delivery */
72    struct sigaction act;
73    bzero(&act, sizeof(act));
74    act.sa_sigaction = sigchld_handler;
75    act.sa_flags = SA_SIGINFO;
76    ret = sigaction(SIGCHLD, &act, NULL);
77    if (ret != 0)
78       perror("sigaction");
79    sigchld_handled = 0;
80    ret = posix_spawn(&child, EXE_NAME, NULL, NULL, argv_exe, envp);
81    if (ret != 0)
82       perror("posix_spawn");
83    waitpid(child, NULL, 0);
84    if (sigchld_handled == 1) {
85       printf("PASS\n");
86    } else {
87       printf("FAIL\n");
88    }
89 
90    /* posix_spawn(), no file actions, attrs, test *no* SIGCHLD delivery */
91    ret = posix_spawnattr_init(&spa);
92    if (ret != 0)
93       perror("posix_spawnattr_init");
94    ret = posix_spawnattr_setflags(&spa, POSIX_SPAWN_NOSIGCHLD_NP);
95    if (ret != 0)
96       perror("posix_spawnattr_setflags");
97    sigchld_handled = 0;
98    ret = posix_spawn(&child, EXE_NAME, NULL, &spa, argv_exe, envp);
99    if (ret != 0)
100       perror("posix_spawn");
101    waitpid(child, NULL, 0);
102    if (sigchld_handled == 0) {
103       printf("PASS\n");
104    } else {
105       printf("FAIL\n");
106    }
107    ret = posix_spawnattr_destroy(&spa);
108    if (ret != 0)
109       perror("posix_spawnattr_destroy");
110 
111    return 0;
112 }
113