/* * Code for various kinds of delays. Most of this is nonportable and * requires various enhancements to the operating system, so it won't * work on all systems. It is included in curses to provide a portable * interface, and so curses itself can use it for function keys. */ /* @(#) select.c: 1.1 10/15/83 (1.10 3/6/83) */ #include "curses.ext" #include <signal.h> #define NAPINTERVAL 100 /* From early specs - this may change by 4.2BSD */ struct _timeval { long tv_sec; long tv_usec; }; #ifdef FIONREAD # ifndef TIOCREMOTE /* * Decide if we can emulate select but don't have it. This is * intended to be true only on 4.1BSD, not 4.2BSD or USG. */ # define NEEDSELECT # endif #endif #ifdef NEEDSELECT /* * Emulation of 4.2BSD select system call. This is somewhat crude but * better than nothing. We do FIONREAD on each fd, and if we have to * wait we use nap to avoid a busy wait. The resolution of the nap * will hurt response - so will the fact that we ignore the write fds. * If we are simulating nap with a 1 second sleep, this will be very poor. * * nfds is the number of fds to check - this is usually 20. * prfds is a pointer to a bit vector of file descriptors - in the case * where nfds < 32, prfds points to an integer, where bit 1<<fd * is 1 if we are supposed to check file descriptor fd. * pwfds is like prfds but for write checks instead of read checks. * ms is the max number of milliseconds to wait before returning failure. * The value returned is the number of file descriptors ready for input. * The bit vectors are updated in place. */ int select(nfds, prfds, pwfds, pefds, timeout) register int nfds; int *prfds, *pwfds, *pefds; struct _timeval *timeout; { register int fd; register int rfds = *prfds; register int n; int nwaiting, rv = 0; long ms = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; for (;;) { /* check the fds */ for (fd=0; fd<nfds; fd++) if (1<<fd & rfds) { ioctl(fd, FIONREAD, &nwaiting); if (nwaiting > 0) { rv++; } else *prfds &= ~(1<<fd); } if (rv) return rv; /* Nothing ready. Should we give up? */ if (ms <= 0) return 0; *prfds = rfds; /* we clobbered it, so restore. */ /* Wait a bit */ n = NAPINTERVAL; if (ms < NAPINTERVAL) n = ms; ms -= n; napms(n); } } #else #ifndef FIONREAD int select(nfds, prfds, pwfds, pefds, ms) register int nfds; int *prfds, *pwfds, *pefds; struct _timeval *ms; { /* Can't do it, but at least compile right */ return ERR; } #endif FIONREAD #endif NEEDSELECT