1 /* $Id: bsd-poll.c,v 1.4 2008/08/29 21:32:38 dtucker Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au). 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "includes.h" 20 #if !defined(HAVE_POLL) 21 22 #ifdef HAVE_SYS_SELECT_H 23 # include <sys/select.h> 24 #endif 25 26 #include <stdlib.h> 27 #include <errno.h> 28 #include "bsd-poll.h" 29 30 /* 31 * A minimal implementation of poll(2), built on top of select(2). 32 * 33 * Only supports POLLIN and POLLOUT flags in pfd.events, and POLLIN, POLLOUT 34 * and POLLERR flags in revents. 35 * 36 * Supports pfd.fd = -1 meaning "unused" although it's not standard. 37 */ 38 39 int 40 poll(struct pollfd *fds, nfds_t nfds, int timeout) 41 { 42 nfds_t i; 43 int saved_errno, ret, fd, maxfd = 0; 44 fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL; 45 size_t nmemb; 46 struct timeval tv, *tvp = NULL; 47 48 for (i = 0; i < nfds; i++) { 49 fd = fds[i].fd; 50 if (fd >= FD_SETSIZE) { 51 errno = EINVAL; 52 return -1; 53 } 54 maxfd = MAX(maxfd, fd); 55 } 56 57 nmemb = howmany(maxfd + 1 , NFDBITS); 58 if ((readfds = calloc(nmemb, sizeof(fd_mask))) == NULL || 59 (writefds = calloc(nmemb, sizeof(fd_mask))) == NULL || 60 (exceptfds = calloc(nmemb, sizeof(fd_mask))) == NULL) { 61 saved_errno = ENOMEM; 62 ret = -1; 63 goto out; 64 } 65 66 /* populate event bit vectors for the events we're interested in */ 67 for (i = 0; i < nfds; i++) { 68 fd = fds[i].fd; 69 if (fd == -1) 70 continue; 71 if (fds[i].events & POLLIN) { 72 FD_SET(fd, readfds); 73 FD_SET(fd, exceptfds); 74 } 75 if (fds[i].events & POLLOUT) { 76 FD_SET(fd, writefds); 77 FD_SET(fd, exceptfds); 78 } 79 } 80 81 /* poll timeout is msec, select is timeval (sec + usec) */ 82 if (timeout >= 0) { 83 tv.tv_sec = timeout / 1000; 84 tv.tv_usec = (timeout % 1000) * 1000; 85 tvp = &tv; 86 } 87 88 ret = select(maxfd + 1, readfds, writefds, exceptfds, tvp); 89 saved_errno = errno; 90 91 /* scan through select results and set poll() flags */ 92 for (i = 0; i < nfds; i++) { 93 fd = fds[i].fd; 94 fds[i].revents = 0; 95 if (fd == -1) 96 continue; 97 if (FD_ISSET(fd, readfds)) { 98 fds[i].revents |= POLLIN; 99 } 100 if (FD_ISSET(fd, writefds)) { 101 fds[i].revents |= POLLOUT; 102 } 103 if (FD_ISSET(fd, exceptfds)) { 104 fds[i].revents |= POLLERR; 105 } 106 } 107 108 out: 109 if (readfds != NULL) 110 free(readfds); 111 if (writefds != NULL) 112 free(writefds); 113 if (exceptfds != NULL) 114 free(exceptfds); 115 if (ret == -1) 116 errno = saved_errno; 117 return ret; 118 } 119 #endif 120