Update gnulib files.
[gnutls.git] / gl / select.c
blobbb6952ebf559a854fae1ec5abde40ef6996344c2
1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2009 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22 #include <config.h>
23 #include <alloca.h>
24 #include <assert.h>
26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
27 /* Native Win32. */
29 #include <sys/types.h>
30 #include <stdbool.h>
31 #include <errno.h>
32 #include <limits.h>
34 #include <winsock2.h>
35 #include <windows.h>
36 #include <io.h>
37 #include <stdio.h>
38 #include <conio.h>
39 #include <time.h>
41 struct bitset {
42 unsigned char in[FD_SETSIZE / CHAR_BIT];
43 unsigned char out[FD_SETSIZE / CHAR_BIT];
46 /* Declare data structures for ntdll functions. */
47 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
48 ULONG NamedPipeType;
49 ULONG NamedPipeConfiguration;
50 ULONG MaximumInstances;
51 ULONG CurrentInstances;
52 ULONG InboundQuota;
53 ULONG ReadDataAvailable;
54 ULONG OutboundQuota;
55 ULONG WriteQuotaAvailable;
56 ULONG NamedPipeState;
57 ULONG NamedPipeEnd;
58 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
60 typedef struct _IO_STATUS_BLOCK
62 union {
63 DWORD Status;
64 PVOID Pointer;
65 } u;
66 ULONG_PTR Information;
67 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
69 typedef enum _FILE_INFORMATION_CLASS {
70 FilePipeLocalInformation = 24
71 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
73 typedef DWORD (WINAPI *PNtQueryInformationFile)
74 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
76 #ifndef PIPE_BUF
77 #define PIPE_BUF 512
78 #endif
80 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
82 static BOOL
83 IsSocketHandle(HANDLE h)
85 WSANETWORKEVENTS ev;
87 if (IsConsoleHandle (h))
88 return FALSE;
90 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
91 WSAEnumNetworkEvents instead distinguishes the two correctly. */
92 ev.lNetworkEvents = 0xDEADBEEF;
93 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
94 return ev.lNetworkEvents != 0xDEADBEEF;
97 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
99 static int
100 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
101 struct bitset *xbits)
103 BOOL read, write, except;
104 int i, ret;
105 INPUT_RECORD *irbuffer;
106 DWORD avail, nbuffer;
107 BOOL bRet;
108 IO_STATUS_BLOCK iosb;
109 FILE_PIPE_LOCAL_INFORMATION fpli;
110 static PNtQueryInformationFile NtQueryInformationFile;
111 static BOOL once_only;
113 read = write = except = FALSE;
114 switch (GetFileType (h))
116 case FILE_TYPE_DISK:
117 read = TRUE;
118 write = TRUE;
119 break;
121 case FILE_TYPE_PIPE:
122 if (!once_only)
124 NtQueryInformationFile = (PNtQueryInformationFile)
125 GetProcAddress (GetModuleHandle ("ntdll.dll"),
126 "NtQueryInformationFile");
127 once_only = TRUE;
130 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
132 if (avail)
133 read = TRUE;
136 else
138 /* It was the write-end of the pipe. Check if it is writable.
139 If NtQueryInformationFile fails, optimistically assume the pipe is
140 writable. This could happen on Win9x, where NtQueryInformationFile
141 is not available, or if we inherit a pipe that doesn't permit
142 FILE_READ_ATTRIBUTES access on the write end (I think this should
143 not happen since WinXP SP2; WINE seems fine too). Otherwise,
144 ensure that enough space is available for atomic writes. */
145 memset (&iosb, 0, sizeof (iosb));
146 memset (&fpli, 0, sizeof (fpli));
148 if (!NtQueryInformationFile
149 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
150 FilePipeLocalInformation)
151 || fpli.WriteQuotaAvailable >= PIPE_BUF
152 || (fpli.OutboundQuota < PIPE_BUF &&
153 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
154 write = TRUE;
156 break;
158 case FILE_TYPE_CHAR:
159 write = TRUE;
160 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
161 break;
163 ret = WaitForSingleObject (h, 0);
164 if (ret == WAIT_OBJECT_0)
166 if (!IsConsoleHandle (h))
168 read = TRUE;
169 break;
172 nbuffer = avail = 0;
173 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
175 /* Screen buffers handles are filtered earlier. */
176 assert (bRet);
177 if (nbuffer == 0)
179 except = TRUE;
180 break;
183 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
184 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
185 if (!bRet || avail == 0)
187 except = TRUE;
188 break;
191 for (i = 0; i < avail; i++)
192 if (irbuffer[i].EventType == KEY_EVENT)
193 read = TRUE;
195 break;
197 default:
198 ret = WaitForSingleObject (h, 0);
199 write = TRUE;
200 if (ret == WAIT_OBJECT_0)
201 read = TRUE;
203 break;
206 ret = 0;
207 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
209 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
210 ret++;
213 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
215 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
216 ret++;
219 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
221 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
222 ret++;
225 return ret;
229 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
230 struct timeval *timeout)
232 static struct timeval tv0;
233 static HANDLE hEvent;
234 HANDLE h, handle_array[FD_SETSIZE + 2];
235 fd_set handle_rfds, handle_wfds, handle_xfds;
236 struct bitset rbits, wbits, xbits;
237 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
238 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
239 MSG msg;
240 int i, fd, rc;
242 if (nfds > FD_SETSIZE)
243 nfds = FD_SETSIZE;
245 if (!timeout)
246 wait_timeout = INFINITE;
247 else
249 wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
251 /* select is also used as a portable usleep. */
252 if (!rfds && !wfds && !xfds)
254 Sleep (wait_timeout);
255 return 0;
259 if (!hEvent)
260 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
262 handle_array[0] = hEvent;
263 nhandles = 1;
264 nsock = 0;
266 /* Copy descriptors to bitsets. At the same time, eliminate
267 bits in the "wrong" direction for console input buffers
268 and screen buffers, because screen buffers are waitable
269 and they will block until a character is available. */
270 memset (&rbits, 0, sizeof (rbits));
271 memset (&wbits, 0, sizeof (wbits));
272 memset (&xbits, 0, sizeof (xbits));
273 memset (anyfds_in, 0, sizeof (anyfds_in));
274 if (rfds)
275 for (i = 0; i < rfds->fd_count; i++)
277 fd = rfds->fd_array[i];
278 h = (HANDLE) _get_osfhandle (fd);
279 if (IsConsoleHandle (h)
280 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
281 continue;
283 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
284 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
286 else
287 rfds = (fd_set *) alloca (sizeof (fd_set));
289 if (wfds)
290 for (i = 0; i < wfds->fd_count; i++)
292 fd = wfds->fd_array[i];
293 h = (HANDLE) _get_osfhandle (fd);
294 if (IsConsoleHandle (h)
295 && GetNumberOfConsoleInputEvents (h, &nbuffer))
296 continue;
298 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
299 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
301 else
302 wfds = (fd_set *) alloca (sizeof (fd_set));
304 if (xfds)
305 for (i = 0; i < xfds->fd_count; i++)
307 fd = xfds->fd_array[i];
308 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
309 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
311 else
312 xfds = (fd_set *) alloca (sizeof (fd_set));
314 /* Zero all the fd_sets, including the application's. */
315 FD_ZERO (rfds);
316 FD_ZERO (wfds);
317 FD_ZERO (xfds);
318 FD_ZERO (&handle_rfds);
319 FD_ZERO (&handle_wfds);
320 FD_ZERO (&handle_xfds);
322 /* Classify handles. Create fd sets for sockets, poll the others. */
323 for (i = 0; i < nfds; i++)
325 WSANETWORKEVENTS ev;
327 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
328 continue;
330 h = (HANDLE) _get_osfhandle (i);
331 if (!h)
333 errno = EBADF;
334 return -1;
337 if (IsSocketHandle (h))
339 int requested = FD_CLOSE;
341 /* See above; socket handles are mapped onto select, but we
342 need to map descriptors to handles. */
343 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
345 requested |= FD_READ | FD_ACCEPT;
346 FD_SET ((SOCKET) h, rfds);
347 FD_SET ((SOCKET) h, &handle_rfds);
349 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
351 requested |= FD_WRITE | FD_CONNECT;
352 FD_SET ((SOCKET) h, wfds);
353 FD_SET ((SOCKET) h, &handle_wfds);
355 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
357 requested |= FD_OOB;
358 FD_SET ((SOCKET) h, xfds);
359 FD_SET ((SOCKET) h, &handle_xfds);
362 WSAEventSelect ((SOCKET) h, hEvent, requested);
363 nsock++;
365 else
367 handle_array[nhandles++] = h;
369 /* Poll now. If we get an event, do not wait below. */
370 if (wait_timeout != 0
371 && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
372 wait_timeout = 0;
376 if (wait_timeout == 0 || nsock == 0)
377 rc = 0;
378 else
380 /* See if we need to wait in the loop below. If any select is ready,
381 do MsgWaitForMultipleObjects anyway to dispatch messages, but
382 no need to call select again. */
383 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
384 if (rc == 0)
386 /* Restore the fd_sets for the other select we do below. */
387 memcpy (&handle_rfds, rfds, sizeof (fd_set));
388 memcpy (&handle_wfds, wfds, sizeof (fd_set));
389 memcpy (&handle_xfds, xfds, sizeof (fd_set));
391 else
392 wait_timeout = 0;
395 for (;;)
397 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
398 wait_timeout, QS_ALLINPUT);
400 if (ret == WAIT_OBJECT_0 + nhandles)
402 /* new input of some other kind */
403 BOOL bRet;
404 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
406 TranslateMessage (&msg);
407 DispatchMessage (&msg);
410 else
411 break;
414 /* If we haven't done it yet, check the status of the sockets. */
415 if (rc == 0 && nsock > 0)
416 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
418 /* Now fill in the results. */
419 FD_ZERO (rfds);
420 FD_ZERO (wfds);
421 FD_ZERO (xfds);
423 /* Place a sentinel at the end of the array. */
424 handle_array[nhandles] = NULL;
425 nhandles = 1;
426 for (i = 0; i < nfds; i++)
428 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
429 continue;
431 h = (HANDLE) _get_osfhandle (i);
432 if (h != handle_array[nhandles])
434 /* Perform handle->descriptor mapping. Don't update rc, as these
435 results are counted in the return value of Winsock's select. */
436 WSAEventSelect ((SOCKET) h, NULL, 0);
437 if (FD_ISSET (h, &handle_rfds))
438 FD_SET (i, rfds);
439 if (FD_ISSET (h, &handle_wfds))
440 FD_SET (i, wfds);
441 if (FD_ISSET (h, &handle_xfds))
442 FD_SET (i, xfds);
444 else
446 /* Not a socket. */
447 nhandles++;
448 win32_poll_handle (h, i, &rbits, &wbits, &xbits);
449 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
451 rc++;
452 FD_SET (i, rfds);
454 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
456 rc++;
457 FD_SET (i, wfds);
459 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
461 rc++;
462 FD_SET (i, xfds);
467 return rc;
470 #else /* ! Native Win32. */
472 #include <sys/select.h>
474 #undef select
477 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
478 struct timeval *timeout)
480 /* Interix 3.5 has a bug: it does not support nfds == 0. */
481 if (nfds == 0)
483 nfds = 1;
484 rfds = NULL;
485 wfds = NULL;
486 xfds = NULL;
488 return select (nfds, rfds, wfds, xfds, timeout);
491 #endif