2 d24ddaa6 2022-02-26 thomas * Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
4 d24ddaa6 2022-02-26 thomas * Permission to use, copy, modify, and distribute this software for any
5 d24ddaa6 2022-02-26 thomas * purpose with or without fee is hereby granted, provided that the above
6 d24ddaa6 2022-02-26 thomas * copyright notice and this permission notice appear in all copies.
8 d24ddaa6 2022-02-26 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 d24ddaa6 2022-02-26 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 d24ddaa6 2022-02-26 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 d24ddaa6 2022-02-26 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 d24ddaa6 2022-02-26 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 d24ddaa6 2022-02-26 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 d24ddaa6 2022-02-26 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 d24ddaa6 2022-02-26 thomas #ifdef HAVE_SYS_SELECT_H
18 d24ddaa6 2022-02-26 thomas # include <sys/select.h>
21 d24ddaa6 2022-02-26 thomas #include <errno.h>
22 d24ddaa6 2022-02-26 thomas #include <stdlib.h>
23 d24ddaa6 2022-02-26 thomas #include <unistd.h>
24 d24ddaa6 2022-02-26 thomas #include "bsd-poll.h"
26 d24ddaa6 2022-02-26 thomas #ifndef MAX
27 d24ddaa6 2022-02-26 thomas #define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b))
30 a3732bb6 2022-02-26 thomas #ifndef howmany
31 a3732bb6 2022-02-26 thomas #define howmany(x,y) (((x)+((y)-1))/(y))
35 d24ddaa6 2022-02-26 thomas * A minimal implementation of ppoll(2), built on top of pselect(2).
37 d24ddaa6 2022-02-26 thomas * Only supports POLLIN, POLLOUT and POLLPRI flags in pfd.events and
38 d24ddaa6 2022-02-26 thomas * revents. Notably POLLERR, POLLHUP and POLLNVAL are not supported.
40 d24ddaa6 2022-02-26 thomas * Supports pfd.fd = -1 meaning "unused" although it's not standard.
44 d24ddaa6 2022-02-26 thomas ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmoutp,
45 d24ddaa6 2022-02-26 thomas const sigset_t *sigmask)
48 d24ddaa6 2022-02-26 thomas int saved_errno, ret, fd, maxfd = 0;
49 d24ddaa6 2022-02-26 thomas fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL;
50 d24ddaa6 2022-02-26 thomas size_t nmemb;
52 d24ddaa6 2022-02-26 thomas for (i = 0; i < nfds; i++) {
53 d24ddaa6 2022-02-26 thomas fd = fds[i].fd;
54 d24ddaa6 2022-02-26 thomas if (fd != -1 && fd >= FD_SETSIZE) {
55 d24ddaa6 2022-02-26 thomas errno = EINVAL;
56 d24ddaa6 2022-02-26 thomas return -1;
58 d24ddaa6 2022-02-26 thomas maxfd = MAX(maxfd, fd);
61 d24ddaa6 2022-02-26 thomas nmemb = howmany(maxfd + 1 , NFDBITS);
62 d24ddaa6 2022-02-26 thomas if ((readfds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
63 d24ddaa6 2022-02-26 thomas (writefds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
64 d24ddaa6 2022-02-26 thomas (exceptfds = calloc(nmemb, sizeof(fd_mask))) == NULL) {
65 d24ddaa6 2022-02-26 thomas saved_errno = ENOMEM;
70 d24ddaa6 2022-02-26 thomas /* populate event bit vectors for the events we're interested in */
71 d24ddaa6 2022-02-26 thomas for (i = 0; i < nfds; i++) {
72 d24ddaa6 2022-02-26 thomas fd = fds[i].fd;
73 d24ddaa6 2022-02-26 thomas if (fd == -1)
75 d24ddaa6 2022-02-26 thomas if (fds[i].events & POLLIN)
76 d24ddaa6 2022-02-26 thomas FD_SET(fd, readfds);
77 d24ddaa6 2022-02-26 thomas if (fds[i].events & POLLOUT)
78 d24ddaa6 2022-02-26 thomas FD_SET(fd, writefds);
79 d24ddaa6 2022-02-26 thomas if (fds[i].events & POLLPRI)
80 d24ddaa6 2022-02-26 thomas FD_SET(fd, exceptfds);
83 d24ddaa6 2022-02-26 thomas ret = pselect(maxfd + 1, readfds, writefds, exceptfds, tmoutp, sigmask);
84 d24ddaa6 2022-02-26 thomas saved_errno = errno;
86 d24ddaa6 2022-02-26 thomas /* scan through select results and set poll() flags */
87 d24ddaa6 2022-02-26 thomas for (i = 0; i < nfds; i++) {
88 d24ddaa6 2022-02-26 thomas fd = fds[i].fd;
89 d24ddaa6 2022-02-26 thomas fds[i].revents = 0;
90 d24ddaa6 2022-02-26 thomas if (fd == -1)
92 d24ddaa6 2022-02-26 thomas if (FD_ISSET(fd, readfds))
93 d24ddaa6 2022-02-26 thomas fds[i].revents |= POLLIN;
94 d24ddaa6 2022-02-26 thomas if (FD_ISSET(fd, writefds))
95 d24ddaa6 2022-02-26 thomas fds[i].revents |= POLLOUT;
96 d24ddaa6 2022-02-26 thomas if (FD_ISSET(fd, exceptfds))
97 d24ddaa6 2022-02-26 thomas fds[i].revents |= POLLPRI;
101 d24ddaa6 2022-02-26 thomas free(readfds);
102 d24ddaa6 2022-02-26 thomas free(writefds);
103 d24ddaa6 2022-02-26 thomas free(exceptfds);
104 d24ddaa6 2022-02-26 thomas if (ret == -1)
105 d24ddaa6 2022-02-26 thomas errno = saved_errno;
106 d24ddaa6 2022-02-26 thomas return ret;
111 d24ddaa6 2022-02-26 thomas poll(struct pollfd *fds, nfds_t nfds, int timeout)
113 d24ddaa6 2022-02-26 thomas struct timespec ts, *tsp = NULL;
115 d24ddaa6 2022-02-26 thomas /* poll timeout is msec, ppoll is timespec (sec + nsec) */
116 d24ddaa6 2022-02-26 thomas if (timeout >= 0) {
117 d24ddaa6 2022-02-26 thomas ts.tv_sec = timeout / 1000;
118 d24ddaa6 2022-02-26 thomas ts.tv_nsec = (timeout % 1000) * 1000000;
119 d24ddaa6 2022-02-26 thomas tsp = &ts;
122 d24ddaa6 2022-02-26 thomas return ppoll(fds, nfds, tsp, NULL);