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
15static volatile int sigchld_handled = 0;
16static void sigchld_handler(int sig, siginfo_t *sip, void *ucontext) {
17   assert(sig == SIGCHLD);
18   sigchld_handled = 1;
19}
20
21int 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