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