xref: /openbsd/regress/lib/libc/sys/t_wait_noproc.c (revision 76d0caae)
1 /*	$OpenBSD: t_wait_noproc.c,v 1.2 2021/12/13 16:56:48 deraadt Exp $	*/
2 /* $NetBSD: t_wait_noproc.c,v 1.5 2016/11/09 17:50:19 kamil Exp $ */
3 
4 /*-
5  * Copyright (c) 2016 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "macros.h"
31 
32 #include <sys/wait.h>
33 #include <sys/resource.h>
34 
35 #include <errno.h>
36 #include <stdio.h>
37 
38 #include "atf-c.h"
39 
40 #ifndef TWAIT_OPTION
41 #define TWAIT_OPTION 0
42 #endif
43 
44 #if TWAIT_OPTION == 0
45 ATF_TC(wait);
46 ATF_TC_HEAD(wait, tc)
47 {
48 	atf_tc_set_md_var(tc, "descr",
49 	    "Test that wait(2) returns ECHILD for no child");
50 }
51 
52 ATF_TC_BODY(wait, tc)
53 {
54 	ATF_REQUIRE_ERRNO(ECHILD, wait(NULL) == -1);
55 }
56 #endif
57 
58 ATF_TC(waitpid);
59 ATF_TC_HEAD(waitpid, tc)
60 {
61 	atf_tc_set_md_var(tc, "descr",
62 	    "Test that waitpid(2) returns ECHILD for WAIT_ANY and option %s",
63 	    ___STRING(TWAIT_OPTION));
64 }
65 
66 ATF_TC_BODY(waitpid, tc)
67 {
68 	ATF_REQUIRE_ERRNO(ECHILD, waitpid(WAIT_ANY, NULL, TWAIT_OPTION) == -1);
69 }
70 
71 #ifndef __OpenBSD__
72 ATF_TC(waitid);
73 ATF_TC_HEAD(waitid, tc)
74 {
75 	atf_tc_set_md_var(tc, "descr",
76 	    "Test that waitid(2) returns ECHILD for P_ALL and option %s",
77 	    ___STRING(TWAIT_OPTION));
78 }
79 
80 ATF_TC_BODY(waitid, tc)
81 {
82 	ATF_REQUIRE_ERRNO(ECHILD,
83 	    waitid(P_ALL, 0, NULL,
84 	        WTRAPPED | WEXITED | TWAIT_OPTION) == -1);
85 }
86 #endif
87 
88 ATF_TC(wait3);
89 ATF_TC_HEAD(wait3, tc)
90 {
91 	atf_tc_set_md_var(tc, "descr",
92 	    "Test that wait3(2) returns ECHILD for no child");
93 }
94 
95 ATF_TC_BODY(wait3, tc)
96 {
97 	ATF_REQUIRE_ERRNO(ECHILD, wait3(NULL, TWAIT_OPTION, NULL) == -1);
98 }
99 
100 ATF_TC(wait4);
101 ATF_TC_HEAD(wait4, tc)
102 {
103 	atf_tc_set_md_var(tc, "descr",
104 	    "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
105 	    ___STRING(TWAIT_OPTION));
106 }
107 
108 ATF_TC_BODY(wait4, tc)
109 {
110 	ATF_REQUIRE_ERRNO(ECHILD,
111 	    wait4(WAIT_ANY, NULL, TWAIT_OPTION, NULL) == -1);
112 }
113 
114 #ifndef __OpenBSD__
115  * Adjusted for OpenBSD, not available
116  * ATF_TC(wait6);
117  * ATF_TC_HEAD(wait6, tc)
118  * {
119  * 	atf_tc_set_md_var(tc, "descr",
120  * 	    "Test that wait6(2) returns ECHILD for P_ALL and option %s",
121  * 	    ___STRING(TWAIT_OPTION));
122  * }
123  *
124  * ATF_TC_BODY(wait6, tc)
125  * {
126  * 	ATF_REQUIRE_ERRNO(ECHILD,
127  * 	    wait6(P_ALL, 0, NULL,
128  * 	        WTRAPPED | WEXITED | TWAIT_OPTION, NULL, NULL) == -1);
129  * }
130  */
131 
132 /*
133  * Generator of valid combinations of options
134  * Usage: i = 0; while ((o = get_options_wait6(i++)) != -1) {}
135  */
136 static int
137 get_options6(size_t pos)
138 {
139 	int rv = 0;
140 	size_t n;
141 	/*
142 	 * waitid(2) must specify at least one of WEXITED, WUNTRACED,
143 	 * WSTOPPED, WTRAPPED or WCONTINUED. Single option WNOWAIT
144 	 * isn't valid.
145 	 */
146 	const int matrix[] = {
147 		WNOWAIT,	// First in order to blacklist it easily
148 		WEXITED,
149 		WUNTRACED,
150 		WSTOPPED,	// SUS compatibility, equal to WUNTRACED
151 		WTRAPPED,
152 		WCONTINUED
153 	};
154 
155 	const size_t M = (1 << __arraycount(matrix)) - 1;
156 	/* Skip empty and sole WNOWAIT option */
157 	pos+=2;
158 
159 	if (pos > M)
160 		return -1;
161 
162 	for (n = 0; n < __arraycount(matrix); n++) {
163 		if (pos & __BIT(n))
164 			rv |= matrix[n];
165 	}
166 
167 	return rv;
168 }
169 #endif
170 
171 /*
172  * Generator of valid combinations of options
173  * Usage: i = 0; while ((o = get_options_wait4(i++)) != -1) {}
174  */
175 static int
176 get_options4(size_t pos)
177 {
178 	int rv = 0;
179 	size_t n;
180 
181 	const int special[] = {
182 		0,
183 #ifndef __OpenBSD__
184 		WALLSIG,
185 		WALTSIG,
186 		__WALL,		// Linux compatibility, equal to WALLSIG
187 		__WCLONE	// Linux compatibility, equal to WALTSIG
188 #endif
189 	};
190 
191 	const int matrix[] = {
192 #ifndef __OpenBSD__
193 		WNOWAIT,
194 		WEXITED,
195 #endif
196 		WUNTRACED,
197 #ifndef __OpenBSD__
198 		WSTOPPED,	// SUS compatibility, equal to WUNTRACED
199 		WTRAPPED,
200 #endif
201 		WCONTINUED
202 	};
203 
204 	const size_t M = (1 << __arraycount(special)) - 1;
205 
206 	if (pos < __arraycount(special))
207 		return special[pos];
208 
209 	pos -= __arraycount(special);
210 
211 	++pos; /* Don't start with empty mask */
212 
213 	if (pos > M)
214 		return -1;
215 
216 	for (n = 0; n < __arraycount(special); n++) {
217 		if (pos & __BIT(n))
218 			rv |= matrix[n];
219 	}
220 
221 	return rv;
222 }
223 
224 ATF_TC(waitpid_options);
225 ATF_TC_HEAD(waitpid_options, tc)
226 {
227 	atf_tc_set_md_var(tc, "descr",
228 	    "Test that waitpid(2) returns ECHILD for WAIT_ANY and valid "
229 	    "combination of options with%s WNOHANG",
230 	    TWAIT_OPTION == 0 ? "out" : "");
231 }
232 
233 ATF_TC_BODY(waitpid_options, tc)
234 {
235 	size_t i = 0;
236 	int o;
237 
238 	while((o = get_options4(i++)) != -1) {
239 		printf("Testing waitpid(2) with options %x\n", o);
240 
241 		ATF_REQUIRE_ERRNO(ECHILD,
242 		    waitpid(WAIT_ANY, NULL, o | TWAIT_OPTION) == -1);
243 	}
244 }
245 
246 #ifndef __OpenBSD__
247 ATF_TC(waitid_options);
248 ATF_TC_HEAD(waitid_options, tc)
249 {
250 	atf_tc_set_md_var(tc, "descr",
251 	    "Test that waitid(2) returns ECHILD for P_ALL and valid "
252 	    "combination of options with%s WNOHANG",
253 	    TWAIT_OPTION == 0 ? "out" : "");
254 }
255 
256 ATF_TC_BODY(waitid_options, tc)
257 {
258 	size_t i = 0;
259 	int o;
260 
261 	while((o = get_options6(i++)) != -1) {
262 		printf("Testing waitid(2) with options %x\n", o);
263 
264 		ATF_REQUIRE_ERRNO(ECHILD,
265 		    waitid(P_ALL, 0, NULL, o | TWAIT_OPTION) == -1);
266 	}
267 }
268 #endif
269 
270 ATF_TC(wait3_options);
271 ATF_TC_HEAD(wait3_options, tc)
272 {
273 	atf_tc_set_md_var(tc, "descr",
274 	    "Test that wait3(2) returns ECHILD for no child");
275 }
276 
277 ATF_TC_BODY(wait3_options, tc)
278 {
279 	size_t i = 0;
280 	int o;
281 
282 	while((o = get_options4(i++)) != -1) {
283 		printf("Testing wait3(2) with options %x\n", o);
284 
285 		ATF_REQUIRE_ERRNO(ECHILD,
286 		    wait3(NULL, o | TWAIT_OPTION, NULL) == -1);
287 	}
288 }
289 
290 ATF_TC(wait4_options);
291 ATF_TC_HEAD(wait4_options, tc)
292 {
293 	atf_tc_set_md_var(tc, "descr",
294 	    "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
295 	    ___STRING(TWAIT_OPTION));
296 }
297 
298 ATF_TC_BODY(wait4_options, tc)
299 {
300 	size_t i = 0;
301 	int o;
302 
303 	while((o = get_options4(i++)) != -1) {
304 		printf("Testing wait4(2) with options %x\n", o);
305 
306 		ATF_REQUIRE_ERRNO(ECHILD,
307 		    wait4(WAIT_ANY, NULL, o | TWAIT_OPTION, NULL) == -1);
308 	}
309 }
310 
311 #ifndef __OpenBSD__
312 ATF_TC(wait6_options);
313 ATF_TC_HEAD(wait6_options, tc)
314 {
315 	atf_tc_set_md_var(tc, "descr",
316 	    "Test that wait6(2) returns ECHILD for P_ALL and option %s",
317 	    ___STRING(TWAIT_OPTION));
318 }
319 
320 ATF_TC_BODY(wait6_options, tc)
321 {
322 	size_t i = 0;
323 	int o;
324 
325 	while((o = get_options6(i++)) != -1) {
326 		printf("Testing wait6(2) with options %x\n", o);
327 
328 		ATF_REQUIRE_ERRNO(ECHILD,
329 		    wait6(P_ALL, 0, NULL, o | TWAIT_OPTION, NULL, NULL) == -1);
330 	}
331 }
332 #endif
333 
334 ATF_TP_ADD_TCS(tp)
335 {
336 
337 #if TWAIT_OPTION == 0
338 	ATF_TP_ADD_TC(tp, wait);
339 #endif
340 	ATF_TP_ADD_TC(tp, waitpid);
341 #ifndef __OpenBSD__
342 	ATF_TP_ADD_TC(tp, waitid);
343 #endif
344 	ATF_TP_ADD_TC(tp, wait3);
345 	ATF_TP_ADD_TC(tp, wait4);
346 #ifndef __OpenBSD__
347 	ATF_TP_ADD_TC(tp, wait6);
348 #endif
349 
350 	ATF_TP_ADD_TC(tp, waitpid_options);
351 #ifndef __OpenBSD__
352 	ATF_TP_ADD_TC(tp, waitid_options);
353 #endif
354 	ATF_TP_ADD_TC(tp, wait3_options);
355 	ATF_TP_ADD_TC(tp, wait4_options);
356 #ifndef __OpenBSD__
357 	ATF_TP_ADD_TC(tp, wait6_options);
358 #endif
359 
360 	return atf_no_error();
361 }
362