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