Blame


1 d24ddaa6 2022-02-26 thomas /*
2 d24ddaa6 2022-02-26 thomas * Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
3 d24ddaa6 2022-02-26 thomas *
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.
7 d24ddaa6 2022-02-26 thomas *
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.
15 d24ddaa6 2022-02-26 thomas */
16 d24ddaa6 2022-02-26 thomas
17 d24ddaa6 2022-02-26 thomas #ifdef HAVE_SYS_SELECT_H
18 d24ddaa6 2022-02-26 thomas # include <sys/select.h>
19 d24ddaa6 2022-02-26 thomas #endif
20 d24ddaa6 2022-02-26 thomas
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"
25 d24ddaa6 2022-02-26 thomas
26 d24ddaa6 2022-02-26 thomas #ifndef MAX
27 d24ddaa6 2022-02-26 thomas #define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b))
28 d24ddaa6 2022-02-26 thomas #endif
29 d24ddaa6 2022-02-26 thomas
30 a3732bb6 2022-02-26 thomas #ifndef howmany
31 a3732bb6 2022-02-26 thomas #define howmany(x,y) (((x)+((y)-1))/(y))
32 a3732bb6 2022-02-26 thomas #endif
33 a3732bb6 2022-02-26 thomas
34 d24ddaa6 2022-02-26 thomas /*
35 d24ddaa6 2022-02-26 thomas * A minimal implementation of ppoll(2), built on top of pselect(2).
36 d24ddaa6 2022-02-26 thomas *
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.
39 d24ddaa6 2022-02-26 thomas *
40 d24ddaa6 2022-02-26 thomas * Supports pfd.fd = -1 meaning "unused" although it's not standard.
41 d24ddaa6 2022-02-26 thomas */
42 d24ddaa6 2022-02-26 thomas
43 d24ddaa6 2022-02-26 thomas int
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)
46 d24ddaa6 2022-02-26 thomas {
47 d24ddaa6 2022-02-26 thomas nfds_t i;
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;
51 d24ddaa6 2022-02-26 thomas
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;
57 d24ddaa6 2022-02-26 thomas }
58 d24ddaa6 2022-02-26 thomas maxfd = MAX(maxfd, fd);
59 d24ddaa6 2022-02-26 thomas }
60 d24ddaa6 2022-02-26 thomas
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;
66 d24ddaa6 2022-02-26 thomas ret = -1;
67 d24ddaa6 2022-02-26 thomas goto out;
68 d24ddaa6 2022-02-26 thomas }
69 d24ddaa6 2022-02-26 thomas
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)
74 d24ddaa6 2022-02-26 thomas continue;
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);
81 d24ddaa6 2022-02-26 thomas }
82 d24ddaa6 2022-02-26 thomas
83 d24ddaa6 2022-02-26 thomas ret = pselect(maxfd + 1, readfds, writefds, exceptfds, tmoutp, sigmask);
84 d24ddaa6 2022-02-26 thomas saved_errno = errno;
85 d24ddaa6 2022-02-26 thomas
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)
91 d24ddaa6 2022-02-26 thomas continue;
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;
98 d24ddaa6 2022-02-26 thomas }
99 d24ddaa6 2022-02-26 thomas
100 d24ddaa6 2022-02-26 thomas out:
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;
107 d24ddaa6 2022-02-26 thomas }
108 d24ddaa6 2022-02-26 thomas
109 d24ddaa6 2022-02-26 thomas #if 0
110 d24ddaa6 2022-02-26 thomas int
111 d24ddaa6 2022-02-26 thomas poll(struct pollfd *fds, nfds_t nfds, int timeout)
112 d24ddaa6 2022-02-26 thomas {
113 d24ddaa6 2022-02-26 thomas struct timespec ts, *tsp = NULL;
114 d24ddaa6 2022-02-26 thomas
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;
120 d24ddaa6 2022-02-26 thomas }
121 d24ddaa6 2022-02-26 thomas
122 d24ddaa6 2022-02-26 thomas return ppoll(fds, nfds, tsp, NULL);
123 d24ddaa6 2022-02-26 thomas }
124 d24ddaa6 2022-02-26 thomas #endif