Use spaces for indentation, not tabs.
[gnulib.git] / lib / select.c
1 /* Emulation for select(2)
2    Contributed by Paolo Bonzini.
3
4    Copyright 2008-2009 Free Software Foundation, Inc.
5
6    This file is part of gnulib.
7
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 2, or (at your option)
11    any later version.
12
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.
17
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.  */
21
22 #include <config.h>
23 #include <alloca.h>
24 #include <assert.h>
25
26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
27 /* Native Win32.  */
28
29 #include <sys/types.h>
30 #include <stdbool.h>
31 #include <errno.h>
32 #include <limits.h>
33
34 #include <winsock2.h>
35 #include <windows.h>
36 #include <io.h>
37 #include <stdio.h>
38 #include <conio.h>
39 #include <time.h>
40
41 struct bitset {
42   unsigned char in[FD_SETSIZE / CHAR_BIT];
43   unsigned char out[FD_SETSIZE / CHAR_BIT];
44 };
45
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;
59
60 typedef struct _IO_STATUS_BLOCK
61 {
62   union {
63     DWORD Status;
64     PVOID Pointer;
65   } u;
66   ULONG_PTR Information;
67 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
68
69 typedef enum _FILE_INFORMATION_CLASS {
70   FilePipeLocalInformation = 24
71 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
72
73 typedef DWORD (WINAPI *PNtQueryInformationFile)
74          (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
75
76 #ifndef PIPE_BUF
77 #define PIPE_BUF        512
78 #endif
79
80 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
81
82 static BOOL
83 IsSocketHandle(HANDLE h)
84 {
85   WSANETWORKEVENTS ev;
86
87   if (IsConsoleHandle (h))
88     return FALSE;
89
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;
95 }
96
97 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H).  */
98
99 static int
100 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
101                    struct bitset *xbits)
102 {
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;
112
113   read = write = except = FALSE;
114   switch (GetFileType (h))
115     {
116     case FILE_TYPE_DISK:
117       read = TRUE;
118       write = TRUE;
119       break;
120
121     case FILE_TYPE_PIPE:
122       if (!once_only)
123         {
124           NtQueryInformationFile = (PNtQueryInformationFile)
125             GetProcAddress (GetModuleHandle ("ntdll.dll"),
126                             "NtQueryInformationFile");
127           once_only = TRUE;
128         }
129
130       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
131         {
132           if (avail)
133             read = TRUE;
134         }
135
136       else
137         {
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));
147
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;
155         }
156       break;
157
158     case FILE_TYPE_CHAR:
159       write = TRUE;
160       if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
161         break;
162
163       ret = WaitForSingleObject (h, 0);
164       if (ret == WAIT_OBJECT_0)
165         {
166           if (!IsConsoleHandle (h))
167             {
168               read = TRUE;
169               break;
170             }
171
172           nbuffer = avail = 0;
173           bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
174
175           /* Screen buffers handles are filtered earlier.  */
176           assert (bRet);
177           if (nbuffer == 0)
178             {
179               except = TRUE;
180               break;
181             }
182
183           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
184           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
185           if (!bRet || avail == 0)
186             {
187               except = TRUE;
188               break;
189             }
190
191           for (i = 0; i < avail; i++)
192             if (irbuffer[i].EventType == KEY_EVENT)
193               read = TRUE;
194         }
195       break;
196
197     default:
198       ret = WaitForSingleObject (h, 0);
199       write = TRUE;
200       if (ret == WAIT_OBJECT_0)
201         read = TRUE;
202
203       break;
204     }
205
206   ret = 0;
207   if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
208     {
209       rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
210       ret++;
211     }
212
213   if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
214     {
215       wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
216       ret++;
217     }
218
219   if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
220     {
221       xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
222       ret++;
223     }
224
225   return ret;
226 }
227
228 int
229 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
230             struct timeval *timeout)
231 {
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;
241
242   if (nfds > FD_SETSIZE)
243     nfds = FD_SETSIZE;
244
245   if (!timeout)
246     wait_timeout = INFINITE;
247   else
248     {
249       wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
250
251       /* select is also used as a portable usleep.  */
252       if (!rfds && !wfds && !xfds)
253         {
254           Sleep (wait_timeout);
255           return 0;
256         }
257     }
258
259   if (!hEvent)
260     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
261
262   handle_array[0] = hEvent;
263   nhandles = 1;
264   nsock = 0;
265
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++)
276       {
277         fd = rfds->fd_array[i];
278         h = (HANDLE) _get_osfhandle (fd);
279         if (IsConsoleHandle (h)
280             && !GetNumberOfConsoleInputEvents (h, &nbuffer))
281           continue;
282
283         rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
284         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
285       }
286   else
287     rfds = (fd_set *) alloca (sizeof (fd_set));
288
289   if (wfds)
290     for (i = 0; i < wfds->fd_count; i++)
291       {
292         fd = wfds->fd_array[i];
293         h = (HANDLE) _get_osfhandle (fd);
294         if (IsConsoleHandle (h)
295             && GetNumberOfConsoleInputEvents (h, &nbuffer))
296           continue;
297
298         wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
299         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
300       }
301   else
302     wfds = (fd_set *) alloca (sizeof (fd_set));
303
304   if (xfds)
305     for (i = 0; i < xfds->fd_count; i++)
306       {
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));
310       }
311   else
312     xfds = (fd_set *) alloca (sizeof (fd_set));
313
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);
321
322   /* Classify handles.  Create fd sets for sockets, poll the others. */
323   for (i = 0; i < nfds; i++)
324     {
325       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
326         continue;
327
328       h = (HANDLE) _get_osfhandle (i);
329       if (!h)
330         {
331           errno = EBADF;
332           return -1;
333         }
334
335       if (IsSocketHandle (h))
336         {
337           int requested = FD_CLOSE;
338
339           /* See above; socket handles are mapped onto select, but we
340              need to map descriptors to handles.  */
341           if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
342             {
343               requested |= FD_READ | FD_ACCEPT;
344               FD_SET ((SOCKET) h, rfds);
345               FD_SET ((SOCKET) h, &handle_rfds);
346             }
347           if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
348             {
349               requested |= FD_WRITE | FD_CONNECT;
350               FD_SET ((SOCKET) h, wfds);
351               FD_SET ((SOCKET) h, &handle_wfds);
352             }
353           if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
354             {
355               requested |= FD_OOB;
356               FD_SET ((SOCKET) h, xfds);
357               FD_SET ((SOCKET) h, &handle_xfds);
358             }
359
360           WSAEventSelect ((SOCKET) h, hEvent, requested);
361           nsock++;
362         }
363       else
364         {
365           handle_array[nhandles++] = h;
366
367           /* Poll now.  If we get an event, do not wait below.  */
368           if (wait_timeout != 0
369               && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
370             wait_timeout = 0;
371         }
372     }
373
374   if (wait_timeout == 0 || nsock == 0)
375     rc = 0;
376   else
377     {
378       /* See if we need to wait in the loop below.  If any select is ready,
379          do MsgWaitForMultipleObjects anyway to dispatch messages, but
380          no need to call select again.  */
381       rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
382       if (rc == 0)
383         {
384           /* Restore the fd_sets for the other select we do below.  */
385           memcpy (&handle_rfds, rfds, sizeof (fd_set));
386           memcpy (&handle_wfds, wfds, sizeof (fd_set));
387           memcpy (&handle_xfds, xfds, sizeof (fd_set));
388         }
389       else
390         wait_timeout = 0;
391     }
392
393   for (;;)
394     {
395       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
396                                        wait_timeout, QS_ALLINPUT);
397
398       if (ret == WAIT_OBJECT_0 + nhandles)
399         {
400           /* new input of some other kind */
401           BOOL bRet;
402           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
403             {
404               TranslateMessage (&msg);
405               DispatchMessage (&msg);
406             }
407         }
408       else
409         break;
410     }
411
412   /* If we haven't done it yet, check the status of the sockets.  */
413   if (rc == 0 && nsock > 0)
414     rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
415
416   /* Now fill in the results.  */
417   FD_ZERO (rfds);
418   FD_ZERO (wfds);
419   FD_ZERO (xfds);
420
421   /* Place a sentinel at the end of the array.  */
422   handle_array[nhandles] = NULL;
423   nhandles = 1;
424   for (i = 0; i < nfds; i++)
425     {
426       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
427         continue;
428
429       h = (HANDLE) _get_osfhandle (i);
430       if (h != handle_array[nhandles])
431         {
432           /* Perform handle->descriptor mapping.  Don't update rc, as these
433              results are counted in the return value of Winsock's select.  */
434           WSAEventSelect ((SOCKET) h, NULL, 0);
435           if (FD_ISSET (h, &handle_rfds))
436             FD_SET (i, rfds);
437           if (FD_ISSET (h, &handle_wfds))
438             FD_SET (i, wfds);
439           if (FD_ISSET (h, &handle_xfds))
440             FD_SET (i, xfds);
441         }
442       else
443         {
444           /* Not a socket.  */
445           nhandles++;
446           win32_poll_handle (h, i, &rbits, &wbits, &xbits);
447           if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
448             {
449               rc++;
450               FD_SET (i, rfds);
451             }
452           if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
453             {
454               rc++;
455               FD_SET (i, wfds);
456             }
457           if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
458             {
459               rc++;
460               FD_SET (i, xfds);
461             }
462         }
463     }
464
465   return rc;
466 }
467
468 #else /* ! Native Win32.  */
469
470 #include <sys/select.h>
471
472 #undef select
473
474 int
475 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
476             struct timeval *timeout)
477 {
478   /* Interix 3.5 has a bug: it does not support nfds == 0.  */
479   if (nfds == 0)
480     {
481       nfds = 1;
482       rfds = NULL;
483       wfds = NULL;
484       xfds = NULL;
485     }
486   return select (nfds, rfds, wfds, xfds, timeout);
487 }
488
489 #endif