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