1/* Emulation for poll(2)
   2   Contributed by Paolo Bonzini.
   3   Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.
   5   This file is part of gnulib.
   7   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   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   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/* Tell gcc not to warn about the (nfd < 0) tests, below.  */
  23#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
  24# pragma GCC diagnostic ignored "-Wtype-limits"
  25#endif
  26#include <malloc.h>
  28#include <sys/types.h>
  30#include "poll.h"
  31#include <errno.h>
  32#include <limits.h>
  33#include <assert.h>
  34#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  36# define WIN32_NATIVE
  37# if defined (_MSC_VER)
  38#  define _WIN32_WINNT 0x0502
  39# endif
  40# include <winsock2.h>
  41# include <windows.h>
  42# include <io.h>
  43# include <stdio.h>
  44# include <conio.h>
  45#else
  46# include <sys/time.h>
  47# include <sys/socket.h>
  48# include <sys/select.h>
  49# include <unistd.h>
  50#endif
  51#ifdef HAVE_SYS_IOCTL_H
  53# include <sys/ioctl.h>
  54#endif
  55#ifdef HAVE_SYS_FILIO_H
  56# include <sys/filio.h>
  57#endif
  58#include <time.h>
  60#ifndef INFTIM
  62# define INFTIM (-1)
  63#endif
  64/* BeOS does not have MSG_PEEK.  */
  66#ifndef MSG_PEEK
  67# define MSG_PEEK 0
  68#endif
  69#ifdef WIN32_NATIVE
  71#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
  73static BOOL
  75IsSocketHandle (HANDLE h)
  76{
  77  WSANETWORKEVENTS ev;
  78  if (IsConsoleHandle (h))
  80    return FALSE;
  81  /* Under Wine, it seems that getsockopt returns 0 for pipes too.
  83     WSAEnumNetworkEvents instead distinguishes the two correctly.  */
  84  ev.lNetworkEvents = 0xDEADBEEF;
  85  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
  86  return ev.lNetworkEvents != 0xDEADBEEF;
  87}
  88/* Declare data structures for ntdll functions.  */
  90typedef struct _FILE_PIPE_LOCAL_INFORMATION {
  91  ULONG NamedPipeType;
  92  ULONG NamedPipeConfiguration;
  93  ULONG MaximumInstances;
  94  ULONG CurrentInstances;
  95  ULONG InboundQuota;
  96  ULONG ReadDataAvailable;
  97  ULONG OutboundQuota;
  98  ULONG WriteQuotaAvailable;
  99  ULONG NamedPipeState;
 100  ULONG NamedPipeEnd;
 101} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
 102typedef struct _IO_STATUS_BLOCK
 104{
 105  union {
 106    DWORD Status;
 107    PVOID Pointer;
 108  } u;
 109  ULONG_PTR Information;
 110} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
 111typedef enum _FILE_INFORMATION_CLASS {
 113  FilePipeLocalInformation = 24
 114} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
 115typedef DWORD (WINAPI *PNtQueryInformationFile)
 117         (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
 118# ifndef PIPE_BUF
 120#  define PIPE_BUF      512
 121# endif
 122/* Compute revents values for file handle H.  If some events cannot happen
 124   for the handle, eliminate them from *P_SOUGHT.  */
 125static int
 127win32_compute_revents (HANDLE h, int *p_sought)
 128{
 129  int i, ret, happened;
 130  INPUT_RECORD *irbuffer;
 131  DWORD avail, nbuffer;
 132  BOOL bRet;
 133  IO_STATUS_BLOCK iosb;
 134  FILE_PIPE_LOCAL_INFORMATION fpli;
 135  static PNtQueryInformationFile NtQueryInformationFile;
 136  static BOOL once_only;
 137  switch (GetFileType (h))
 139    {
 140    case FILE_TYPE_PIPE:
 141      if (!once_only)
 142        {
 143          NtQueryInformationFile = (PNtQueryInformationFile)
 144            GetProcAddress (GetModuleHandle ("ntdll.dll"),
 145                            "NtQueryInformationFile");
 146          once_only = TRUE;
 147        }
 148      happened = 0;
 150      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
 151        {
 152          if (avail)
 153            happened |= *p_sought & (POLLIN | POLLRDNORM);
 154        }
 155      else if (GetLastError () == ERROR_BROKEN_PIPE)
 156        happened |= POLLHUP;
 157      else
 159        {
 160          /* It was the write-end of the pipe.  Check if it is writable.
 161             If NtQueryInformationFile fails, optimistically assume the pipe is
 162             writable.  This could happen on Win9x, where NtQueryInformationFile
 163             is not available, or if we inherit a pipe that doesn't permit
 164             FILE_READ_ATTRIBUTES access on the write end (I think this should
 165             not happen since WinXP SP2; WINE seems fine too).  Otherwise,
 166             ensure that enough space is available for atomic writes.  */
 167          memset (&iosb, 0, sizeof (iosb));
 168          memset (&fpli, 0, sizeof (fpli));
 169          if (!NtQueryInformationFile
 171              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
 172                                         FilePipeLocalInformation)
 173              || fpli.WriteQuotaAvailable >= PIPE_BUF
 174              || (fpli.OutboundQuota < PIPE_BUF &&
 175                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
 176            happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
 177        }
 178      return happened;
 179    case FILE_TYPE_CHAR:
 181      ret = WaitForSingleObject (h, 0);
 182      if (!IsConsoleHandle (h))
 183        return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
 184      nbuffer = avail = 0;
 186      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
 187      if (bRet)
 188        {
 189          /* Input buffer.  */
 190          *p_sought &= POLLIN | POLLRDNORM;
 191          if (nbuffer == 0)
 192            return POLLHUP;
 193          if (!*p_sought)
 194            return 0;
 195          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
 197          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
 198          if (!bRet || avail == 0)
 199            return POLLHUP;
 200          for (i = 0; i < avail; i++)
 202            if (irbuffer[i].EventType == KEY_EVENT)
 203              return *p_sought;
 204          return 0;
 205        }
 206      else
 207        {
 208          /* Screen buffer.  */
 209          *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
 210          return *p_sought;
 211        }
 212    default:
 214      ret = WaitForSingleObject (h, 0);
 215      if (ret == WAIT_OBJECT_0)
 216        return *p_sought & ~(POLLPRI | POLLRDBAND);
 217      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
 219    }
 220}
 221/* Convert fd_sets returned by select into revents values.  */
 223static int
 225win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
 226{
 227  int happened = 0;
 228  if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
 230    happened |= (POLLIN | POLLRDNORM) & sought;
 231  else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
 233    {
 234      int r, error;
 235      char data[64];
 237      WSASetLastError (0);
 238      r = recv (h, data, sizeof (data), MSG_PEEK);
 239      error = WSAGetLastError ();
 240      WSASetLastError (0);
 241      if (r > 0 || error == WSAENOTCONN)
 243        happened |= (POLLIN | POLLRDNORM) & sought;
 244      /* Distinguish hung-up sockets from other errors.  */
 246      else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
 247               || error == WSAECONNABORTED || error == WSAENETRESET)
 248        happened |= POLLHUP;
 249      else
 251        happened |= POLLERR;
 252    }
 253  if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
 255    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
 256  if (lNetworkEvents & FD_OOB)
 258    happened |= (POLLPRI | POLLRDBAND) & sought;
 259  return happened;
 261}
 262#else /* !MinGW */
 264/* Convert select(2) returned fd_sets into poll(2) revents values.  */
 266static int
 267compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
 268{
 269  int happened = 0;
 270  if (FD_ISSET (fd, rfds))
 271    {
 272      int r;
 273      int socket_errno;
 274# if defined __MACH__ && defined __APPLE__
 276      /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
 277         for some kinds of descriptors.  Detect if this descriptor is a
 278         connected socket, a server socket, or something else using a
 279         0-byte recv, and use ioctl(2) to detect POLLHUP.  */
 280      r = recv (fd, NULL, 0, MSG_PEEK);
 281      socket_errno = (r < 0) ? errno : 0;
 282      if (r == 0 || socket_errno == ENOTSOCK)
 283        ioctl (fd, FIONREAD, &r);
 284# else
 285      char data[64];
 286      r = recv (fd, data, sizeof (data), MSG_PEEK);
 287      socket_errno = (r < 0) ? errno : 0;
 288# endif
 289      if (r == 0)
 290        happened |= POLLHUP;
 291      /* If the event happened on an unconnected server socket,
 293         that's fine. */
 294      else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
 295        happened |= (POLLIN | POLLRDNORM) & sought;
 296      /* Distinguish hung-up sockets from other errors.  */
 298      else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
 299               || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
 300        happened |= POLLHUP;
 301      else
 303        happened |= POLLERR;
 304    }
 305  if (FD_ISSET (fd, wfds))
 307    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
 308  if (FD_ISSET (fd, efds))
 310    happened |= (POLLPRI | POLLRDBAND) & sought;
 311  return happened;
 313}
 314#endif /* !MinGW */
 315int
 317poll (pfd, nfd, timeout)
 318     struct pollfd *pfd;
 319     nfds_t nfd;
 320     int timeout;
 321{
 322#ifndef WIN32_NATIVE
 323  fd_set rfds, wfds, efds;
 324  struct timeval tv;
 325  struct timeval *ptv;
 326  int maxfd, rc;
 327  nfds_t i;
 328# ifdef _SC_OPEN_MAX
 330  static int sc_open_max = -1;
 331  if (nfd < 0
 333      || (nfd > sc_open_max
 334          && (sc_open_max != -1
 335              || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
 336    {
 337      errno = EINVAL;
 338      return -1;
 339    }
 340# else /* !_SC_OPEN_MAX */
 341#  ifdef OPEN_MAX
 342  if (nfd < 0 || nfd > OPEN_MAX)
 343    {
 344      errno = EINVAL;
 345      return -1;
 346    }
 347#  endif /* OPEN_MAX -- else, no check is needed */
 348# endif /* !_SC_OPEN_MAX */
 349  /* EFAULT is not necessary to implement, but let's do it in the
 351     simplest case. */
 352  if (!pfd)
 353    {
 354      errno = EFAULT;
 355      return -1;
 356    }
 357  /* convert timeout number into a timeval structure */
 359  if (timeout == 0)
 360    {
 361      ptv = &tv;
 362      ptv->tv_sec = 0;
 363      ptv->tv_usec = 0;
 364    }
 365  else if (timeout > 0)
 366    {
 367      ptv = &tv;
 368      ptv->tv_sec = timeout / 1000;
 369      ptv->tv_usec = (timeout % 1000) * 1000;
 370    }
 371  else if (timeout == INFTIM)
 372    /* wait forever */
 373    ptv = NULL;
 374  else
 375    {
 376      errno = EINVAL;
 377      return -1;
 378    }
 379  /* create fd sets and determine max fd */
 381  maxfd = -1;
 382  FD_ZERO (&rfds);
 383  FD_ZERO (&wfds);
 384  FD_ZERO (&efds);
 385  for (i = 0; i < nfd; i++)
 386    {
 387      if (pfd[i].fd < 0)
 388        continue;
 389      if (pfd[i].events & (POLLIN | POLLRDNORM))
 391        FD_SET (pfd[i].fd, &rfds);
 392      /* see select(2): "the only exceptional condition detectable
 394         is out-of-band data received on a socket", hence we push
 395         POLLWRBAND events onto wfds instead of efds. */
 396      if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
 397        FD_SET (pfd[i].fd, &wfds);
 398      if (pfd[i].events & (POLLPRI | POLLRDBAND))
 399        FD_SET (pfd[i].fd, &efds);
 400      if (pfd[i].fd >= maxfd
 401          && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
 402                               | POLLRDNORM | POLLRDBAND
 403                               | POLLWRNORM | POLLWRBAND)))
 404        {
 405          maxfd = pfd[i].fd;
 406          if (maxfd > FD_SETSIZE)
 407            {
 408              errno = EOVERFLOW;
 409              return -1;
 410            }
 411        }
 412    }
 413  /* examine fd sets */
 415  rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
 416  if (rc < 0)
 417    return rc;
 418  /* establish results */
 420  rc = 0;
 421  for (i = 0; i < nfd; i++)
 422    if (pfd[i].fd < 0)
 423      pfd[i].revents = 0;
 424    else
 425      {
 426        int happened = compute_revents (pfd[i].fd, pfd[i].events,
 427                                        &rfds, &wfds, &efds);
 428        if (happened)
 429          {
 430            pfd[i].revents = happened;
 431            rc++;
 432          }
 433      }
 434  return rc;
 436#else
 437  static struct timeval tv0;
 438  static HANDLE hEvent;
 439  WSANETWORKEVENTS ev;
 440  HANDLE h, handle_array[FD_SETSIZE + 2];
 441  DWORD ret, wait_timeout, nhandles;
 442  fd_set rfds, wfds, xfds;
 443  BOOL poll_again;
 444  MSG msg;
 445  int rc = 0;
 446  nfds_t i;
 447  if (nfd < 0 || timeout < -1)
 449    {
 450      errno = EINVAL;
 451      return -1;
 452    }
 453  if (!hEvent)
 455    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
 456  handle_array[0] = hEvent;
 458  nhandles = 1;
 459  FD_ZERO (&rfds);
 460  FD_ZERO (&wfds);
 461  FD_ZERO (&xfds);
 462  /* Classify socket handles and create fd sets. */
 464  for (i = 0; i < nfd; i++)
 465    {
 466      int sought = pfd[i].events;
 467      pfd[i].revents = 0;
 468      if (pfd[i].fd < 0)
 469        continue;
 470      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
 471                      | POLLPRI | POLLRDBAND)))
 472        continue;
 473      h = (HANDLE) _get_osfhandle (pfd[i].fd);
 475      assert (h != NULL);
 476      if (IsSocketHandle (h))
 477        {
 478          int requested = FD_CLOSE;
 479          /* see above; socket handles are mapped onto select.  */
 481          if (sought & (POLLIN | POLLRDNORM))
 482            {
 483              requested |= FD_READ | FD_ACCEPT;
 484              FD_SET ((SOCKET) h, &rfds);
 485            }
 486          if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
 487            {
 488              requested |= FD_WRITE | FD_CONNECT;
 489              FD_SET ((SOCKET) h, &wfds);
 490            }
 491          if (sought & (POLLPRI | POLLRDBAND))
 492            {
 493              requested |= FD_OOB;
 494              FD_SET ((SOCKET) h, &xfds);
 495            }
 496          if (requested)
 498            WSAEventSelect ((SOCKET) h, hEvent, requested);
 499        }
 500      else
 501        {
 502          /* Poll now.  If we get an event, do not poll again.  Also,
 503             screen buffer handles are waitable, and they'll block until
 504             a character is available.  win32_compute_revents eliminates
 505             bits for the "wrong" direction. */
 506          pfd[i].revents = win32_compute_revents (h, &sought);
 507          if (sought)
 508            handle_array[nhandles++] = h;
 509          if (pfd[i].revents)
 510            timeout = 0;
 511        }
 512    }
 513  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
 515    {
 516      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
 517         no need to call select again.  */
 518      poll_again = FALSE;
 519      wait_timeout = 0;
 520    }
 521  else
 522    {
 523      poll_again = TRUE;
 524      if (timeout == INFTIM)
 525        wait_timeout = INFINITE;
 526      else
 527        wait_timeout = timeout;
 528    }
 529  for (;;)
 531    {
 532      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
 533                                       wait_timeout, QS_ALLINPUT);
 534      if (ret == WAIT_OBJECT_0 + nhandles)
 536        {
 537          /* new input of some other kind */
 538          BOOL bRet;
 539          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
 540            {
 541              TranslateMessage (&msg);
 542              DispatchMessage (&msg);
 543            }
 544        }
 545      else
 546        break;
 547    }
 548  if (poll_again)
 550    select (0, &rfds, &wfds, &xfds, &tv0);
 551  /* Place a sentinel at the end of the array.  */
 553  handle_array[nhandles] = NULL;
 554  nhandles = 1;
 555  for (i = 0; i < nfd; i++)
 556    {
 557      int happened;
 558      if (pfd[i].fd < 0)
 560        continue;
 561      if (!(pfd[i].events & (POLLIN | POLLRDNORM |
 562                             POLLOUT | POLLWRNORM | POLLWRBAND)))
 563        continue;
 564      h = (HANDLE) _get_osfhandle (pfd[i].fd);
 566      if (h != handle_array[nhandles])
 567        {
 568          /* It's a socket.  */
 569          WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
 570          WSAEventSelect ((SOCKET) h, 0, 0);
 571          /* If we're lucky, WSAEnumNetworkEvents already provided a way
 573             to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
 574          if (FD_ISSET ((SOCKET) h, &rfds)
 575              && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
 576            ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
 577          if (FD_ISSET ((SOCKET) h, &wfds))
 578            ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
 579          if (FD_ISSET ((SOCKET) h, &xfds))
 580            ev.lNetworkEvents |= FD_OOB;
 581          happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
 583                                                   ev.lNetworkEvents);
 584        }
 585      else
 586        {
 587          /* Not a socket.  */
 588          int sought = pfd[i].events;
 589          happened = win32_compute_revents (h, &sought);
 590          nhandles++;
 591        }
 592       if ((pfd[i].revents |= happened) != 0)
 594        rc++;
 595    }
 596  return rc;
 598#endif
 599}