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