]>
Commit | Line | Data |
---|---|---|
cb323159 A |
1 | #include <darwintest.h> |
2 | ||
3 | #include <errno.h> | |
4 | #include <libproc.h> | |
5 | #include <signal.h> | |
6 | #include <spawn.h> | |
7 | #include <spawn_private.h> | |
8 | #include <stdbool.h> | |
9 | #include <stdint.h> | |
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
13 | #include <sys/proc_info.h> | |
14 | #include <sys/spawn_internal.h> | |
15 | #include <sys/sysctl.h> | |
16 | #include <sysexits.h> | |
17 | #include <unistd.h> | |
18 | #include <sys/fileport.h> | |
19 | ||
20 | T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true)); | |
21 | ||
22 | T_DECL(posix_spawn_file_actions_add_fileportdup2_np, | |
23 | "Check posix_spawnattr for posix_spawn_file_actions_add_fileportdup2_np", | |
24 | T_META_ASROOT(true)) | |
25 | { | |
26 | posix_spawnattr_t attr; | |
27 | posix_spawn_file_actions_t fact; | |
28 | int ret, pipes[2]; | |
29 | mach_port_t mp; | |
30 | ||
31 | ret = pipe(pipes); | |
32 | T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "pipe"); | |
33 | ||
34 | ret = fileport_makeport(pipes[1], &mp); | |
35 | T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "fileport_makefd"); | |
36 | ||
37 | ret = posix_spawnattr_init(&attr); | |
38 | T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "posix_spawnattr_init"); | |
39 | ||
40 | ret = posix_spawn_file_actions_init(&fact); | |
41 | T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "posix_spawn_file_actions_init"); | |
42 | ||
43 | ret = posix_spawn_file_actions_add_fileportdup2_np(&fact, mp, STDOUT_FILENO); | |
44 | T_ASSERT_POSIX_SUCCESS(ret, "posix_spawn_file_actions_add_fileportdup2_np"); | |
45 | ||
46 | char * const prog = "/bin/echo"; | |
47 | char * const argv_child[] = { prog, "1", NULL }; | |
48 | pid_t child_pid; | |
49 | extern char **environ; | |
50 | ||
51 | ret = posix_spawn(&child_pid, prog, &fact, &attr, argv_child, environ); | |
52 | T_ASSERT_POSIX_SUCCESS(ret, "posix_spawn"); | |
53 | ||
54 | ret = posix_spawn_file_actions_destroy(&fact); | |
55 | T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "posix_spawn_file_actions_destroy"); | |
56 | ||
57 | ret = posix_spawnattr_destroy(&attr); | |
58 | T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "posix_spawnattr_destroy"); | |
59 | ||
60 | T_LOG("parent: spawned child with pid %d\n", child_pid); | |
61 | ||
62 | int status = 0; | |
63 | int waitpid_result = waitpid(child_pid, &status, 0); | |
64 | T_ASSERT_POSIX_SUCCESS(waitpid_result, "waitpid"); | |
65 | T_ASSERT_EQ(waitpid_result, child_pid, "waitpid should return child we spawned"); | |
66 | T_ASSERT_EQ(WIFEXITED(status), 1, "child should have exited normally"); | |
67 | T_ASSERT_EQ(WEXITSTATUS(status), EX_OK, "child should have exited with success"); | |
68 | ||
69 | char buf[1]; | |
70 | ssize_t rc = read(pipes[0], buf, sizeof(buf)); | |
71 | T_ASSERT_POSIX_SUCCESS(rc, "read"); | |
72 | T_ASSERT_EQ(rc, 1l, "should have read one byte"); | |
73 | T_ASSERT_EQ(buf[0], '1', "should have read '1'"); | |
74 | } |