Change select(2) to kevent(2) on script(1)...
Norikatsu Shigemura
nork at FreeBSD.org
Sat Dec 20 16:27:54 UTC 2008
Hi Ed!
I inspired by your 'kqueue()-support to pseudo-terminal master
devices' (svn commit: r185942). So I'm trying to use kevent(2)
on script(1). (SEE ALSO following patch)
But it doesn't work. Because 'master' file descriptor (from
openpty(3)) doesn't return last 0 byte data readable when shell
exit. In this case of select(2), 'master' file descriptor
gets 0 byte data and exit script(1).
Do you have any idea?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--- usr.bin/script/script.c.orig 2004-02-16 02:30:13.000000000 +0900
+++ usr.bin/script/script.c 2008-12-21 00:59:59.929804968 +0900
@@ -49,6 +49,7 @@
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
+#include <sys/event.h>
#include <sys/time.h>
#include <err.h>
@@ -85,11 +86,12 @@
struct termios rtt, stt;
struct winsize win;
int aflg, kflg, ch, n;
- struct timeval tv, *tvp;
+ struct timespec ts, *tsp;
time_t tvec, start;
char obuf[BUFSIZ];
char ibuf[BUFSIZ];
- fd_set rfd;
+ int kq;
+ struct kevent kev[2];
int flushtime = 30;
aflg = kflg = 0;
@@ -160,23 +162,29 @@
doshell(argv);
if (flushtime > 0)
- tvp = &tv;
+ tsp = &ts;
else
- tvp = NULL;
+ tsp = NULL;
start = time(0);
- FD_ZERO(&rfd);
+
+ if ((kq = kqueue()) < 0)
+ err(1, "kqueue");
+
+ EV_SET(&kev[0], master, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ EV_SET(&kev[1], STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ if (kevent(kq, kev, 2, NULL, 0, NULL) < 0)
+ err(1, "kevent");
+
for (;;) {
- FD_SET(master, &rfd);
- FD_SET(STDIN_FILENO, &rfd);
if (flushtime > 0) {
- tv.tv_sec = flushtime;
- tv.tv_usec = 0;
+ ts.tv_sec = flushtime;
+ ts.tv_nsec = 0;
}
- n = select(master + 1, &rfd, 0, 0, tvp);
+ n = kevent(kq, NULL, 0, kev, 1, tsp);
if (n < 0 && errno != EINTR)
break;
- if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
+ if (n > 0 && kev[0].ident == STDIN_FILENO) {
cc = read(STDIN_FILENO, ibuf, BUFSIZ);
if (cc < 0)
break;
@@ -190,7 +198,7 @@
}
}
}
- if (n > 0 && FD_ISSET(master, &rfd)) {
+ if (n > 0 && kev[0].ident == master) {
cc = read(master, obuf, sizeof (obuf));
if (cc <= 0)
break;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
More information about the freebsd-current
mailing list