xref: /openbsd-src/regress/sys/kern/kqueue/kqueue-pty.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: kqueue-pty.c,v 1.6 2015/08/13 10:11:38 uebayasi Exp $	*/
2 
3 /*	Written by Michael Shalayeff, 2003, Public Domain	*/
4 
5 #include <sys/types.h>
6 #include <sys/time.h>
7 #include <sys/event.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <util.h>
11 #include <termios.h>
12 #include <fcntl.h>
13 #include <err.h>
14 #include <string.h>
15 
16 static int
17 pty_check(int kq, struct kevent *ev, int n, int rm, int rs, int wm, int ws)
18 {
19 	struct timespec ts;
20 	int i;
21 
22 	ts.tv_sec = 0;
23 	ts.tv_nsec = 0;
24 	if ((n = kevent(kq, NULL, 0, ev, n, &ts)) < 0)
25 		err(1, "slave: kevent");
26 
27 	if (n == 0)
28 		return (1);
29 
30 	for (i = 0; i < n; i++, ev++) {
31 		if (ev->filter == EVFILT_READ) {
32 			if (rm < 0 && ev->ident == -rm)
33 				return (1);
34 			if (rs < 0 && ev->ident == -rs)
35 				return (1);
36 		} else if (ev->filter == EVFILT_WRITE) {
37 			if (wm < 0 && ev->ident == -wm)
38 				return (1);
39 			if (ws < 0 && ev->ident == -ws)
40 				return (1);
41 		} else
42 			errx(1, "unknown event");
43 	}
44 
45 	return (0);
46 }
47 
48 int do_pty(void);
49 
50 int
51 do_pty(void)
52 {
53 	struct kevent ev[4];
54 	struct termios tt;
55 	int kq, massa, slave;
56 	char buf[1024];
57 
58 	tcgetattr(STDIN_FILENO, &tt);
59 	cfmakeraw(&tt);
60 	tt.c_lflag &= ~ECHO;
61 	if (openpty(&massa, &slave, NULL, &tt, NULL) < 0)
62 		err(1, "openpty");
63 	if (fcntl(massa, F_SETFL, O_NONBLOCK) < 0)
64 		err(1, "massa: fcntl");
65 	if (fcntl(slave, F_SETFL, O_NONBLOCK) < 0)
66 		err(1, "massa: fcntl");
67 	if ((kq = kqueue()) == -1)
68 		err(1, "kqueue");
69 
70 	/* test the read from the slave works */
71 	EV_SET(&ev[0], massa, EVFILT_READ,  EV_ADD|EV_ENABLE, 0, 0, NULL);
72 	EV_SET(&ev[1], massa, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, NULL);
73 	EV_SET(&ev[2], slave, EVFILT_READ,  EV_ADD|EV_ENABLE, 0, 0, NULL);
74 	EV_SET(&ev[3], slave, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, NULL);
75 	if (kevent(kq, ev, 4, NULL, 0, NULL) < 0)
76 		err(1, "slave: kevent add");
77 
78 	memset(buf, 0, sizeof buf);
79 
80 	if (write(massa, " ", 1) != 1)
81 		err(1, "massa: write");
82 
83 	if (pty_check(kq, ev, 4, -massa, slave, massa, slave))
84 		return (1);
85 
86 	read(slave, buf, sizeof(buf));
87 
88 	if (pty_check(kq, ev, 4, -massa, -slave, massa, slave))
89 		return (1);
90 
91 	while (write(massa, buf, sizeof(buf)) > 0)
92 		continue;
93 
94 	if (pty_check(kq, ev, 4, -massa, slave, -massa, slave))
95 		return (1);
96 
97 	read(slave, buf, 1);
98 
99 	if (pty_check(kq, ev, 4, -massa, slave, massa, slave))
100 		return (1);
101 
102 	while (read(slave, buf, sizeof(buf)) > 0)
103 		continue;
104 
105 	if (pty_check(kq, ev, 4, -massa, -slave, massa, slave))
106 		return (1);
107 
108 	return (0);
109 }
110