+/* kludge up some limited epoll semantics using select for 2.4 kernels */
+/* $Id: fake_epoll.h,v 1.1 2005-06-04 15:42:35 bodea Exp $ */
+
+#ifndef __FAKE_EPOLL_H__
+#define __FAKE_EPOLL_H__
+
+#define EPOLLIN 0x01
+#define EPOLLOUT 0x04
+#define EPOLLERR 0x08
+#define EPOLLHUP 0x10
+
+#define EPOLL_CTL_ADD 1
+#define EPOLL_CTL_DEL 2
+#define EPOLL_CTL_MOD 3
+
+struct epoll_event {
+ uint32_t events;
+ union epoll_data {
+ void *ptr;
+ int fd;
+ uint32_t u32;
+ uint64_t u64;
+ } data;
+};
+
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
+
+#ifdef FAKE_EPOLL_IMPLEMENTATION
+
+#include <sys/select.h>
+
+static fd_set _epoll_read_set;
+static fd_set _epoll_write_set;
+static int _epoll_fds;
+static struct epoll_event *_epoll_data[128];
+
+static int epoll_create(int size __attribute__ ((unused)))
+{
+ static int once = 0;
+ if (once++)
+ {
+ errno = ENFILE; /* only support one instance */
+ return -1;
+ }
+
+ FD_ZERO(&_epoll_read_set);
+ FD_ZERO(&_epoll_write_set);
+ _epoll_fds = 0;
+
+ memset(_epoll_data, 0, sizeof(_epoll_data));
+
+ return 1; /* "descriptor" */
+}
+
+int epoll_ctl(int epfd __attribute__ ((unused)), int op, int fd,
+ struct epoll_event *event)
+{
+ if (fd > (sizeof(_epoll_data)/sizeof(*_epoll_data)) - 1)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ switch (op)
+ {
+ case EPOLL_CTL_ADD:
+ if (event->events & EPOLLIN)
+ FD_SET(fd, &_epoll_read_set);
+
+ if (event->events & EPOLLOUT)
+ FD_SET(fd, &_epoll_write_set);
+
+ if (fd >= _epoll_fds)
+ _epoll_fds = fd + 1;
+
+ if (_epoll_data[fd])
+ free(_epoll_data[fd]);
+
+ if (!(_epoll_data[fd] = malloc(sizeof(*_epoll_data))))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ memcpy(_epoll_data[fd], &event->data, sizeof(*_epoll_data));
+ break;
+
+ case EPOLL_CTL_MOD:
+ if (event->events & EPOLLIN)
+ FD_SET(fd, &_epoll_read_set);
+ else
+ FD_CLR(fd, &_epoll_read_set);
+
+ if (event->events & EPOLLOUT)
+ FD_SET(fd, &_epoll_write_set);
+ else
+ FD_CLR(fd, &_epoll_write_set);
+
+ memcpy(_epoll_data[fd], &event->data, sizeof(*_epoll_data));
+ break;
+
+ case EPOLL_CTL_DEL:
+ FD_CLR(fd, &_epoll_read_set);
+ FD_CLR(fd, &_epoll_write_set);
+
+ free(_epoll_data[fd]);
+ _epoll_data[fd] = 0;
+
+ if (fd == _epoll_fds - 1)
+ {
+ _epoll_fds = 0;
+ while (fd-- > 0)
+ {
+ if (FD_ISSET(fd, &_epoll_read_set) ||
+ FD_ISSET(fd, &_epoll_write_set))
+ {
+ _epoll_fds = fd + 1;
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+static int epoll_wait(int epfd __attribute__ ((unused)),
+ struct epoll_event *events, int maxevents, int timout)
+{
+ fd_set r;
+ fd_set w;
+ struct timeval t;
+ struct timeval *tp;
+ int n;
+ int e;
+ int i;
+
+ memcpy(&r, &_epoll_read_set, sizeof(r));
+ memcpy(&w, &_epoll_write_set, sizeof(w));
+
+ if (timout >= 0)
+ {
+ t.tv_sec = 0;
+ t.tv_usec = timout * 1000;
+ tp = &t;
+ }
+ else
+ tp = 0;
+
+ n = select(_epoll_fds, &r, &w, 0, tp);
+ if (n > maxevents)
+ n = maxevents;
+
+ for (i = e = 0; n > 0 && i < _epoll_fds; i++)
+ {
+ if (!_epoll_data[i])
+ continue;
+
+ events[e].events = 0;
+ if (FD_ISSET(i, &r))
+ events[e].events |= EPOLLIN;
+
+ if (FD_ISSET(i, &w))
+ events[e].events |= EPOLLOUT;
+
+ if (events[e].events)
+ {
+ memcpy(&events[e++].data, _epoll_data[i], sizeof(events[0].data));
+ n--;
+ }
+ }
+
+ return e;
+}
+
+#endif /* FAKE_EPOLL_IMPLEMENTATION */
+#endif /* __FAKE_EPOLL_H__ */