DEV: poll: add support for epoll

When called with -e, epoll is used instead of poll. The poller does
very little in this code (just checks for any event without waiting) but
that's sufficient to see return values.
diff --git a/dev/poll/poll.c b/dev/poll/poll.c
index 554fd63..022c039 100644
--- a/dev/poll/poll.c
+++ b/dev/poll/poll.c
@@ -2,6 +2,11 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+
+#ifdef __linux__
+#include <sys/epoll.h>
+#endif
+
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <errno.h>
@@ -33,6 +38,7 @@
 int cfd = -1;
 int sfd = -1;
 int connected = 0;
+int use_epoll = 0;
 struct sockaddr_in saddr, caddr;
 socklen_t salen, calen;
 
@@ -53,6 +59,7 @@
 	       "args:\n"
 	       "    -h            display this help\n"
 	       "    -v            verbose mode (shows ret values)\n"
+	       "    -e            use epoll instead of poll\n"
 	       "    -c <actions>  perform <action> on client side socket\n"
 	       "    -s <actions>  perform <action> on server side socket\n"
 	       "    -l <actions>  perform <action> on listening socket\n"
@@ -209,13 +216,56 @@
 void do_pol(int fd)
 {
 	struct pollfd fds = { .fd = fd, .events = POLLIN|POLLOUT|POLLRDHUP, .revents=0 };
+	int flags, flag;
 	int ret;
 
+#ifdef __linux__
+	while (use_epoll) {
+		struct epoll_event evt;
+		static int epoll_fd = -1;
+
+		if (epoll_fd == -1)
+			epoll_fd = epoll_create(1024);
+		if (epoll_fd == -1)
+			break;
+		evt.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
+		evt.data.fd = fd;
+		epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &evt);
+		ret = epoll_wait(epoll_fd, &evt, 1, 0);
+
+		if (verbose) {
+			printf("cmd #%d stp #%d: %s(%s=%d): ret=%d%s ev=%#x ", cmd, cmdstep, __FUNCTION__ + 3, side(fd), fd, ret, get_errno(ret), ret > 0 ? evt.events : 0);
+			if (ret > 0 && evt.events) {
+				putchar('(');
+
+				for (flags = evt.events; flags; flags ^= flag) {
+					flag = flags ^ (flags & (flags - 1)); // keep lowest bit only
+					switch (flag) {
+					case EPOLLIN: printf("IN"); break;
+					case EPOLLOUT: printf("OUT"); break;
+					case EPOLLPRI: printf("PRI"); break;
+					case EPOLLHUP: printf("HUP"); break;
+					case EPOLLERR: printf("ERR"); break;
+					case EPOLLRDHUP: printf("RDHUP"); break;
+					default: printf("???[%#x]", flag); break;
+					}
+					if (flags ^ flag)
+						putchar(' ');
+				}
+				putchar(')');
+			}
+			putchar('\n');
+		}
+
+		evt.data.fd = fd;
+		epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &evt);
+		return;
+	}
+#endif
 	ret = poll(&fds, 1, 0);
 	if (verbose) {
 		printf("cmd #%d stp #%d: %s(%s=%d): ret=%d%s ev=%#x ", cmd, cmdstep, __FUNCTION__ + 3, side(fd), fd, ret, get_errno(ret), ret > 0 ? fds.revents : 0);
 		if (ret > 0 && fds.revents) {
-			int flags, flag;
 			putchar('(');
 
 			for (flags = fds.revents; flags; flags ^= flag) {
@@ -298,6 +348,9 @@
 		case 'v' :
 			verbose++;
 			break;
+		case 'e' :
+			use_epoll = 1;
+			break;
 		case 'c' :
 			cmd++; cmdstep = 0;
 			if (!connected) {