1*36b1b8b4Svisa /* $OpenBSD: sigio.c,v 1.5 2020/01/08 16:27:40 visa Exp $ */
27d954e70Santon
37d954e70Santon /*
47d954e70Santon * Copyright (c) 2018 Anton Lindqvist <anton@openbsd.org>
57d954e70Santon *
67d954e70Santon * Permission to use, copy, modify, and distribute this software for any
77d954e70Santon * purpose with or without fee is hereby granted, provided that the above
87d954e70Santon * copyright notice and this permission notice appear in all copies.
97d954e70Santon *
107d954e70Santon * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
117d954e70Santon * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
127d954e70Santon * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
137d954e70Santon * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
147d954e70Santon * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
157d954e70Santon * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
167d954e70Santon * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
177d954e70Santon */
187d954e70Santon
197d954e70Santon #include <sys/ioctl.h>
207d954e70Santon #include <sys/time.h>
217d954e70Santon #include <sys/wait.h>
227d954e70Santon
237d954e70Santon #include <dev/wscons/wsconsio.h>
247d954e70Santon
257d954e70Santon #include <err.h>
267d954e70Santon #include <fcntl.h>
277d954e70Santon #include <signal.h>
287d954e70Santon #include <stdlib.h>
297d954e70Santon #include <string.h>
307d954e70Santon #include <unistd.h>
317d954e70Santon
32a83a5986Santon #include "util.h"
33a83a5986Santon
344319b3fdSanton static int test_getown_fcntl(int);
354319b3fdSanton static int test_getown_ioctl(int);
364319b3fdSanton static int test_gpgrp(int);
37169d0bb4Santon static int test_setown_fcntl(int);
38169d0bb4Santon static int test_setown_ioctl(int);
397d954e70Santon static int test_sigio(int);
407d954e70Santon static int test_spgrp(int);
417d954e70Santon
424319b3fdSanton static int test_common_getown(int, int);
43169d0bb4Santon static int test_common_setown(int, int);
44169d0bb4Santon
457d954e70Santon static void sigio(int);
467d954e70Santon static void syncrecv(int, int);
477d954e70Santon static void syncsend(int, int);
487d954e70Santon
497d954e70Santon static volatile sig_atomic_t nsigio;
507d954e70Santon
517d954e70Santon static int
test_getown_fcntl(int fd)524319b3fdSanton test_getown_fcntl(int fd)
534319b3fdSanton {
544319b3fdSanton return test_common_getown(fd, 1);
554319b3fdSanton }
564319b3fdSanton
574319b3fdSanton static int
test_getown_ioctl(int fd)584319b3fdSanton test_getown_ioctl(int fd)
594319b3fdSanton {
604319b3fdSanton return test_common_getown(fd, 0);
614319b3fdSanton }
624319b3fdSanton
634319b3fdSanton static int
test_gpgrp(int fd)644319b3fdSanton test_gpgrp(int fd)
654319b3fdSanton {
664319b3fdSanton int arg, pgrp;
674319b3fdSanton
684319b3fdSanton if (ioctl(fd, TIOCGPGRP, &pgrp) == -1)
694319b3fdSanton err(1, "ioctl: TIOCGPGRP");
704319b3fdSanton if (pgrp != 0)
714319b3fdSanton errx(1, "ioctl: TIOCGPGRP: expected 0, got %d", pgrp);
724319b3fdSanton
734319b3fdSanton arg = getpgrp();
744319b3fdSanton if (ioctl(fd, TIOCSPGRP, &arg) == -1)
754319b3fdSanton err(1, "ioctl: TIOCSPGRP");
764319b3fdSanton if (ioctl(fd, TIOCGPGRP, &pgrp) == -1)
774319b3fdSanton err(1, "ioctl: TIOCGPGRP");
784319b3fdSanton if (pgrp != getpgrp())
794319b3fdSanton errx(1, "ioctl: TIOCGPGRP: expected %d, got %d", getpgrp(), pgrp);
804319b3fdSanton
814319b3fdSanton return 0;
824319b3fdSanton }
834319b3fdSanton
844319b3fdSanton static int
test_setown_fcntl(int fd)85169d0bb4Santon test_setown_fcntl(int fd)
867d954e70Santon {
87169d0bb4Santon return test_common_setown(fd, 1);
88169d0bb4Santon }
897d954e70Santon
90169d0bb4Santon static int
test_setown_ioctl(int fd)91169d0bb4Santon test_setown_ioctl(int fd)
92169d0bb4Santon {
93169d0bb4Santon return test_common_setown(fd, 0);
947d954e70Santon }
957d954e70Santon
967d954e70Santon static int
test_sigio(int fd)977d954e70Santon test_sigio(int fd)
987d954e70Santon {
997d954e70Santon struct wscons_event ev;
1007d954e70Santon int cfd[2], pfd[2];
1017d954e70Santon ssize_t n;
1027d954e70Santon pid_t pid;
1037d954e70Santon int arg, len, status;
1047d954e70Santon
1057d954e70Santon if (pipe(cfd) == -1)
1067d954e70Santon err(1, "pipe");
1077d954e70Santon if (pipe(pfd) == -1)
1087d954e70Santon err(1, "pipe");
1097d954e70Santon
1107d954e70Santon arg = getpid();
1117d954e70Santon if (ioctl(fd, FIOSETOWN, &arg) == -1)
1127d954e70Santon err(1, "ioctl: FIOSETOWN");
1137d954e70Santon
1147d954e70Santon /* Enable async IO. */
1157d954e70Santon arg = 1;
1167d954e70Santon if (ioctl(fd, FIOASYNC, &arg) == -1)
1177d954e70Santon err(1, "ioctl: FIOASYNC");
1187d954e70Santon
1197d954e70Santon pid = fork();
1207d954e70Santon if (pid == -1)
1217d954e70Santon err(1, "fork");
1227d954e70Santon if (pid == 0) {
1237d954e70Santon close(cfd[1]);
1247d954e70Santon close(pfd[0]);
1257d954e70Santon
1267d954e70Santon syncsend(pfd[1], 1);
1277d954e70Santon syncrecv(cfd[0], 2);
1287d954e70Santon
1297d954e70Santon memset(&ev, 0, sizeof(ev));
1307d954e70Santon if (ioctl(fd, WSMUXIO_INJECTEVENT, &ev) == -1)
1317d954e70Santon err(1, "ioctl: WSMUXIO_INJECTEVENT");
1327d954e70Santon
1337d954e70Santon close(cfd[0]);
1347d954e70Santon close(pfd[1]);
1357d954e70Santon _exit(0);
1367d954e70Santon }
1377d954e70Santon close(cfd[0]);
1387d954e70Santon close(pfd[1]);
1397d954e70Santon
1407d954e70Santon syncrecv(pfd[0], 1);
1417d954e70Santon
1427d954e70Santon if (signal(SIGIO, sigio) == SIG_ERR)
1437d954e70Santon err(1, "signal");
1447d954e70Santon
1457d954e70Santon syncsend(cfd[1], 2);
1467d954e70Santon
1477d954e70Santon if (waitpid(pid, &status, 0) == -1)
1487d954e70Santon err(1, "waitpid");
1497d954e70Santon if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
1507d954e70Santon errx(1, "child exited %d", WEXITSTATUS(status));
1517d954e70Santon if (WIFSIGNALED(status))
1527d954e70Santon errx(1, "child killed by signal %d", WTERMSIG(status));
1537d954e70Santon
1547d954e70Santon if (nsigio != 1)
1557d954e70Santon errx(1, "expected SIGIO to be received once, got %d", nsigio);
1567d954e70Santon
1577d954e70Santon len = sizeof(ev);
1587d954e70Santon n = read(fd, &ev, len);
1597d954e70Santon if (n == -1)
1607d954e70Santon err(1, "read");
1617d954e70Santon if (n != len)
1627d954e70Santon errx(1, "read: expected %d bytes, got %ld", len, n);
1637d954e70Santon
1647d954e70Santon /* Disable async IO. */
1657d954e70Santon arg = 0;
1667d954e70Santon if (ioctl(fd, FIOASYNC, &arg) == -1)
1677d954e70Santon err(1, "ioctl: FIOASYNC");
1687d954e70Santon
1697d954e70Santon return 0;
1707d954e70Santon }
1717d954e70Santon
1727d954e70Santon static int
test_spgrp(int fd)1737d954e70Santon test_spgrp(int fd)
1747d954e70Santon {
1757d954e70Santon int arg;
1767d954e70Santon
1777d954e70Santon /* The process group must be able to receive SIGIO. */
1787d954e70Santon arg = getpgrp();
1797d954e70Santon if (ioctl(fd, TIOCSPGRP, &arg) == -1)
1807d954e70Santon errx(1, "ioctl: TIOCSPGRP");
1817d954e70Santon
1827d954e70Santon /* Bogus process groups must be rejected. */
1837d954e70Santon arg = -getpgrp();
1847d954e70Santon if (ioctl(fd, TIOCSPGRP, &arg) != -1)
1857d954e70Santon errx(1, "ioctl: TIOCSPGRP: %d accepted", arg);
1867d954e70Santon arg = 1000000;
1877d954e70Santon if (ioctl(fd, TIOCSPGRP, &arg) != -1)
1887d954e70Santon errx(1, "ioctl: TIOCSPGRP: %d accepted", arg);
1897d954e70Santon
1907d954e70Santon return 0;
1917d954e70Santon }
1927d954e70Santon
193169d0bb4Santon static int
test_common_getown(int fd,int dofcntl)1944319b3fdSanton test_common_getown(int fd, int dofcntl)
1954319b3fdSanton {
1964319b3fdSanton int arg, pgrp;
1974319b3fdSanton
1984319b3fdSanton if (dofcntl) {
1994319b3fdSanton pgrp = fcntl(fd, F_GETOWN);
2004319b3fdSanton if (pgrp == -1)
2014319b3fdSanton err(1, "fcntl: F_GETOWN");
2024319b3fdSanton if (pgrp != 0)
2034319b3fdSanton errx(1, "fcntl: F_GETOWN: expected 0, got %d", pgrp);
2044319b3fdSanton } else {
2054319b3fdSanton if (ioctl(fd, FIOGETOWN, &pgrp) == -1)
2064319b3fdSanton err(1, "ioctl: FIOGETOWN");
2074319b3fdSanton if (pgrp != 0)
2084319b3fdSanton errx(1, "ioctl: FIOGETOWN: expected 0, got %d", pgrp);
2094319b3fdSanton }
2104319b3fdSanton
211*36b1b8b4Svisa arg = -getpgrp();
2124319b3fdSanton if (ioctl(fd, FIOSETOWN, &arg) == -1)
2134319b3fdSanton err(1, "ioctl: FIOSETOWN");
2144319b3fdSanton if (dofcntl) {
2154319b3fdSanton pgrp = fcntl(fd, F_GETOWN);
2164319b3fdSanton if (pgrp == -1)
2174319b3fdSanton err(1, "fcntl: F_GETOWN");
2184319b3fdSanton if (pgrp != -getpgrp())
2194319b3fdSanton errx(1, "fcntl: F_GETOWN: expected %d, got %d",
2204319b3fdSanton -getpgrp(), pgrp);
2214319b3fdSanton } else {
2224319b3fdSanton if (ioctl(fd, FIOGETOWN, &pgrp) == -1)
2234319b3fdSanton err(1, "ioctl: FIOGETOWN");
2244319b3fdSanton if (pgrp != -getpgrp())
2254319b3fdSanton errx(1, "ioctl: FIOGETOWN: expected %d, got %d",
2264319b3fdSanton -getpgrp(), pgrp);
2274319b3fdSanton }
2284319b3fdSanton
2294319b3fdSanton return 0;
2304319b3fdSanton }
2314319b3fdSanton
2324319b3fdSanton static int
test_common_setown(int fd,int dofcntl)233169d0bb4Santon test_common_setown(int fd, int dofcntl)
234169d0bb4Santon {
235169d0bb4Santon int arg;
236169d0bb4Santon
237169d0bb4Santon /* The process must be able to receive SIGIO. */
238169d0bb4Santon arg = getpid();
239169d0bb4Santon if (dofcntl) {
240169d0bb4Santon if (fcntl(fd, F_SETOWN, arg) == -1)
241169d0bb4Santon errx(1, "fcntl: F_SETOWN: process rejected");
242169d0bb4Santon } else {
243169d0bb4Santon if (ioctl(fd, FIOSETOWN, &arg) == -1)
244169d0bb4Santon errx(1, "ioctl: FIOSETOWN: process rejected");
245169d0bb4Santon }
246169d0bb4Santon
247169d0bb4Santon /* The process group must be able to receive SIGIO. */
248169d0bb4Santon arg = -getpgrp();
249169d0bb4Santon if (dofcntl) {
250169d0bb4Santon if (fcntl(fd, F_SETOWN, arg) == -1)
251169d0bb4Santon errx(1, "fcntl: F_SETOWN: process group rejected");
252169d0bb4Santon } else {
253169d0bb4Santon if (ioctl(fd, FIOSETOWN, &arg) == -1)
254169d0bb4Santon errx(1, "ioctl: FIOSETOWN: process group rejected");
255169d0bb4Santon }
256169d0bb4Santon
257169d0bb4Santon /* A bogus process must be rejected. */
258169d0bb4Santon arg = 1000000;
259169d0bb4Santon if (dofcntl) {
260169d0bb4Santon if (fcntl(fd, F_SETOWN, arg) != -1)
261169d0bb4Santon errx(1, "fcntl: F_SETOWN: bogus process accepted");
262169d0bb4Santon } else {
263169d0bb4Santon if (ioctl(fd, FIOSETOWN, &arg) != -1)
264169d0bb4Santon errx(1, "ioctl: FIOSETOWN: bogus process accepted");
265169d0bb4Santon }
266169d0bb4Santon
267169d0bb4Santon /* A bogus process group must be rejected. */
268169d0bb4Santon arg = -1000000;
269169d0bb4Santon if (dofcntl) {
270169d0bb4Santon if (fcntl(fd, F_SETOWN, arg) != -1)
271169d0bb4Santon errx(1, "fcntl: F_SETOWN: bogus process group accepted");
272169d0bb4Santon } else {
273169d0bb4Santon if (ioctl(fd, FIOSETOWN, &arg) != -1)
274169d0bb4Santon errx(1, "ioctl: FIOSETOWN: bogus process group accepted");
275169d0bb4Santon }
276169d0bb4Santon
277169d0bb4Santon return 0;
278169d0bb4Santon }
279169d0bb4Santon
2807d954e70Santon static void
sigio(int signo)2817d954e70Santon sigio(int signo)
2827d954e70Santon {
2837d954e70Santon nsigio++;
2847d954e70Santon }
2857d954e70Santon
2867d954e70Santon static void
syncrecv(int fd,int id)2877d954e70Santon syncrecv(int fd, int id)
2887d954e70Santon {
2897d954e70Santon int r;
2907d954e70Santon
2917d954e70Santon if (read(fd, &r, sizeof(r)) == -1)
2927d954e70Santon err(1, "%s: read", __func__);
2937d954e70Santon if (r != id)
2947d954e70Santon errx(1, "%s: expected %d, got %d", __func__, id, r);
2957d954e70Santon }
2967d954e70Santon
2977d954e70Santon static void
syncsend(int fd,int id)2987d954e70Santon syncsend(int fd, int id)
2997d954e70Santon {
3007d954e70Santon if (write(fd, &id, sizeof(id)) == -1)
3017d954e70Santon err(1, "%s: write", __func__);
3027d954e70Santon }
3037d954e70Santon
304a83a5986Santon int
main(int argc,char * argv[])305a83a5986Santon main(int argc, char *argv[])
3067d954e70Santon {
307a83a5986Santon struct test tests[] = {
308a83a5986Santon { "getown-fcntl", test_getown_fcntl },
309a83a5986Santon { "getown-ioctl", test_getown_ioctl },
310a83a5986Santon { "gpgrp", test_gpgrp },
311a83a5986Santon { "setown-fcntl", test_setown_fcntl },
312a83a5986Santon { "setown-ioctl", test_setown_ioctl },
313a83a5986Santon { "sigio", test_sigio },
314a83a5986Santon { "spgrp", test_spgrp },
315a83a5986Santon { NULL, NULL },
316a83a5986Santon };
317a83a5986Santon
318a83a5986Santon return dotest(argc, argv, tests);
3197d954e70Santon }
320