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