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