PageRenderTime 61ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/lib-src/poll.c

https://github.com/indeyets/smalltalk
C | 254 lines | 184 code | 31 blank | 39 comment | 59 complexity | d3ea9c0b3236b572d8835933b5ea3d22 MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-4.0, LGPL-2.1, CC-BY-SA-3.0
  1. /* Emulation for poll(2)
  2. Contributed by Paolo Bonzini.
  3. Copyright 2001, 2002, 2003, 2006, 2007, 2008 Free Software Foundation, Inc.
  4. This file is part of gnulib.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License along
  14. with this program; if not, write to the Free Software Foundation,
  15. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
  16. #include <config.h>
  17. #if defined(_AIX)
  18. #pragma alloca
  19. #else
  20. # if !defined(alloca) /* predefined by HP cc +Olibcalls */
  21. # ifdef __GNUC__
  22. # define alloca(size) __builtin_alloca(size)
  23. # else
  24. # if HAVE_ALLOCA_H
  25. # include <alloca.h>
  26. # else
  27. # if defined(__hpux)
  28. void *alloca ();
  29. # else
  30. # if !defined(__OS2__) && !defined(WIN32)
  31. char *alloca ();
  32. # else
  33. # include <malloc.h> /* OS/2 defines alloca in here */
  34. # endif
  35. # endif
  36. # endif
  37. # endif
  38. # endif
  39. #endif
  40. #if !defined _WIN32 && !defined __WIN32__
  41. #include <sys/types.h>
  42. #include "poll.h"
  43. #include <errno.h>
  44. #include <limits.h>
  45. #include <assert.h>
  46. #include <sys/time.h>
  47. #include <sys/socket.h>
  48. #include <sys/select.h>
  49. #include <unistd.h>
  50. #ifdef HAVE_SYS_IOCTL_H
  51. #include <sys/ioctl.h>
  52. #endif
  53. #ifdef HAVE_SYS_FILIO_H
  54. #include <sys/filio.h>
  55. #endif
  56. #include <time.h>
  57. #ifndef INFTIM
  58. #define INFTIM (-1)
  59. #endif
  60. /* BeOS does not have MSG_PEEK. */
  61. #ifndef MSG_PEEK
  62. #define MSG_PEEK 0
  63. #endif
  64. /* Convert select(2) returned fd_sets into poll(2) revents values. */
  65. static int
  66. compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
  67. {
  68. int happened = 0;
  69. if (FD_ISSET (fd, rfds))
  70. {
  71. int r;
  72. int socket_errno;
  73. #if defined __MACH__ && defined __APPLE__
  74. /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
  75. for some kinds of descriptors. Detect if this descriptor is a
  76. connected socket, a server socket, or something else using a
  77. 0-byte recv, and use ioctl(2) to detect POLLHUP. */
  78. r = recv (fd, NULL, 0, MSG_PEEK);
  79. socket_errno = (r < 0) ? errno : 0;
  80. if (r == 0 || socket_errno == ENOTSOCK)
  81. ioctl (fd, FIONREAD, &r);
  82. if (r == 0 && !isatty (fd))
  83. happened |= POLLHUP;
  84. #else
  85. char data[64];
  86. r = recv (fd, data, sizeof (data), MSG_PEEK);
  87. socket_errno = (r < 0) ? errno : 0;
  88. if (r == 0)
  89. happened |= POLLHUP;
  90. #endif
  91. /* If the event happened on an unconnected server socket,
  92. that's fine. */
  93. else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
  94. happened |= (POLLIN | POLLRDNORM) & sought;
  95. /* Distinguish hung-up sockets from other errors. */
  96. else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
  97. || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
  98. happened |= POLLHUP;
  99. else
  100. happened |= POLLERR;
  101. }
  102. if (FD_ISSET (fd, wfds))
  103. happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
  104. if (FD_ISSET (fd, efds))
  105. happened |= (POLLPRI | POLLRDBAND) & sought;
  106. return happened;
  107. }
  108. int
  109. poll (pfd, nfd, timeout)
  110. struct pollfd *pfd;
  111. nfds_t nfd;
  112. int timeout;
  113. {
  114. fd_set rfds, wfds, efds;
  115. struct timeval tv;
  116. struct timeval *ptv;
  117. int maxfd, rc;
  118. nfds_t i;
  119. #ifdef _SC_OPEN_MAX
  120. static int sc_open_max = -1;
  121. if (nfd < 0
  122. || (nfd > sc_open_max
  123. && (sc_open_max != -1
  124. || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
  125. {
  126. errno = EINVAL;
  127. return -1;
  128. }
  129. #else /* !_SC_OPEN_MAX */
  130. #ifdef OPEN_MAX
  131. if (nfd < 0 || nfd > OPEN_MAX)
  132. {
  133. errno = EINVAL;
  134. return -1;
  135. }
  136. #endif /* OPEN_MAX -- else, no check is needed */
  137. #endif /* !_SC_OPEN_MAX */
  138. /* EFAULT is not necessary to implement, but let's do it in the
  139. simplest case. */
  140. if (!pfd)
  141. {
  142. errno = EFAULT;
  143. return -1;
  144. }
  145. /* convert timeout number into a timeval structure */
  146. if (timeout == 0)
  147. {
  148. ptv = &tv;
  149. ptv->tv_sec = 0;
  150. ptv->tv_usec = 0;
  151. }
  152. else if (timeout > 0)
  153. {
  154. ptv = &tv;
  155. ptv->tv_sec = timeout / 1000;
  156. ptv->tv_usec = (timeout % 1000) * 1000;
  157. }
  158. else if (timeout == INFTIM)
  159. /* wait forever */
  160. ptv = NULL;
  161. else
  162. {
  163. errno = EINVAL;
  164. return -1;
  165. }
  166. /* create fd sets and determine max fd */
  167. maxfd = -1;
  168. FD_ZERO (&rfds);
  169. FD_ZERO (&wfds);
  170. FD_ZERO (&efds);
  171. for (i = 0; i < nfd; i++)
  172. {
  173. if (pfd[i].fd < 0)
  174. continue;
  175. if (pfd[i].events & (POLLIN | POLLRDNORM))
  176. FD_SET (pfd[i].fd, &rfds);
  177. /* see select(2): "the only exceptional condition detectable
  178. is out-of-band data received on a socket", hence we push
  179. POLLWRBAND events onto wfds instead of efds. */
  180. if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
  181. FD_SET (pfd[i].fd, &wfds);
  182. if (pfd[i].events & (POLLPRI | POLLRDBAND))
  183. FD_SET (pfd[i].fd, &efds);
  184. if (pfd[i].fd >= maxfd
  185. && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
  186. | POLLRDNORM | POLLRDBAND
  187. | POLLWRNORM | POLLWRBAND)))
  188. {
  189. maxfd = pfd[i].fd;
  190. if (maxfd > FD_SETSIZE)
  191. {
  192. errno = EOVERFLOW;
  193. return -1;
  194. }
  195. }
  196. }
  197. /* examine fd sets */
  198. rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
  199. if (rc < 0)
  200. return rc;
  201. /* establish results */
  202. rc = 0;
  203. for (i = 0; i < nfd; i++)
  204. if (pfd[i].fd < 0)
  205. pfd[i].revents = 0;
  206. else
  207. {
  208. int happened = compute_revents (pfd[i].fd, pfd[i].events,
  209. &rfds, &wfds, &efds);
  210. if (happened)
  211. {
  212. pfd[i].revents = happened;
  213. rc++;
  214. }
  215. }
  216. return rc;
  217. }
  218. #endif /* !WIN32 */