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