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");