xref: /illumos-gate/usr/src/test/libc-tests/tests/posix_spawn/posix_spawn_child.c (revision 93d6c51de00648a982a50fbecc433b5482953fc7)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2026 Oxide Computer Company
14  */
15 
16 /*
17  * Helper program for posix_spawn tests. This is exec()d by the test programs
18  * via posix_spawn() and reports back process state through stdout (which the
19  * parent has wired to a pipe via file actions).
20  *
21  * Usage:
22  *   posix_spawn_child fds <fd0> [fd1 ...]
23  *     Report whether each fd is open and its access mode flags.
24  *
25  *   posix_spawn_child ids
26  *     Report uid, euid, gid, egid.
27  *
28  *   posix_spawn_child sched
29  *     Report scheduling policy and priority.
30  *
31  *   posix_spawn_child sidpgid
32  *     Report session ID and process group ID as raw pid_t values.
33  *
34  *   posix_spawn_child sigmask
35  *     Report the current signal mask as a raw sigset_t.
36  *
37  *   posix_spawn_child sigs <sig0> [sig1 ...]
38  *     Report the disposition (SIG_DFL or SIG_IGN) of each signal.
39  */
40 
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <sched.h>
45 #include <signal.h>
46 #include <string.h>
47 #include <errno.h>
48 
49 #include "posix_spawn_common.h"
50 
51 static int
do_fds(int argc,char * argv[])52 do_fds(int argc, char *argv[])
53 {
54 	for (int i = 2; i < argc; i++) {
55 		spawn_fd_result_t res;
56 		int fd = (int)strtol(argv[i], NULL, 10);
57 		int flags;
58 
59 		(void) memset(&res, 0, sizeof (res));
60 		res.srf_fd = fd;
61 
62 		flags = fcntl(fd, F_GETFL);
63 		if (flags == -1) {
64 			res.srf_open = 0;
65 			res.srf_flags = -1;
66 			res.srf_err = errno;
67 		} else {
68 			res.srf_open = 1;
69 			res.srf_flags = flags & O_ACCMODE;
70 			res.srf_err = 0;
71 		}
72 
73 		if (write(STDOUT_FILENO, &res, sizeof (res)) != sizeof (res))
74 			return (EXIT_FAILURE);
75 	}
76 
77 	return (EXIT_SUCCESS);
78 }
79 
80 static int
do_ids(void)81 do_ids(void)
82 {
83 	spawn_id_result_t res;
84 
85 	(void) memset(&res, 0, sizeof (res));
86 	res.sir_uid = getuid();
87 	res.sir_euid = geteuid();
88 	res.sir_gid = getgid();
89 	res.sir_egid = getegid();
90 
91 	if (write(STDOUT_FILENO, &res, sizeof (res)) != sizeof (res))
92 		return (EXIT_FAILURE);
93 
94 	return (EXIT_SUCCESS);
95 }
96 
97 static int
do_sched(void)98 do_sched(void)
99 {
100 	spawn_sched_result_t res;
101 	struct sched_param param;
102 
103 	(void) memset(&res, 0, sizeof (res));
104 	res.ssr_policy = sched_getscheduler(0);
105 	if (res.ssr_policy == -1)
106 		return (EXIT_FAILURE);
107 
108 	if (sched_getparam(0, &param) != 0)
109 		return (EXIT_FAILURE);
110 	res.ssr_priority = param.sched_priority;
111 
112 	if (write(STDOUT_FILENO, &res, sizeof (res)) != sizeof (res))
113 		return (EXIT_FAILURE);
114 
115 	return (EXIT_SUCCESS);
116 }
117 
118 static int
do_sidpgid(void)119 do_sidpgid(void)
120 {
121 	spawn_sidpgid_result_t res;
122 
123 	(void) memset(&res, 0, sizeof (res));
124 	res.sspr_sid = getsid(0);
125 	res.sspr_pgid = getpgid(0);
126 
127 	if (write(STDOUT_FILENO, &res, sizeof (res)) != sizeof (res))
128 		return (EXIT_FAILURE);
129 
130 	return (EXIT_SUCCESS);
131 }
132 
133 static int
do_sigmask(void)134 do_sigmask(void)
135 {
136 	sigset_t mask;
137 
138 	if (sigprocmask(SIG_BLOCK, NULL, &mask) != 0)
139 		return (EXIT_FAILURE);
140 
141 	if (write(STDOUT_FILENO, &mask, sizeof (mask)) != sizeof (mask))
142 		return (EXIT_FAILURE);
143 
144 	return (EXIT_SUCCESS);
145 }
146 
147 static int
do_sigs(int argc,char * argv[])148 do_sigs(int argc, char *argv[])
149 {
150 	for (int i = 2; i < argc; i++) {
151 		spawn_sig_result_t res;
152 		struct sigaction sa;
153 		int sig = (int)strtol(argv[i], NULL, 10);
154 
155 		(void) memset(&res, 0, sizeof (res));
156 		res.ssr_sig = sig;
157 
158 		if (sigaction(sig, NULL, &sa) != 0)
159 			return (EXIT_FAILURE);
160 
161 		if (sa.sa_handler == SIG_DFL)
162 			res.ssr_disp = 0;
163 		else if (sa.sa_handler == SIG_IGN)
164 			res.ssr_disp = 1;
165 		else
166 			res.ssr_disp = 2;
167 
168 		if (write(STDOUT_FILENO, &res, sizeof (res)) != sizeof (res))
169 			return (EXIT_FAILURE);
170 	}
171 
172 	return (EXIT_SUCCESS);
173 }
174 
175 int
main(int argc,char * argv[])176 main(int argc, char *argv[])
177 {
178 	if (argc < 2)
179 		return (EXIT_FAILURE);
180 
181 	if (strcmp(argv[1], "fds") == 0) {
182 		if (argc < 3)
183 			return (EXIT_FAILURE);
184 		return (do_fds(argc, argv));
185 	}
186 
187 	if (strcmp(argv[1], "ids") == 0)
188 		return (do_ids());
189 
190 	if (strcmp(argv[1], "sched") == 0)
191 		return (do_sched());
192 
193 	if (strcmp(argv[1], "sidpgid") == 0)
194 		return (do_sidpgid());
195 
196 	if (strcmp(argv[1], "sigmask") == 0)
197 		return (do_sigmask());
198 
199 	if (strcmp(argv[1], "sigs") == 0) {
200 		if (argc < 3)
201 			return (EXIT_FAILURE);
202 		return (do_sigs(argc, argv));
203 	}
204 
205 	return (EXIT_FAILURE);
206 }
207