xref: /openbsd-src/regress/sys/kern/kqueue/kqueue-exec.c (revision 391a0cc7e0c8423428e25d58a35438f6c9a24bfd)
1*391a0cc7Svisa /*	$OpenBSD: kqueue-exec.c,v 1.1 2023/08/20 15:19:34 visa Exp $	*/
2*391a0cc7Svisa 
3*391a0cc7Svisa /*
4*391a0cc7Svisa  * Copyright (c) 2023 Visa Hankala
5*391a0cc7Svisa  *
6*391a0cc7Svisa  * Permission to use, copy, modify, and distribute this software for any
7*391a0cc7Svisa  * purpose with or without fee is hereby granted, provided that the above
8*391a0cc7Svisa  * copyright notice and this permission notice appear in all copies.
9*391a0cc7Svisa  *
10*391a0cc7Svisa  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*391a0cc7Svisa  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*391a0cc7Svisa  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*391a0cc7Svisa  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*391a0cc7Svisa  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*391a0cc7Svisa  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*391a0cc7Svisa  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*391a0cc7Svisa  */
18*391a0cc7Svisa 
19*391a0cc7Svisa #include <sys/types.h>
20*391a0cc7Svisa #include <sys/event.h>
21*391a0cc7Svisa #include <sys/time.h>
22*391a0cc7Svisa #include <sys/wait.h>
23*391a0cc7Svisa #include <err.h>
24*391a0cc7Svisa #include <errno.h>
25*391a0cc7Svisa #include <fcntl.h>
26*391a0cc7Svisa #include <stdio.h>
27*391a0cc7Svisa #include <stdlib.h>
28*391a0cc7Svisa #include <string.h>
29*391a0cc7Svisa #include <unistd.h>
30*391a0cc7Svisa 
31*391a0cc7Svisa #include "main.h"
32*391a0cc7Svisa 
33*391a0cc7Svisa static void	do_exec_child(void);
34*391a0cc7Svisa static void	do_exec_parent(const char *, int);
35*391a0cc7Svisa 
36*391a0cc7Svisa int
do_exec(const char * argv0)37*391a0cc7Svisa do_exec(const char *argv0)
38*391a0cc7Svisa {
39*391a0cc7Svisa 	do_exec_parent(argv0, 0);
40*391a0cc7Svisa 	do_exec_parent(argv0, 1);
41*391a0cc7Svisa 	return 0;
42*391a0cc7Svisa }
43*391a0cc7Svisa 
44*391a0cc7Svisa static void
do_exec_parent(const char * argv0,int cloexec)45*391a0cc7Svisa do_exec_parent(const char *argv0, int cloexec)
46*391a0cc7Svisa {
47*391a0cc7Svisa 	char *args[] = {
48*391a0cc7Svisa 		(char *)argv0,
49*391a0cc7Svisa 		"-e",
50*391a0cc7Svisa 		NULL
51*391a0cc7Svisa 	};
52*391a0cc7Svisa 	char fdbuf[12];
53*391a0cc7Svisa 	pid_t pid;
54*391a0cc7Svisa 	int kq, status;
55*391a0cc7Svisa 
56*391a0cc7Svisa 	if (getenv("REGRESS_KQUEUE_FD") != NULL) {
57*391a0cc7Svisa 		do_exec_child();
58*391a0cc7Svisa 		_exit(0);
59*391a0cc7Svisa 	}
60*391a0cc7Svisa 
61*391a0cc7Svisa 	pid = fork();
62*391a0cc7Svisa 	if (pid == -1)
63*391a0cc7Svisa 		err(1, "fork");
64*391a0cc7Svisa 	if (pid == 0) {
65*391a0cc7Svisa 		kq = kqueue1(cloexec ? O_CLOEXEC : 0);
66*391a0cc7Svisa 		if (kq == -1)
67*391a0cc7Svisa 			err(1, "kqueue1");
68*391a0cc7Svisa 		snprintf(fdbuf, sizeof(fdbuf), "%d", kq);
69*391a0cc7Svisa 		if (setenv("REGRESS_KQUEUE_FD", fdbuf, 1) == -1)
70*391a0cc7Svisa 			err(1, "setenv");
71*391a0cc7Svisa 		if (setenv("REGRESS_KQUEUE_CLOEXEC",
72*391a0cc7Svisa 		    cloexec ? "1" : "0", 1) == -1)
73*391a0cc7Svisa 			err(1, "setenv 2");
74*391a0cc7Svisa 		execv(argv0, args);
75*391a0cc7Svisa 		err(1, "execve");
76*391a0cc7Svisa 	}
77*391a0cc7Svisa 	if (waitpid(pid, &status, 0) == -1)
78*391a0cc7Svisa 		err(1, "waitpid");
79*391a0cc7Svisa 	if (status != 0)
80*391a0cc7Svisa 		errx(1, "child failed");
81*391a0cc7Svisa }
82*391a0cc7Svisa 
83*391a0cc7Svisa static void
do_exec_child(void)84*391a0cc7Svisa do_exec_child(void)
85*391a0cc7Svisa {
86*391a0cc7Svisa 	char *arg;
87*391a0cc7Svisa 	int cloexec, fd;
88*391a0cc7Svisa 
89*391a0cc7Svisa 	arg = getenv("REGRESS_KQUEUE_FD");
90*391a0cc7Svisa 	if (arg == NULL)
91*391a0cc7Svisa 		errx(1, "fd arg is missing");
92*391a0cc7Svisa 	fd = atoi(arg);
93*391a0cc7Svisa 
94*391a0cc7Svisa 	arg = getenv("REGRESS_KQUEUE_CLOEXEC");
95*391a0cc7Svisa 	if (arg != NULL && strcmp(arg, "1") == 0)
96*391a0cc7Svisa 		cloexec = 1;
97*391a0cc7Svisa 	else
98*391a0cc7Svisa 		cloexec = 0;
99*391a0cc7Svisa 
100*391a0cc7Svisa 	if (cloexec) {
101*391a0cc7Svisa 		if (kevent(fd, NULL, 0, NULL, 0, 0) == -1) {
102*391a0cc7Svisa 			if (errno != EBADF)
103*391a0cc7Svisa 				err(1, "child after exec: kevent cloexec");
104*391a0cc7Svisa 		} else {
105*391a0cc7Svisa 			errx(1, "child after exec: "
106*391a0cc7Svisa 			    "kqueue cloexec fd is not closed");
107*391a0cc7Svisa 		}
108*391a0cc7Svisa 	} else {
109*391a0cc7Svisa 		if (kevent(fd, NULL, 0, NULL, 0, 0) == -1) {
110*391a0cc7Svisa 			err(1, "child after exec: kevent");
111*391a0cc7Svisa 		}
112*391a0cc7Svisa 	}
113*391a0cc7Svisa }
114