xref: /netbsd-src/external/gpl3/gdb/dist/gnulib/import/select.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
1*4b169a6bSchristos /* Emulation for select(2)
2*4b169a6bSchristos    Contributed by Paolo Bonzini.
3*4b169a6bSchristos 
4*4b169a6bSchristos    Copyright 2008-2022 Free Software Foundation, Inc.
5*4b169a6bSchristos 
6*4b169a6bSchristos    This file is part of gnulib.
7*4b169a6bSchristos 
8*4b169a6bSchristos    This file is free software: you can redistribute it and/or modify
9*4b169a6bSchristos    it under the terms of the GNU Lesser General Public License as
10*4b169a6bSchristos    published by the Free Software Foundation; either version 2.1 of the
11*4b169a6bSchristos    License, or (at your option) any later version.
12*4b169a6bSchristos 
13*4b169a6bSchristos    This file is distributed in the hope that it will be useful,
14*4b169a6bSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*4b169a6bSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*4b169a6bSchristos    GNU Lesser General Public License for more details.
17*4b169a6bSchristos 
18*4b169a6bSchristos    You should have received a copy of the GNU Lesser General Public License
19*4b169a6bSchristos    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
20*4b169a6bSchristos 
21*4b169a6bSchristos #include <config.h>
22*4b169a6bSchristos 
23*4b169a6bSchristos /* Specification.  */
24*4b169a6bSchristos #include <sys/select.h>
25*4b169a6bSchristos 
26*4b169a6bSchristos #if defined _WIN32 && ! defined __CYGWIN__
27*4b169a6bSchristos /* Native Windows.  */
28*4b169a6bSchristos 
29*4b169a6bSchristos #include <alloca.h>
30*4b169a6bSchristos #include <assert.h>
31*4b169a6bSchristos #include <sys/types.h>
32*4b169a6bSchristos #include <errno.h>
33*4b169a6bSchristos #include <limits.h>
34*4b169a6bSchristos 
35*4b169a6bSchristos #include <winsock2.h>
36*4b169a6bSchristos #include <windows.h>
37*4b169a6bSchristos #include <io.h>
38*4b169a6bSchristos #include <stdio.h>
39*4b169a6bSchristos #include <conio.h>
40*4b169a6bSchristos #include <time.h>
41*4b169a6bSchristos 
42*4b169a6bSchristos /* Get the overridden 'struct timeval'.  */
43*4b169a6bSchristos #include <sys/time.h>
44*4b169a6bSchristos 
45*4b169a6bSchristos #if GNULIB_MSVC_NOTHROW
46*4b169a6bSchristos # include "msvc-nothrow.h"
47*4b169a6bSchristos #else
48*4b169a6bSchristos # include <io.h>
49*4b169a6bSchristos #endif
50*4b169a6bSchristos 
51*4b169a6bSchristos #undef select
52*4b169a6bSchristos 
53*4b169a6bSchristos /* Don't assume that UNICODE is not defined.  */
54*4b169a6bSchristos #undef GetModuleHandle
55*4b169a6bSchristos #define GetModuleHandle GetModuleHandleA
56*4b169a6bSchristos #undef PeekConsoleInput
57*4b169a6bSchristos #define PeekConsoleInput PeekConsoleInputA
58*4b169a6bSchristos #undef CreateEvent
59*4b169a6bSchristos #define CreateEvent CreateEventA
60*4b169a6bSchristos #undef PeekMessage
61*4b169a6bSchristos #define PeekMessage PeekMessageA
62*4b169a6bSchristos #undef DispatchMessage
63*4b169a6bSchristos #define DispatchMessage DispatchMessageA
64*4b169a6bSchristos 
65*4b169a6bSchristos /* Avoid warnings from gcc -Wcast-function-type.  */
66*4b169a6bSchristos #define GetProcAddress \
67*4b169a6bSchristos   (void *) GetProcAddress
68*4b169a6bSchristos 
69*4b169a6bSchristos struct bitset {
70*4b169a6bSchristos   unsigned char in[FD_SETSIZE / CHAR_BIT];
71*4b169a6bSchristos   unsigned char out[FD_SETSIZE / CHAR_BIT];
72*4b169a6bSchristos };
73*4b169a6bSchristos 
74*4b169a6bSchristos /* Declare data structures for ntdll functions.  */
75*4b169a6bSchristos typedef struct _FILE_PIPE_LOCAL_INFORMATION {
76*4b169a6bSchristos   ULONG NamedPipeType;
77*4b169a6bSchristos   ULONG NamedPipeConfiguration;
78*4b169a6bSchristos   ULONG MaximumInstances;
79*4b169a6bSchristos   ULONG CurrentInstances;
80*4b169a6bSchristos   ULONG InboundQuota;
81*4b169a6bSchristos   ULONG ReadDataAvailable;
82*4b169a6bSchristos   ULONG OutboundQuota;
83*4b169a6bSchristos   ULONG WriteQuotaAvailable;
84*4b169a6bSchristos   ULONG NamedPipeState;
85*4b169a6bSchristos   ULONG NamedPipeEnd;
86*4b169a6bSchristos } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
87*4b169a6bSchristos 
88*4b169a6bSchristos typedef struct _IO_STATUS_BLOCK
89*4b169a6bSchristos {
90*4b169a6bSchristos   union {
91*4b169a6bSchristos     DWORD Status;
92*4b169a6bSchristos     PVOID Pointer;
93*4b169a6bSchristos   } u;
94*4b169a6bSchristos   ULONG_PTR Information;
95*4b169a6bSchristos } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
96*4b169a6bSchristos 
97*4b169a6bSchristos typedef enum _FILE_INFORMATION_CLASS {
98*4b169a6bSchristos   FilePipeLocalInformation = 24
99*4b169a6bSchristos } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
100*4b169a6bSchristos 
101*4b169a6bSchristos typedef DWORD (WINAPI *PNtQueryInformationFile)
102*4b169a6bSchristos          (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
103*4b169a6bSchristos 
104*4b169a6bSchristos #ifndef PIPE_BUF
105*4b169a6bSchristos #define PIPE_BUF        512
106*4b169a6bSchristos #endif
107*4b169a6bSchristos 
IsConsoleHandle(HANDLE h)108*4b169a6bSchristos static BOOL IsConsoleHandle (HANDLE h)
109*4b169a6bSchristos {
110*4b169a6bSchristos   DWORD mode;
111*4b169a6bSchristos   return GetConsoleMode (h, &mode) != 0;
112*4b169a6bSchristos }
113*4b169a6bSchristos 
114*4b169a6bSchristos static BOOL
IsSocketHandle(HANDLE h)115*4b169a6bSchristos IsSocketHandle (HANDLE h)
116*4b169a6bSchristos {
117*4b169a6bSchristos   WSANETWORKEVENTS ev;
118*4b169a6bSchristos 
119*4b169a6bSchristos   if (IsConsoleHandle (h))
120*4b169a6bSchristos     return FALSE;
121*4b169a6bSchristos 
122*4b169a6bSchristos   /* Under Wine, it seems that getsockopt returns 0 for pipes too.
123*4b169a6bSchristos      WSAEnumNetworkEvents instead distinguishes the two correctly.  */
124*4b169a6bSchristos   ev.lNetworkEvents = 0xDEADBEEF;
125*4b169a6bSchristos   WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
126*4b169a6bSchristos   return ev.lNetworkEvents != 0xDEADBEEF;
127*4b169a6bSchristos }
128*4b169a6bSchristos 
129*4b169a6bSchristos /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
130*4b169a6bSchristos    H).  */
131*4b169a6bSchristos 
132*4b169a6bSchristos static int
windows_poll_handle(HANDLE h,int fd,struct bitset * rbits,struct bitset * wbits,struct bitset * xbits)133*4b169a6bSchristos windows_poll_handle (HANDLE h, int fd,
134*4b169a6bSchristos                      struct bitset *rbits,
135*4b169a6bSchristos                      struct bitset *wbits,
136*4b169a6bSchristos                      struct bitset *xbits)
137*4b169a6bSchristos {
138*4b169a6bSchristos   BOOL read, write, except;
139*4b169a6bSchristos   int i, ret;
140*4b169a6bSchristos   INPUT_RECORD *irbuffer;
141*4b169a6bSchristos   DWORD avail, nbuffer;
142*4b169a6bSchristos   BOOL bRet;
143*4b169a6bSchristos   IO_STATUS_BLOCK iosb;
144*4b169a6bSchristos   FILE_PIPE_LOCAL_INFORMATION fpli;
145*4b169a6bSchristos   static PNtQueryInformationFile NtQueryInformationFile;
146*4b169a6bSchristos   static BOOL once_only;
147*4b169a6bSchristos 
148*4b169a6bSchristos   read = write = except = FALSE;
149*4b169a6bSchristos   switch (GetFileType (h))
150*4b169a6bSchristos     {
151*4b169a6bSchristos     case FILE_TYPE_DISK:
152*4b169a6bSchristos       read = TRUE;
153*4b169a6bSchristos       write = TRUE;
154*4b169a6bSchristos       break;
155*4b169a6bSchristos 
156*4b169a6bSchristos     case FILE_TYPE_PIPE:
157*4b169a6bSchristos       if (!once_only)
158*4b169a6bSchristos         {
159*4b169a6bSchristos           NtQueryInformationFile = (PNtQueryInformationFile)
160*4b169a6bSchristos             GetProcAddress (GetModuleHandle ("ntdll.dll"),
161*4b169a6bSchristos                             "NtQueryInformationFile");
162*4b169a6bSchristos           once_only = TRUE;
163*4b169a6bSchristos         }
164*4b169a6bSchristos 
165*4b169a6bSchristos       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
166*4b169a6bSchristos         {
167*4b169a6bSchristos           if (avail)
168*4b169a6bSchristos             read = TRUE;
169*4b169a6bSchristos         }
170*4b169a6bSchristos       else if (GetLastError () == ERROR_BROKEN_PIPE)
171*4b169a6bSchristos         ;
172*4b169a6bSchristos 
173*4b169a6bSchristos       else
174*4b169a6bSchristos         {
175*4b169a6bSchristos           /* It was the write-end of the pipe.  Check if it is writable.
176*4b169a6bSchristos              If NtQueryInformationFile fails, optimistically assume the pipe is
177*4b169a6bSchristos              writable.  This could happen on Windows 9x, where
178*4b169a6bSchristos              NtQueryInformationFile is not available, or if we inherit a pipe
179*4b169a6bSchristos              that doesn't permit FILE_READ_ATTRIBUTES access on the write end
180*4b169a6bSchristos              (I think this should not happen since Windows XP SP2; WINE seems
181*4b169a6bSchristos              fine too).  Otherwise, ensure that enough space is available for
182*4b169a6bSchristos              atomic writes.  */
183*4b169a6bSchristos           memset (&iosb, 0, sizeof (iosb));
184*4b169a6bSchristos           memset (&fpli, 0, sizeof (fpli));
185*4b169a6bSchristos 
186*4b169a6bSchristos           if (!NtQueryInformationFile
187*4b169a6bSchristos               || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
188*4b169a6bSchristos                                          FilePipeLocalInformation)
189*4b169a6bSchristos               || fpli.WriteQuotaAvailable >= PIPE_BUF
190*4b169a6bSchristos               || (fpli.OutboundQuota < PIPE_BUF &&
191*4b169a6bSchristos                   fpli.WriteQuotaAvailable == fpli.OutboundQuota))
192*4b169a6bSchristos             write = TRUE;
193*4b169a6bSchristos         }
194*4b169a6bSchristos       break;
195*4b169a6bSchristos 
196*4b169a6bSchristos     case FILE_TYPE_CHAR:
197*4b169a6bSchristos       write = TRUE;
198*4b169a6bSchristos       if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
199*4b169a6bSchristos         break;
200*4b169a6bSchristos 
201*4b169a6bSchristos       ret = WaitForSingleObject (h, 0);
202*4b169a6bSchristos       if (ret == WAIT_OBJECT_0)
203*4b169a6bSchristos         {
204*4b169a6bSchristos           if (!IsConsoleHandle (h))
205*4b169a6bSchristos             {
206*4b169a6bSchristos               read = TRUE;
207*4b169a6bSchristos               break;
208*4b169a6bSchristos             }
209*4b169a6bSchristos 
210*4b169a6bSchristos           nbuffer = avail = 0;
211*4b169a6bSchristos           bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
212*4b169a6bSchristos 
213*4b169a6bSchristos           /* Screen buffers handles are filtered earlier.  */
214*4b169a6bSchristos           assert (bRet);
215*4b169a6bSchristos           if (nbuffer == 0)
216*4b169a6bSchristos             {
217*4b169a6bSchristos               except = TRUE;
218*4b169a6bSchristos               break;
219*4b169a6bSchristos             }
220*4b169a6bSchristos 
221*4b169a6bSchristos           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
222*4b169a6bSchristos           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
223*4b169a6bSchristos           if (!bRet || avail == 0)
224*4b169a6bSchristos             {
225*4b169a6bSchristos               except = TRUE;
226*4b169a6bSchristos               break;
227*4b169a6bSchristos             }
228*4b169a6bSchristos 
229*4b169a6bSchristos           for (i = 0; i < avail; i++)
230*4b169a6bSchristos             if (irbuffer[i].EventType == KEY_EVENT)
231*4b169a6bSchristos               read = TRUE;
232*4b169a6bSchristos         }
233*4b169a6bSchristos       break;
234*4b169a6bSchristos 
235*4b169a6bSchristos     default:
236*4b169a6bSchristos       ret = WaitForSingleObject (h, 0);
237*4b169a6bSchristos       write = TRUE;
238*4b169a6bSchristos       if (ret == WAIT_OBJECT_0)
239*4b169a6bSchristos         read = TRUE;
240*4b169a6bSchristos 
241*4b169a6bSchristos       break;
242*4b169a6bSchristos     }
243*4b169a6bSchristos 
244*4b169a6bSchristos   ret = 0;
245*4b169a6bSchristos   if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
246*4b169a6bSchristos     {
247*4b169a6bSchristos       rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
248*4b169a6bSchristos       ret++;
249*4b169a6bSchristos     }
250*4b169a6bSchristos 
251*4b169a6bSchristos   if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
252*4b169a6bSchristos     {
253*4b169a6bSchristos       wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
254*4b169a6bSchristos       ret++;
255*4b169a6bSchristos     }
256*4b169a6bSchristos 
257*4b169a6bSchristos   if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
258*4b169a6bSchristos     {
259*4b169a6bSchristos       xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
260*4b169a6bSchristos       ret++;
261*4b169a6bSchristos     }
262*4b169a6bSchristos 
263*4b169a6bSchristos   return ret;
264*4b169a6bSchristos }
265*4b169a6bSchristos 
266*4b169a6bSchristos int
rpl_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * xfds,struct timeval * timeout)267*4b169a6bSchristos rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
268*4b169a6bSchristos             struct timeval *timeout)
269*4b169a6bSchristos #undef timeval
270*4b169a6bSchristos {
271*4b169a6bSchristos   static struct timeval tv0;
272*4b169a6bSchristos   static HANDLE hEvent;
273*4b169a6bSchristos   HANDLE h, handle_array[FD_SETSIZE + 2];
274*4b169a6bSchristos   fd_set handle_rfds, handle_wfds, handle_xfds;
275*4b169a6bSchristos   struct bitset rbits, wbits, xbits;
276*4b169a6bSchristos   unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
277*4b169a6bSchristos   DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
278*4b169a6bSchristos   MSG msg;
279*4b169a6bSchristos   int i, fd, rc;
280*4b169a6bSchristos   clock_t tend;
281*4b169a6bSchristos 
282*4b169a6bSchristos   if (nfds > FD_SETSIZE)
283*4b169a6bSchristos     nfds = FD_SETSIZE;
284*4b169a6bSchristos 
285*4b169a6bSchristos   if (!timeout)
286*4b169a6bSchristos     wait_timeout = INFINITE;
287*4b169a6bSchristos   else
288*4b169a6bSchristos     {
289*4b169a6bSchristos       wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
290*4b169a6bSchristos 
291*4b169a6bSchristos       /* select is also used as a portable usleep.  */
292*4b169a6bSchristos       if (!rfds && !wfds && !xfds)
293*4b169a6bSchristos         {
294*4b169a6bSchristos           Sleep (wait_timeout);
295*4b169a6bSchristos           return 0;
296*4b169a6bSchristos         }
297*4b169a6bSchristos     }
298*4b169a6bSchristos 
299*4b169a6bSchristos   if (!hEvent)
300*4b169a6bSchristos     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
301*4b169a6bSchristos 
302*4b169a6bSchristos   handle_array[0] = hEvent;
303*4b169a6bSchristos   nhandles = 1;
304*4b169a6bSchristos   nsock = 0;
305*4b169a6bSchristos 
306*4b169a6bSchristos   /* Copy descriptors to bitsets.  At the same time, eliminate
307*4b169a6bSchristos      bits in the "wrong" direction for console input buffers
308*4b169a6bSchristos      and screen buffers, because screen buffers are waitable
309*4b169a6bSchristos      and they will block until a character is available.  */
310*4b169a6bSchristos   memset (&rbits, 0, sizeof (rbits));
311*4b169a6bSchristos   memset (&wbits, 0, sizeof (wbits));
312*4b169a6bSchristos   memset (&xbits, 0, sizeof (xbits));
313*4b169a6bSchristos   memset (anyfds_in, 0, sizeof (anyfds_in));
314*4b169a6bSchristos   if (rfds)
315*4b169a6bSchristos     for (i = 0; i < rfds->fd_count; i++)
316*4b169a6bSchristos       {
317*4b169a6bSchristos         fd = rfds->fd_array[i];
318*4b169a6bSchristos         h = (HANDLE) _get_osfhandle (fd);
319*4b169a6bSchristos         if (IsConsoleHandle (h)
320*4b169a6bSchristos             && !GetNumberOfConsoleInputEvents (h, &nbuffer))
321*4b169a6bSchristos           continue;
322*4b169a6bSchristos 
323*4b169a6bSchristos         rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
324*4b169a6bSchristos         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
325*4b169a6bSchristos       }
326*4b169a6bSchristos   else
327*4b169a6bSchristos     rfds = (fd_set *) alloca (sizeof (fd_set));
328*4b169a6bSchristos 
329*4b169a6bSchristos   if (wfds)
330*4b169a6bSchristos     for (i = 0; i < wfds->fd_count; i++)
331*4b169a6bSchristos       {
332*4b169a6bSchristos         fd = wfds->fd_array[i];
333*4b169a6bSchristos         h = (HANDLE) _get_osfhandle (fd);
334*4b169a6bSchristos         if (IsConsoleHandle (h)
335*4b169a6bSchristos             && GetNumberOfConsoleInputEvents (h, &nbuffer))
336*4b169a6bSchristos           continue;
337*4b169a6bSchristos 
338*4b169a6bSchristos         wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
339*4b169a6bSchristos         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
340*4b169a6bSchristos       }
341*4b169a6bSchristos   else
342*4b169a6bSchristos     wfds = (fd_set *) alloca (sizeof (fd_set));
343*4b169a6bSchristos 
344*4b169a6bSchristos   if (xfds)
345*4b169a6bSchristos     for (i = 0; i < xfds->fd_count; i++)
346*4b169a6bSchristos       {
347*4b169a6bSchristos         fd = xfds->fd_array[i];
348*4b169a6bSchristos         xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
349*4b169a6bSchristos         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
350*4b169a6bSchristos       }
351*4b169a6bSchristos   else
352*4b169a6bSchristos     xfds = (fd_set *) alloca (sizeof (fd_set));
353*4b169a6bSchristos 
354*4b169a6bSchristos   /* Zero all the fd_sets, including the application's.  */
355*4b169a6bSchristos   FD_ZERO (rfds);
356*4b169a6bSchristos   FD_ZERO (wfds);
357*4b169a6bSchristos   FD_ZERO (xfds);
358*4b169a6bSchristos   FD_ZERO (&handle_rfds);
359*4b169a6bSchristos   FD_ZERO (&handle_wfds);
360*4b169a6bSchristos   FD_ZERO (&handle_xfds);
361*4b169a6bSchristos 
362*4b169a6bSchristos   /* Classify handles.  Create fd sets for sockets, poll the others. */
363*4b169a6bSchristos   for (i = 0; i < nfds; i++)
364*4b169a6bSchristos     {
365*4b169a6bSchristos       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
366*4b169a6bSchristos         continue;
367*4b169a6bSchristos 
368*4b169a6bSchristos       h = (HANDLE) _get_osfhandle (i);
369*4b169a6bSchristos       if (!h)
370*4b169a6bSchristos         {
371*4b169a6bSchristos           errno = EBADF;
372*4b169a6bSchristos           return -1;
373*4b169a6bSchristos         }
374*4b169a6bSchristos 
375*4b169a6bSchristos       if (IsSocketHandle (h))
376*4b169a6bSchristos         {
377*4b169a6bSchristos           int requested = FD_CLOSE;
378*4b169a6bSchristos 
379*4b169a6bSchristos           /* See above; socket handles are mapped onto select, but we
380*4b169a6bSchristos              need to map descriptors to handles.  */
381*4b169a6bSchristos           if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
382*4b169a6bSchristos             {
383*4b169a6bSchristos               requested |= FD_READ | FD_ACCEPT;
384*4b169a6bSchristos               FD_SET ((SOCKET) h, rfds);
385*4b169a6bSchristos               FD_SET ((SOCKET) h, &handle_rfds);
386*4b169a6bSchristos             }
387*4b169a6bSchristos           if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
388*4b169a6bSchristos             {
389*4b169a6bSchristos               requested |= FD_WRITE | FD_CONNECT;
390*4b169a6bSchristos               FD_SET ((SOCKET) h, wfds);
391*4b169a6bSchristos               FD_SET ((SOCKET) h, &handle_wfds);
392*4b169a6bSchristos             }
393*4b169a6bSchristos           if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
394*4b169a6bSchristos             {
395*4b169a6bSchristos               requested |= FD_OOB;
396*4b169a6bSchristos               FD_SET ((SOCKET) h, xfds);
397*4b169a6bSchristos               FD_SET ((SOCKET) h, &handle_xfds);
398*4b169a6bSchristos             }
399*4b169a6bSchristos 
400*4b169a6bSchristos           WSAEventSelect ((SOCKET) h, hEvent, requested);
401*4b169a6bSchristos           nsock++;
402*4b169a6bSchristos         }
403*4b169a6bSchristos       else
404*4b169a6bSchristos         {
405*4b169a6bSchristos           handle_array[nhandles++] = h;
406*4b169a6bSchristos 
407*4b169a6bSchristos           /* Poll now.  If we get an event, do not wait below.  */
408*4b169a6bSchristos           if (wait_timeout != 0
409*4b169a6bSchristos               && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
410*4b169a6bSchristos             wait_timeout = 0;
411*4b169a6bSchristos         }
412*4b169a6bSchristos     }
413*4b169a6bSchristos 
414*4b169a6bSchristos   /* Place a sentinel at the end of the array.  */
415*4b169a6bSchristos   handle_array[nhandles] = NULL;
416*4b169a6bSchristos 
417*4b169a6bSchristos   /* When will the waiting period expire?  */
418*4b169a6bSchristos   if (wait_timeout != INFINITE)
419*4b169a6bSchristos     tend = clock () + wait_timeout;
420*4b169a6bSchristos 
421*4b169a6bSchristos restart:
422*4b169a6bSchristos   if (wait_timeout == 0 || nsock == 0)
423*4b169a6bSchristos     rc = 0;
424*4b169a6bSchristos   else
425*4b169a6bSchristos     {
426*4b169a6bSchristos       /* See if we need to wait in the loop below.  If any select is ready,
427*4b169a6bSchristos          do MsgWaitForMultipleObjects anyway to dispatch messages, but
428*4b169a6bSchristos          no need to call select again.  */
429*4b169a6bSchristos       rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
430*4b169a6bSchristos       if (rc == 0)
431*4b169a6bSchristos         {
432*4b169a6bSchristos           /* Restore the fd_sets for the other select we do below.  */
433*4b169a6bSchristos           memcpy (&handle_rfds, rfds, sizeof (fd_set));
434*4b169a6bSchristos           memcpy (&handle_wfds, wfds, sizeof (fd_set));
435*4b169a6bSchristos           memcpy (&handle_xfds, xfds, sizeof (fd_set));
436*4b169a6bSchristos         }
437*4b169a6bSchristos       else
438*4b169a6bSchristos         wait_timeout = 0;
439*4b169a6bSchristos     }
440*4b169a6bSchristos 
441*4b169a6bSchristos   /* How much is left to wait?  */
442*4b169a6bSchristos   if (wait_timeout != INFINITE)
443*4b169a6bSchristos     {
444*4b169a6bSchristos       clock_t tnow = clock ();
445*4b169a6bSchristos       if (tend >= tnow)
446*4b169a6bSchristos         wait_timeout = tend - tnow;
447*4b169a6bSchristos       else
448*4b169a6bSchristos         wait_timeout = 0;
449*4b169a6bSchristos     }
450*4b169a6bSchristos 
451*4b169a6bSchristos   for (;;)
452*4b169a6bSchristos     {
453*4b169a6bSchristos       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
454*4b169a6bSchristos                                        wait_timeout, QS_ALLINPUT);
455*4b169a6bSchristos 
456*4b169a6bSchristos       if (ret == WAIT_OBJECT_0 + nhandles)
457*4b169a6bSchristos         {
458*4b169a6bSchristos           /* new input of some other kind */
459*4b169a6bSchristos           BOOL bRet;
460*4b169a6bSchristos           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
461*4b169a6bSchristos             {
462*4b169a6bSchristos               TranslateMessage (&msg);
463*4b169a6bSchristos               DispatchMessage (&msg);
464*4b169a6bSchristos             }
465*4b169a6bSchristos         }
466*4b169a6bSchristos       else
467*4b169a6bSchristos         break;
468*4b169a6bSchristos     }
469*4b169a6bSchristos 
470*4b169a6bSchristos   /* If we haven't done it yet, check the status of the sockets.  */
471*4b169a6bSchristos   if (rc == 0 && nsock > 0)
472*4b169a6bSchristos     rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
473*4b169a6bSchristos 
474*4b169a6bSchristos   if (nhandles > 1)
475*4b169a6bSchristos     {
476*4b169a6bSchristos       /* Count results that are not counted in the return value of select.  */
477*4b169a6bSchristos       nhandles = 1;
478*4b169a6bSchristos       for (i = 0; i < nfds; i++)
479*4b169a6bSchristos         {
480*4b169a6bSchristos           if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
481*4b169a6bSchristos             continue;
482*4b169a6bSchristos 
483*4b169a6bSchristos           h = (HANDLE) _get_osfhandle (i);
484*4b169a6bSchristos           if (h == handle_array[nhandles])
485*4b169a6bSchristos             {
486*4b169a6bSchristos               /* Not a socket.  */
487*4b169a6bSchristos               nhandles++;
488*4b169a6bSchristos               windows_poll_handle (h, i, &rbits, &wbits, &xbits);
489*4b169a6bSchristos               if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
490*4b169a6bSchristos                   || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
491*4b169a6bSchristos                   || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
492*4b169a6bSchristos                 rc++;
493*4b169a6bSchristos             }
494*4b169a6bSchristos         }
495*4b169a6bSchristos 
496*4b169a6bSchristos       if (rc == 0
497*4b169a6bSchristos           && (wait_timeout == INFINITE
498*4b169a6bSchristos               /* If NHANDLES > 1, but no bits are set, it means we've
499*4b169a6bSchristos                  been told incorrectly that some handle was signaled.
500*4b169a6bSchristos                  This happens with anonymous pipes, which always cause
501*4b169a6bSchristos                  MsgWaitForMultipleObjects to exit immediately, but no
502*4b169a6bSchristos                  data is found ready to be read by windows_poll_handle.
503*4b169a6bSchristos                  To avoid a total failure (whereby we return zero and
504*4b169a6bSchristos                  don't wait at all), let's poll in a more busy loop.  */
505*4b169a6bSchristos               || (wait_timeout != 0 && nhandles > 1)))
506*4b169a6bSchristos         {
507*4b169a6bSchristos           /* Sleep 1 millisecond to avoid busy wait and retry with the
508*4b169a6bSchristos              original fd_sets.  */
509*4b169a6bSchristos           memcpy (&handle_rfds, rfds, sizeof (fd_set));
510*4b169a6bSchristos           memcpy (&handle_wfds, wfds, sizeof (fd_set));
511*4b169a6bSchristos           memcpy (&handle_xfds, xfds, sizeof (fd_set));
512*4b169a6bSchristos           SleepEx (1, TRUE);
513*4b169a6bSchristos           goto restart;
514*4b169a6bSchristos         }
515*4b169a6bSchristos       if (timeout && wait_timeout == 0 && rc == 0)
516*4b169a6bSchristos         timeout->tv_sec = timeout->tv_usec = 0;
517*4b169a6bSchristos     }
518*4b169a6bSchristos 
519*4b169a6bSchristos   /* Now fill in the results.  */
520*4b169a6bSchristos   FD_ZERO (rfds);
521*4b169a6bSchristos   FD_ZERO (wfds);
522*4b169a6bSchristos   FD_ZERO (xfds);
523*4b169a6bSchristos   nhandles = 1;
524*4b169a6bSchristos   for (i = 0; i < nfds; i++)
525*4b169a6bSchristos     {
526*4b169a6bSchristos       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
527*4b169a6bSchristos         continue;
528*4b169a6bSchristos 
529*4b169a6bSchristos       h = (HANDLE) _get_osfhandle (i);
530*4b169a6bSchristos       if (h != handle_array[nhandles])
531*4b169a6bSchristos         {
532*4b169a6bSchristos           /* Perform handle->descriptor mapping.  */
533*4b169a6bSchristos           SOCKET s = (SOCKET) h;
534*4b169a6bSchristos           WSAEventSelect (s, NULL, 0);
535*4b169a6bSchristos           if (FD_ISSET (s, &handle_rfds))
536*4b169a6bSchristos             FD_SET (i, rfds);
537*4b169a6bSchristos           if (FD_ISSET (s, &handle_wfds))
538*4b169a6bSchristos             FD_SET (i, wfds);
539*4b169a6bSchristos           if (FD_ISSET (s, &handle_xfds))
540*4b169a6bSchristos             FD_SET (i, xfds);
541*4b169a6bSchristos         }
542*4b169a6bSchristos       else
543*4b169a6bSchristos         {
544*4b169a6bSchristos           /* Not a socket.  */
545*4b169a6bSchristos           nhandles++;
546*4b169a6bSchristos           if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
547*4b169a6bSchristos             FD_SET (i, rfds);
548*4b169a6bSchristos           if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
549*4b169a6bSchristos             FD_SET (i, wfds);
550*4b169a6bSchristos           if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
551*4b169a6bSchristos             FD_SET (i, xfds);
552*4b169a6bSchristos         }
553*4b169a6bSchristos     }
554*4b169a6bSchristos 
555*4b169a6bSchristos   return rc;
556*4b169a6bSchristos }
557*4b169a6bSchristos 
558*4b169a6bSchristos #else /* ! Native Windows.  */
559*4b169a6bSchristos 
560*4b169a6bSchristos #include <stddef.h> /* NULL */
561*4b169a6bSchristos #include <errno.h>
562*4b169a6bSchristos #include <unistd.h>
563*4b169a6bSchristos 
564*4b169a6bSchristos #undef select
565*4b169a6bSchristos 
566*4b169a6bSchristos int
rpl_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * xfds,struct timeval * timeout)567*4b169a6bSchristos rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
568*4b169a6bSchristos             struct timeval *timeout)
569*4b169a6bSchristos {
570*4b169a6bSchristos   int i;
571*4b169a6bSchristos 
572*4b169a6bSchristos   /* FreeBSD 8.2 has a bug: it does not always detect invalid fds.  */
573*4b169a6bSchristos   if (nfds < 0 || nfds > FD_SETSIZE)
574*4b169a6bSchristos     {
575*4b169a6bSchristos       errno = EINVAL;
576*4b169a6bSchristos       return -1;
577*4b169a6bSchristos     }
578*4b169a6bSchristos   for (i = 0; i < nfds; i++)
579*4b169a6bSchristos     {
580*4b169a6bSchristos       if (((rfds && FD_ISSET (i, rfds))
581*4b169a6bSchristos            || (wfds && FD_ISSET (i, wfds))
582*4b169a6bSchristos            || (xfds && FD_ISSET (i, xfds)))
583*4b169a6bSchristos           && dup2 (i, i) != i)
584*4b169a6bSchristos         return -1;
585*4b169a6bSchristos     }
586*4b169a6bSchristos 
587*4b169a6bSchristos   /* Interix 3.5 has a bug: it does not support nfds == 0.  */
588*4b169a6bSchristos   if (nfds == 0)
589*4b169a6bSchristos     {
590*4b169a6bSchristos       nfds = 1;
591*4b169a6bSchristos       rfds = NULL;
592*4b169a6bSchristos       wfds = NULL;
593*4b169a6bSchristos       xfds = NULL;
594*4b169a6bSchristos     }
595*4b169a6bSchristos   return select (nfds, rfds, wfds, xfds, timeout);
596*4b169a6bSchristos }
597*4b169a6bSchristos 
598*4b169a6bSchristos #endif
599