$NetBSD: patch-ax,v 1.1 2005/11/04 21:09:15 dbj Exp $

--- /dev/null	2005-10-13 14:41:11.000000000 -0400
+++ fakepoll.h
@@ -0,0 +1,161 @@
+// fakepoll.h
+// poll using select
+// Warning: a call to this poll() takes about 4K of stack space.
+
+// Greg Parker     gparker-web@sealiesoftware.com     December 2000
+// This code is in the public domain and may be copied or modified without 
+// permission. 
+
+// Updated May 2002: 
+// * fix crash when an fd is less than 0
+// * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
+// * don't set POLLIN or POLLOUT in revents if it wasn't requested 
+//   in events (only happens when an fd is in the poll set twice)
+
+#ifndef _FAKE_POLL_H
+#define _FAKE_POLL_H
+
+#include <limits.h>
+#define FD_SETSIZE OPEN_MAX
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef struct pollfd {
+    int fd;                         /* file desc to poll */
+    short events;                   /* events of interest on fd */
+    short revents;                  /* events that occurred on fd */
+} pollfd_t;
+
+
+// poll flags
+#define POLLIN  0x0001
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+
+// synonyms
+#define POLLNORM POLLIN
+#define POLLPRI POLLIN
+#define POLLRDNORM POLLIN
+#define POLLRDBAND POLLIN
+#define POLLWRNORM POLLOUT
+#define POLLWRBAND POLLOUT
+
+// ignored
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
+
+inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
+{
+    struct timeval tv;
+    struct timeval *tvp;
+    fd_set readFDs, writeFDs, exceptFDs;
+    fd_set *readp, *writep, *exceptp;
+    struct pollfd *pollEnd, *p;
+    int selected;
+    int result;
+    int maxFD;
+
+    if (!pollSet) {
+        pollEnd = NULL;
+        readp = NULL;
+        writep = NULL;
+        exceptp = NULL;
+        maxFD = 0;
+    } 
+    else {
+        pollEnd = pollSet + pollCount;
+        readp = &readFDs;
+        writep = &writeFDs;
+        exceptp = &exceptFDs;
+
+        FD_ZERO(readp);
+        FD_ZERO(writep);
+        FD_ZERO(exceptp);
+        
+        // Find the biggest fd in the poll set
+        maxFD = 0;
+        for (p = pollSet; p < pollEnd; p++) {
+            if (p->fd > maxFD) maxFD = p->fd;
+        }
+
+        if (maxFD >= FD_SETSIZE) {
+            // At least one fd is too big
+            errno = EINVAL;
+            return -1;
+        }
+        
+        // Transcribe flags from the poll set to the fd sets
+        for (p = pollSet; p < pollEnd; p++) {
+            if (p->fd < 0) {
+                // Negative fd checks nothing and always reports zero
+            } else {
+                if (p->events & POLLIN)  FD_SET(p->fd, readp);
+                if (p->events & POLLOUT) FD_SET(p->fd, writep);
+                if (p->events != 0)      FD_SET(p->fd, exceptp);
+                // POLLERR is never set coming in; poll() always reports errors
+                // But don't report if we're not listening to anything at all.
+            }
+        }
+    }
+        
+    // poll timeout is in milliseconds. Convert to struct timeval.
+    // poll timeout == -1 : wait forever : select timeout of NULL
+    // poll timeout == 0  : return immediately : select timeout of zero
+    if (pollTimeout >= 0) {
+        tv.tv_sec = pollTimeout / 1000;
+        tv.tv_usec = (pollTimeout % 1000) * 1000;
+        tvp = &tv;
+    } else {
+        tvp = NULL;
+    }
+    
+    
+    selected = select(maxFD+1, readp, writep, exceptp, tvp);
+
+
+    if (selected < 0) {
+        // Error during select
+        result = -1;
+    } 
+    else if (selected > 0) {
+        // Select found something
+        // Transcribe result from fd sets to poll set.
+        // Also count the number of selected fds. poll returns the 
+        // number of ready fds; select returns the number of bits set.
+        int polled = 0;
+        for (p = pollSet; p < pollEnd; p++) {
+	    p->revents = 0;
+            if (p->fd < 0) {
+                // Negative fd always reports zero
+            } else {
+                if ((p->events & POLLIN)   &&  FD_ISSET(p->fd, readp)) {
+                    p->revents |= POLLIN;
+                }
+                if ((p->events & POLLOUT)  &&  FD_ISSET(p->fd, writep)) {
+                    p->revents |= POLLOUT;
+                }
+                if ((p->events != 0)       &&  FD_ISSET(p->fd, exceptp)) {
+                    p->revents |= POLLERR;
+                }
+
+                if (p->revents) polled++;
+            }
+	}
+        result = polled;
+    }
+    else {
+	// selected == 0, select timed out before anything happened
+        // Clear all result bits and return zero.
+        for (p = pollSet; p < pollEnd; p++) {
+            p->revents = 0;
+        }
+        result = 0;
+    }
+
+    return result;
+}
+
+
+#endif
