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