xref: /openbsd-src/regress/sys/kern/kqueue/kqueue-pty.c (revision 0df5504e01e3ff46ff45e5d4f08baef5372ff7f4)
1*0df5504eSanton /*	$OpenBSD: kqueue-pty.c,v 1.10 2019/03/04 19:35:28 anton Exp $	*/
257873b1bSmickey 
3e337cadcSmickey /*	Written by Michael Shalayeff, 2003, Public Domain	*/
4507ad807Smickey 
5507ad807Smickey #include <sys/types.h>
6507ad807Smickey #include <sys/time.h>
7507ad807Smickey #include <sys/event.h>
8bd35765dSbluhm 
9bd35765dSbluhm #include <err.h>
10bd35765dSbluhm #include <fcntl.h>
11507ad807Smickey #include <stdio.h>
12bd35765dSbluhm #include <string.h>
13bd35765dSbluhm #include <termios.h>
14507ad807Smickey #include <unistd.h>
15507ad807Smickey #include <util.h>
16bd35765dSbluhm 
17bd35765dSbluhm #include "main.h"
18507ad807Smickey 
19db3296cfSderaadt static int
pty_check(int kq,struct kevent * ev,int n,int rm,int rs,int wm,int ws)20507ad807Smickey pty_check(int kq, struct kevent *ev, int n, int rm, int rs, int wm, int ws)
21507ad807Smickey {
22507ad807Smickey 	struct timespec ts;
23507ad807Smickey 	int i;
24507ad807Smickey 
25507ad807Smickey 	ts.tv_sec = 0;
26507ad807Smickey 	ts.tv_nsec = 0;
27507ad807Smickey 	if ((n = kevent(kq, NULL, 0, ev, n, &ts)) < 0)
28507ad807Smickey 		err(1, "slave: kevent");
29507ad807Smickey 
30bd35765dSbluhm 	ASSX(n != 0);
31507ad807Smickey 
32507ad807Smickey 	for (i = 0; i < n; i++, ev++) {
33507ad807Smickey 		if (ev->filter == EVFILT_READ) {
3421d707c3Sbluhm 			ASSX(ev->ident != -rm);
3521d707c3Sbluhm 			ASSX(ev->ident != -rs);
3621d707c3Sbluhm 			if (ev->ident == rm)
3721d707c3Sbluhm 				rm = 0;
3821d707c3Sbluhm 			if (ev->ident == rs)
3921d707c3Sbluhm 				rs = 0;
40507ad807Smickey 		} else if (ev->filter == EVFILT_WRITE) {
4121d707c3Sbluhm 			ASSX(ev->ident != -wm);
4221d707c3Sbluhm 			ASSX(ev->ident != -ws);
4321d707c3Sbluhm 			if (ev->ident == wm)
4421d707c3Sbluhm 				wm = 0;
4521d707c3Sbluhm 			if (ev->ident == ws)
4621d707c3Sbluhm 				ws = 0;
47507ad807Smickey 		} else
48507ad807Smickey 			errx(1, "unknown event");
49507ad807Smickey 	}
5021d707c3Sbluhm 	ASSX(rm <= 0);
5121d707c3Sbluhm 	ASSX(rs <= 0);
5221d707c3Sbluhm 	ASSX(wm <= 0);
5321d707c3Sbluhm 	ASSX(ws <= 0);
54507ad807Smickey 
55507ad807Smickey 	return (0);
56507ad807Smickey }
57507ad807Smickey 
58e56ad730Santon static int
pty_rdrw(void)59e56ad730Santon pty_rdrw(void)
60507ad807Smickey {
61507ad807Smickey 	struct kevent ev[4];
62507ad807Smickey 	struct termios tt;
6321d707c3Sbluhm 	int fd, kq, massa, slave;
64507ad807Smickey 	char buf[1024];
65507ad807Smickey 
6621d707c3Sbluhm 	ASS((fd = open("/dev/console", O_RDONLY, &tt)) > 0,
6721d707c3Sbluhm 	    warn("open /dev/console"));
6821d707c3Sbluhm 	ASS(tcgetattr(fd, &tt) == 0,
6921d707c3Sbluhm 	    warn("tcgetattr"));
70507ad807Smickey 	cfmakeraw(&tt);
71507ad807Smickey 	tt.c_lflag &= ~ECHO;
72507ad807Smickey 	if (openpty(&massa, &slave, NULL, &tt, NULL) < 0)
73507ad807Smickey 		err(1, "openpty");
74507ad807Smickey 	if (fcntl(massa, F_SETFL, O_NONBLOCK) < 0)
75507ad807Smickey 		err(1, "massa: fcntl");
76507ad807Smickey 	if (fcntl(slave, F_SETFL, O_NONBLOCK) < 0)
77507ad807Smickey 		err(1, "massa: fcntl");
78507ad807Smickey 	if ((kq = kqueue()) == -1)
79507ad807Smickey 		err(1, "kqueue");
80507ad807Smickey 
81507ad807Smickey 	/* test the read from the slave works */
82507ad807Smickey 	EV_SET(&ev[0], massa, EVFILT_READ,  EV_ADD|EV_ENABLE, 0, 0, NULL);
83507ad807Smickey 	EV_SET(&ev[1], massa, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, NULL);
84507ad807Smickey 	EV_SET(&ev[2], slave, EVFILT_READ,  EV_ADD|EV_ENABLE, 0, 0, NULL);
85507ad807Smickey 	EV_SET(&ev[3], slave, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, NULL);
86507ad807Smickey 	if (kevent(kq, ev, 4, NULL, 0, NULL) < 0)
87507ad807Smickey 		err(1, "slave: kevent add");
88507ad807Smickey 
8921d707c3Sbluhm 	memset(buf, 0, sizeof(buf));
9021d707c3Sbluhm 
9121d707c3Sbluhm 	ASSX(pty_check(kq, ev, 4, -massa, -slave, massa, slave) == 0);
925b288fd1Suebayasi 
93507ad807Smickey 	if (write(massa, " ", 1) != 1)
94507ad807Smickey 		err(1, "massa: write");
95507ad807Smickey 
96bd35765dSbluhm 	ASSX(pty_check(kq, ev, 4, -massa, slave, massa, slave) == 0);
97507ad807Smickey 
98507ad807Smickey 	read(slave, buf, sizeof(buf));
99507ad807Smickey 
100bd35765dSbluhm 	ASSX(pty_check(kq, ev, 4, -massa, -slave, massa, slave) == 0);
101507ad807Smickey 
1025b288fd1Suebayasi 	while (write(massa, buf, sizeof(buf)) > 0)
1035b288fd1Suebayasi 		continue;
104507ad807Smickey 
105bd35765dSbluhm 	ASSX(pty_check(kq, ev, 4, -massa, slave, -massa, slave) == 0);
106507ad807Smickey 
107507ad807Smickey 	read(slave, buf, 1);
108507ad807Smickey 
109bd35765dSbluhm 	ASSX(pty_check(kq, ev, 4, -massa, slave, massa, slave) == 0);
110507ad807Smickey 
1115b288fd1Suebayasi 	while (read(slave, buf, sizeof(buf)) > 0)
1125b288fd1Suebayasi 		continue;
113507ad807Smickey 
114bd35765dSbluhm 	ASSX(pty_check(kq, ev, 4, -massa, -slave, massa, slave) == 0);
115507ad807Smickey 
116507ad807Smickey 	return (0);
117507ad807Smickey }
118e56ad730Santon 
119*0df5504eSanton static int
pty_close(void)120*0df5504eSanton pty_close(void)
121*0df5504eSanton {
122*0df5504eSanton 	struct kevent ev[1];
123*0df5504eSanton 	struct timespec ts;
124*0df5504eSanton 	int kq, massa, n, slave;
125*0df5504eSanton 
126*0df5504eSanton 	if (openpty(&massa, &slave, NULL, NULL, NULL) == -1)
127*0df5504eSanton 		err(1, "openpty");
128*0df5504eSanton 
129*0df5504eSanton 	kq = kqueue();
130*0df5504eSanton 	if (kq == -1)
131*0df5504eSanton 		err(1, "kqueue");
132*0df5504eSanton 
133*0df5504eSanton 	EV_SET(&ev[0], massa, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, NULL);
134*0df5504eSanton 	if (kevent(kq, ev, 1, NULL, 0, NULL) == -1)
135*0df5504eSanton 		err(1, "kevent: add");
136*0df5504eSanton 
137*0df5504eSanton 	close(slave);
138*0df5504eSanton 
139*0df5504eSanton 	ts.tv_sec = 5;
140*0df5504eSanton 	ts.tv_nsec = 0;
141*0df5504eSanton 	n = kevent(kq, NULL, 0, ev, 1, &ts);
142*0df5504eSanton 	ASSX(n == 1);
143*0df5504eSanton 	ASSX(ev[0].filter == EVFILT_READ);
144*0df5504eSanton 	ASSX(ev[0].flags & EV_EOF);
145*0df5504eSanton 
146*0df5504eSanton 	return 0;
147*0df5504eSanton }
148*0df5504eSanton 
149e56ad730Santon int
do_pty(int n)150e56ad730Santon do_pty(int n)
151e56ad730Santon {
152e56ad730Santon 	switch (n) {
153e56ad730Santon 	case 1:
154e56ad730Santon 		return pty_rdrw();
155*0df5504eSanton 	case 2:
156*0df5504eSanton 		return pty_close();
157e56ad730Santon 	default:
158e56ad730Santon 		errx(1, "unknown pty test number %d", n);
159e56ad730Santon 	}
160e56ad730Santon }
161