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