11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $Id: bsd-poll.c,v 1.4 2008/08/29 21:32:38 dtucker Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies.
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if !defined(HAVE_POLL)
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_SELECT_H
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/select.h>
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h>
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "bsd-poll.h"
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * A minimal implementation of poll(2), built on top of select(2).
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Only supports POLLIN and POLLOUT flags in pfd.events, and POLLIN, POLLOUT
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * and POLLERR flags in revents.
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Supports pfd.fd = -1 meaning "unused" although it's not standard.
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpoll(struct pollfd *fds, nfds_t nfds, int timeout)
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	nfds_t i;
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int saved_errno, ret, fd, maxfd = 0;
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL;
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t nmemb;
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct timeval tv, *tvp = NULL;
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < nfds; i++) {
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fd = fds[i].fd;
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (fd >= FD_SETSIZE) {
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			errno = EINVAL;
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		maxfd = MAX(maxfd, fd);
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	nmemb = howmany(maxfd + 1 , NFDBITS);
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((readfds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (writefds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (exceptfds = calloc(nmemb, sizeof(fd_mask))) == NULL) {
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		saved_errno = ENOMEM;
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ret = -1;
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* populate event bit vectors for the events we're interested in */
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < nfds; i++) {
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fd = fds[i].fd;
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (fd == -1)
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (fds[i].events & POLLIN) {
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(fd, readfds);
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(fd, exceptfds);
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (fds[i].events & POLLOUT) {
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(fd, writefds);
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(fd, exceptfds);
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* poll timeout is msec, select is timeval (sec + usec) */
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (timeout >= 0) {
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tv.tv_sec = timeout / 1000;
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tv.tv_usec = (timeout % 1000) * 1000;
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tvp = &tv;
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = select(maxfd + 1, readfds, writefds, exceptfds, tvp);
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	saved_errno = errno;
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* scan through select results and set poll() flags */
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < nfds; i++) {
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fd = fds[i].fd;
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fds[i].revents = 0;
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (fd == -1)
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (FD_ISSET(fd, readfds)) {
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fds[i].revents |= POLLIN;
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (FD_ISSET(fd, writefds)) {
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fds[i].revents |= POLLOUT;
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (FD_ISSET(fd, exceptfds)) {
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fds[i].revents |= POLLERR;
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodout:
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (readfds != NULL)
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		free(readfds);
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (writefds != NULL)
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		free(writefds);
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (exceptfds != NULL)
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		free(exceptfds);
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ret == -1)
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		errno = saved_errno;
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
120