1 #include <darwintest.h>
7 #include <spawn_private.h>
13 #include <sys/spawn_internal.h>
14 #include <sys/sysctl.h>
15 #include <sys/syslimits.h>
19 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
21 /* TEST_PATH needs to be something that exists, but is not the cwd */
22 #define TEST_PATH "/System/Library/Caches"
24 T_DECL(posix_spawn_file_actions_addchdir_np
, "Check posix_spawn_file_actions_addchdir_np",
27 posix_spawn_file_actions_t file_actions
;
30 ret
= posix_spawn_file_actions_init(&file_actions
);
32 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_init");
34 ret
= posix_spawn_file_actions_addchdir_np(&file_actions
, TEST_PATH
);
35 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_addchdir_np");
37 char * const prog
= "/bin/sh";
38 char * const argv_child
[] = { prog
,
40 "test $(pwd) = \"" TEST_PATH
"\"",
43 extern char **environ
;
45 ret
= posix_spawn(&child_pid
, prog
, &file_actions
, NULL
, argv_child
, environ
);
46 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn");
48 T_LOG("parent: spawned child with pid %d\n", child_pid
);
50 ret
= posix_spawn_file_actions_destroy(&file_actions
);
52 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_destroy");
54 T_LOG("parent: waiting for child process\n");
57 int waitpid_result
= waitpid(child_pid
, &status
, 0);
58 T_ASSERT_POSIX_SUCCESS(waitpid_result
, "waitpid");
59 T_ASSERT_EQ(waitpid_result
, child_pid
, "waitpid should return child we spawned");
60 T_ASSERT_EQ(WIFEXITED(status
), 1, "child should have exited normally");
61 T_ASSERT_EQ(WEXITSTATUS(status
), EX_OK
, "child should have exited with success");
64 T_DECL(posix_spawn_file_actions_addchdir_np_errors
, "Check posix_spawn_file_actions_addchdir_np errors",
67 char longpath
[PATH_MAX
+ 1];
68 posix_spawn_file_actions_t file_actions
;
71 memset(longpath
, 'a', PATH_MAX
);
72 longpath
[PATH_MAX
] = '\0';
74 ret
= posix_spawn_file_actions_init(&file_actions
);
76 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_init");
78 ret
= posix_spawn_file_actions_addchdir_np(NULL
, "/");
79 T_ASSERT_EQ(ret
, EINVAL
, "NULL *file_actions returns EINVAL");
81 ret
= posix_spawn_file_actions_addchdir_np(&file_actions
, longpath
);
82 T_ASSERT_EQ(ret
, ENAMETOOLONG
, "Path longer than PATH_MAX returns ENAMETOOLONG");
84 ret
= posix_spawn_file_actions_destroy(&file_actions
);
86 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_destroy");
89 T_DECL(posix_spawn_file_actions_addfchdir_np
, "Check posix_spawn_file_actions_addfchdir_np",
92 posix_spawn_file_actions_t file_actions
;
96 ret
= posix_spawn_file_actions_init(&file_actions
);
98 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_init");
100 test_fd
= open(TEST_PATH
, O_RDONLY
| O_CLOEXEC
);
101 T_ASSERT_POSIX_SUCCESS(test_fd
, "open " TEST_PATH
);
103 ret
= posix_spawn_file_actions_addfchdir_np(&file_actions
, test_fd
);
104 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_addfchdir_np");
106 char * const prog
= "/bin/sh";
107 char * const argv_child
[] = { prog
,
109 "test $(pwd) = \"" TEST_PATH
"\"",
112 extern char **environ
;
114 ret
= posix_spawn(&child_pid
, prog
, &file_actions
, NULL
, argv_child
, environ
);
115 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn");
117 T_LOG("parent: spawned child with pid %d\n", child_pid
);
119 ret
= posix_spawn_file_actions_destroy(&file_actions
);
121 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_destroy");
123 T_LOG("parent: waiting for child process\n");
126 int waitpid_result
= waitpid(child_pid
, &status
, 0);
127 T_ASSERT_POSIX_SUCCESS(waitpid_result
, "waitpid");
128 T_ASSERT_EQ(waitpid_result
, child_pid
, "waitpid should return child we spawned");
129 T_ASSERT_EQ(WIFEXITED(status
), 1, "child should have exited normally");
130 T_ASSERT_EQ(WEXITSTATUS(status
), EX_OK
, "child should have exited with success");
132 ret
= close(test_fd
);
134 T_ASSERT_POSIX_SUCCESS(ret
, "close test fd");
137 T_DECL(posix_spawn_file_actions_addfchdir_np_errors
, "Check posix_spawn_file_actions_addfchdir_np errors",
140 posix_spawn_file_actions_t file_actions
;
143 ret
= posix_spawn_file_actions_init(&file_actions
);
145 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_init");
147 ret
= posix_spawn_file_actions_addfchdir_np(NULL
, 0);
148 T_ASSERT_EQ(ret
, EINVAL
, "NULL *file_actions returns EINVAL");
150 ret
= posix_spawn_file_actions_addfchdir_np(&file_actions
, -1);
151 T_ASSERT_EQ(ret
, EBADF
, "-1 file descriptor returns EBADF");
153 ret
= posix_spawn_file_actions_destroy(&file_actions
);
155 T_ASSERT_POSIX_SUCCESS(ret
, "posix_spawn_file_actions_destroy");