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