1264377Sdes/* $Id: bsd-poll.c,v 1.6 2014/02/05 23:44:13 dtucker Exp $ */ 2180744Sdes 3180744Sdes/* 4180744Sdes * Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au). 5180744Sdes * 6180744Sdes * Permission to use, copy, modify, and distribute this software for any 7180744Sdes * purpose with or without fee is hereby granted, provided that the above 8180744Sdes * copyright notice and this permission notice appear in all copies. 9180744Sdes * 10180744Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11180744Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12180744Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13180744Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14180744Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15180744Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16180744Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17180744Sdes */ 18180744Sdes 19180744Sdes#include "includes.h" 20180746Sdes#if !defined(HAVE_POLL) 21180744Sdes 22262566Sdes#include <sys/types.h> 23262566Sdes#include <sys/time.h> 24180744Sdes#ifdef HAVE_SYS_SELECT_H 25180744Sdes# include <sys/select.h> 26180744Sdes#endif 27180744Sdes 28262566Sdes#include <errno.h> 29180750Sdes#include <stdlib.h> 30262566Sdes#include <unistd.h> 31180744Sdes#include "bsd-poll.h" 32180744Sdes 33180744Sdes/* 34180744Sdes * A minimal implementation of poll(2), built on top of select(2). 35180744Sdes * 36180744Sdes * Only supports POLLIN and POLLOUT flags in pfd.events, and POLLIN, POLLOUT 37180744Sdes * and POLLERR flags in revents. 38180744Sdes * 39180744Sdes * Supports pfd.fd = -1 meaning "unused" although it's not standard. 40180744Sdes */ 41180744Sdes 42180744Sdesint 43180744Sdespoll(struct pollfd *fds, nfds_t nfds, int timeout) 44180744Sdes{ 45180744Sdes nfds_t i; 46180744Sdes int saved_errno, ret, fd, maxfd = 0; 47180744Sdes fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL; 48180744Sdes size_t nmemb; 49180744Sdes struct timeval tv, *tvp = NULL; 50180744Sdes 51180744Sdes for (i = 0; i < nfds; i++) { 52192595Sdes fd = fds[i].fd; 53180744Sdes if (fd >= FD_SETSIZE) { 54180744Sdes errno = EINVAL; 55180744Sdes return -1; 56180744Sdes } 57192595Sdes maxfd = MAX(maxfd, fd); 58180744Sdes } 59180744Sdes 60180744Sdes nmemb = howmany(maxfd + 1 , NFDBITS); 61180744Sdes if ((readfds = calloc(nmemb, sizeof(fd_mask))) == NULL || 62180744Sdes (writefds = calloc(nmemb, sizeof(fd_mask))) == NULL || 63180744Sdes (exceptfds = calloc(nmemb, sizeof(fd_mask))) == NULL) { 64180744Sdes saved_errno = ENOMEM; 65180744Sdes ret = -1; 66180744Sdes goto out; 67180744Sdes } 68180744Sdes 69180744Sdes /* populate event bit vectors for the events we're interested in */ 70180744Sdes for (i = 0; i < nfds; i++) { 71180744Sdes fd = fds[i].fd; 72180744Sdes if (fd == -1) 73180744Sdes continue; 74180744Sdes if (fds[i].events & POLLIN) { 75180744Sdes FD_SET(fd, readfds); 76180744Sdes FD_SET(fd, exceptfds); 77180744Sdes } 78180744Sdes if (fds[i].events & POLLOUT) { 79180744Sdes FD_SET(fd, writefds); 80180744Sdes FD_SET(fd, exceptfds); 81180744Sdes } 82180744Sdes } 83180744Sdes 84180744Sdes /* poll timeout is msec, select is timeval (sec + usec) */ 85180744Sdes if (timeout >= 0) { 86180744Sdes tv.tv_sec = timeout / 1000; 87180744Sdes tv.tv_usec = (timeout % 1000) * 1000; 88180744Sdes tvp = &tv; 89180744Sdes } 90180744Sdes 91180744Sdes ret = select(maxfd + 1, readfds, writefds, exceptfds, tvp); 92180744Sdes saved_errno = errno; 93180744Sdes 94180744Sdes /* scan through select results and set poll() flags */ 95180744Sdes for (i = 0; i < nfds; i++) { 96180744Sdes fd = fds[i].fd; 97180744Sdes fds[i].revents = 0; 98180744Sdes if (fd == -1) 99180744Sdes continue; 100180744Sdes if (FD_ISSET(fd, readfds)) { 101180744Sdes fds[i].revents |= POLLIN; 102180744Sdes } 103180744Sdes if (FD_ISSET(fd, writefds)) { 104180744Sdes fds[i].revents |= POLLOUT; 105180744Sdes } 106180744Sdes if (FD_ISSET(fd, exceptfds)) { 107180744Sdes fds[i].revents |= POLLERR; 108180744Sdes } 109180744Sdes } 110180744Sdes 111180744Sdesout: 112264377Sdes free(readfds); 113264377Sdes free(writefds); 114264377Sdes free(exceptfds); 115180744Sdes if (ret == -1) 116180744Sdes errno = saved_errno; 117180744Sdes return ret; 118180744Sdes} 119180744Sdes#endif 120