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