xref: /openbsd-src/regress/sys/kern/kqueue/kqueue-pty.c (revision 0df5504e01e3ff46ff45e5d4f08baef5372ff7f4)
1 /*	$OpenBSD: kqueue-pty.c,v 1.10 2019/03/04 19:35:28 anton 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 
9 #include <err.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <termios.h>
14 #include <unistd.h>
15 #include <util.h>
16 
17 #include "main.h"
18 
19 static int
pty_check(int kq,struct kevent * ev,int n,int rm,int rs,int wm,int ws)20 pty_check(int kq, struct kevent *ev, int n, int rm, int rs, int wm, int ws)
21 {
22 	struct timespec ts;
23 	int i;
24 
25 	ts.tv_sec = 0;
26 	ts.tv_nsec = 0;
27 	if ((n = kevent(kq, NULL, 0, ev, n, &ts)) < 0)
28 		err(1, "slave: kevent");
29 
30 	ASSX(n != 0);
31 
32 	for (i = 0; i < n; i++, ev++) {
33 		if (ev->filter == EVFILT_READ) {
34 			ASSX(ev->ident != -rm);
35 			ASSX(ev->ident != -rs);
36 			if (ev->ident == rm)
37 				rm = 0;
38 			if (ev->ident == rs)
39 				rs = 0;
40 		} else if (ev->filter == EVFILT_WRITE) {
41 			ASSX(ev->ident != -wm);
42 			ASSX(ev->ident != -ws);
43 			if (ev->ident == wm)
44 				wm = 0;
45 			if (ev->ident == ws)
46 				ws = 0;
47 		} else
48 			errx(1, "unknown event");
49 	}
50 	ASSX(rm <= 0);
51 	ASSX(rs <= 0);
52 	ASSX(wm <= 0);
53 	ASSX(ws <= 0);
54 
55 	return (0);
56 }
57 
58 static int
pty_rdrw(void)59 pty_rdrw(void)
60 {
61 	struct kevent ev[4];
62 	struct termios tt;
63 	int fd, kq, massa, slave;
64 	char buf[1024];
65 
66 	ASS((fd = open("/dev/console", O_RDONLY, &tt)) > 0,
67 	    warn("open /dev/console"));
68 	ASS(tcgetattr(fd, &tt) == 0,
69 	    warn("tcgetattr"));
70 	cfmakeraw(&tt);
71 	tt.c_lflag &= ~ECHO;
72 	if (openpty(&massa, &slave, NULL, &tt, NULL) < 0)
73 		err(1, "openpty");
74 	if (fcntl(massa, F_SETFL, O_NONBLOCK) < 0)
75 		err(1, "massa: fcntl");
76 	if (fcntl(slave, F_SETFL, O_NONBLOCK) < 0)
77 		err(1, "massa: fcntl");
78 	if ((kq = kqueue()) == -1)
79 		err(1, "kqueue");
80 
81 	/* test the read from the slave works */
82 	EV_SET(&ev[0], massa, EVFILT_READ,  EV_ADD|EV_ENABLE, 0, 0, NULL);
83 	EV_SET(&ev[1], massa, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, NULL);
84 	EV_SET(&ev[2], slave, EVFILT_READ,  EV_ADD|EV_ENABLE, 0, 0, NULL);
85 	EV_SET(&ev[3], slave, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, NULL);
86 	if (kevent(kq, ev, 4, NULL, 0, NULL) < 0)
87 		err(1, "slave: kevent add");
88 
89 	memset(buf, 0, sizeof(buf));
90 
91 	ASSX(pty_check(kq, ev, 4, -massa, -slave, massa, slave) == 0);
92 
93 	if (write(massa, " ", 1) != 1)
94 		err(1, "massa: write");
95 
96 	ASSX(pty_check(kq, ev, 4, -massa, slave, massa, slave) == 0);
97 
98 	read(slave, buf, sizeof(buf));
99 
100 	ASSX(pty_check(kq, ev, 4, -massa, -slave, massa, slave) == 0);
101 
102 	while (write(massa, buf, sizeof(buf)) > 0)
103 		continue;
104 
105 	ASSX(pty_check(kq, ev, 4, -massa, slave, -massa, slave) == 0);
106 
107 	read(slave, buf, 1);
108 
109 	ASSX(pty_check(kq, ev, 4, -massa, slave, massa, slave) == 0);
110 
111 	while (read(slave, buf, sizeof(buf)) > 0)
112 		continue;
113 
114 	ASSX(pty_check(kq, ev, 4, -massa, -slave, massa, slave) == 0);
115 
116 	return (0);
117 }
118 
119 static int
pty_close(void)120 pty_close(void)
121 {
122 	struct kevent ev[1];
123 	struct timespec ts;
124 	int kq, massa, n, slave;
125 
126 	if (openpty(&massa, &slave, NULL, NULL, NULL) == -1)
127 		err(1, "openpty");
128 
129 	kq = kqueue();
130 	if (kq == -1)
131 		err(1, "kqueue");
132 
133 	EV_SET(&ev[0], massa, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, NULL);
134 	if (kevent(kq, ev, 1, NULL, 0, NULL) == -1)
135 		err(1, "kevent: add");
136 
137 	close(slave);
138 
139 	ts.tv_sec = 5;
140 	ts.tv_nsec = 0;
141 	n = kevent(kq, NULL, 0, ev, 1, &ts);
142 	ASSX(n == 1);
143 	ASSX(ev[0].filter == EVFILT_READ);
144 	ASSX(ev[0].flags & EV_EOF);
145 
146 	return 0;
147 }
148 
149 int
do_pty(int n)150 do_pty(int n)
151 {
152 	switch (n) {
153 	case 1:
154 		return pty_rdrw();
155 	case 2:
156 		return pty_close();
157 	default:
158 		errx(1, "unknown pty test number %d", n);
159 	}
160 }
161