00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include <alloca.h>
00024
00025 #include <sys/types.h>
00026 #include "poll.h"
00027 #include <errno.h>
00028 #include <limits.h>
00029 #include <assert.h>
00030
00031 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
00032 #define WIN32_NATIVE
00033 #include <winsock2.h>
00034 #include <windows.h>
00035 #include <io.h>
00036 #include <stdio.h>
00037 #include <conio.h>
00038 #else
00039 #include <sys/time.h>
00040 #include <sys/socket.h>
00041 #include <sys/select.h>
00042 #include <unistd.h>
00043 #endif
00044
00045 #ifdef HAVE_SYS_IOCTL_H
00046 #include <sys/ioctl.h>
00047 #endif
00048 #ifdef HAVE_SYS_FILIO_H
00049 #include <sys/filio.h>
00050 #endif
00051
00052 #include <time.h>
00053
00054 #ifndef INFTIM
00055 #define INFTIM (-1)
00056 #endif
00057
00058
00059 #ifndef MSG_PEEK
00060 #define MSG_PEEK 0
00061 #endif
00062
00063 #ifdef WIN32_NATIVE
00064
00065
00066 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
00067 ULONG NamedPipeType;
00068 ULONG NamedPipeConfiguration;
00069 ULONG MaximumInstances;
00070 ULONG CurrentInstances;
00071 ULONG InboundQuota;
00072 ULONG ReadDataAvailable;
00073 ULONG OutboundQuota;
00074 ULONG WriteQuotaAvailable;
00075 ULONG NamedPipeState;
00076 ULONG NamedPipeEnd;
00077 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
00078
00079 typedef struct _IO_STATUS_BLOCK
00080 {
00081 union {
00082 DWORD Status;
00083 PVOID Pointer;
00084 } u;
00085 ULONG_PTR Information;
00086 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
00087
00088 typedef enum _FILE_INFORMATION_CLASS {
00089 FilePipeLocalInformation = 24
00090 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
00091
00092 typedef DWORD (WINAPI *PNtQueryInformationFile)
00093 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
00094
00095 #ifndef PIPE_BUF
00096 #define PIPE_BUF 512
00097 #endif
00098
00099
00100
00101 static int
00102 win32_compute_revents (HANDLE h, int sought)
00103 {
00104 int i, ret, happened;
00105 INPUT_RECORD *irbuffer;
00106 DWORD avail, nbuffer;
00107 BOOL bRet;
00108 IO_STATUS_BLOCK iosb;
00109 FILE_PIPE_LOCAL_INFORMATION fpli;
00110 static PNtQueryInformationFile NtQueryInformationFile;
00111 static BOOL once_only;
00112
00113 switch (GetFileType (h))
00114 {
00115 case FILE_TYPE_PIPE:
00116 if (!once_only)
00117 {
00118 NtQueryInformationFile = (PNtQueryInformationFile)
00119 GetProcAddress (GetModuleHandle ("ntdll.dll"),
00120 "NtQueryInformationFile");
00121 once_only = TRUE;
00122 }
00123
00124 happened = 0;
00125 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
00126 {
00127 if (avail)
00128 happened |= sought & (POLLIN | POLLRDNORM);
00129 }
00130
00131 else
00132 {
00133
00134
00135
00136
00137
00138
00139
00140 memset (&iosb, 0, sizeof (iosb));
00141 memset (&fpli, 0, sizeof (fpli));
00142
00143 if (!NtQueryInformationFile
00144 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
00145 FilePipeLocalInformation)
00146 || fpli.WriteQuotaAvailable >= PIPE_BUF
00147 || (fpli.OutboundQuota < PIPE_BUF &&
00148 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
00149 happened |= sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
00150 }
00151 return happened;
00152
00153 case FILE_TYPE_CHAR:
00154 ret = WaitForSingleObject (h, 0);
00155 if (ret == WAIT_OBJECT_0)
00156 {
00157 nbuffer = avail = 0;
00158 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
00159 if (!bRet || nbuffer == 0)
00160 return POLLHUP;
00161
00162 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
00163 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
00164 if (!bRet || avail == 0)
00165 return POLLHUP;
00166
00167 for (i = 0; i < avail; i++)
00168 if (irbuffer[i].EventType == KEY_EVENT)
00169 return sought & ~(POLLPRI | POLLRDBAND);
00170 }
00171 break;
00172
00173 default:
00174 ret = WaitForSingleObject (h, 0);
00175 if (ret == WAIT_OBJECT_0)
00176 return sought & ~(POLLPRI | POLLRDBAND);
00177
00178 break;
00179 }
00180
00181 return sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
00182 }
00183
00184
00185
00186 static int
00187 win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
00188 {
00189 int happened = 0;
00190
00191 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
00192 happened |= (POLLIN | POLLRDNORM) & sought;
00193
00194 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
00195 {
00196 int r, error;
00197
00198 char data[64];
00199 WSASetLastError (0);
00200 r = recv (h, data, sizeof (data), MSG_PEEK);
00201 error = WSAGetLastError ();
00202 WSASetLastError (0);
00203
00204 if (r > 0 || error == WSAENOTCONN)
00205 happened |= (POLLIN | POLLRDNORM) & sought;
00206
00207
00208 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
00209 || error == WSAECONNABORTED || error == WSAENETRESET)
00210 happened |= POLLHUP;
00211
00212 else
00213 happened |= POLLERR;
00214 }
00215
00216 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
00217 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
00218
00219 if (lNetworkEvents & FD_OOB)
00220 happened |= (POLLPRI | POLLRDBAND) & sought;
00221
00222 return happened;
00223 }
00224
00225 #else
00226
00227
00228 static int
00229 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
00230 {
00231 int happened = 0;
00232 if (FD_ISSET (fd, rfds))
00233 {
00234 int r;
00235 int socket_errno;
00236
00237 #if defined __MACH__ && defined __APPLE__
00238
00239
00240
00241
00242 r = recv (fd, NULL, 0, MSG_PEEK);
00243 socket_errno = (r < 0) ? errno : 0;
00244 if (r == 0 || socket_errno == ENOTSOCK)
00245 ioctl (fd, FIONREAD, &r);
00246 #else
00247 char data[64];
00248 r = recv (fd, data, sizeof (data), MSG_PEEK);
00249 socket_errno = (r < 0) ? errno : 0;
00250 #endif
00251 if (r == 0)
00252 happened |= POLLHUP;
00253
00254
00255
00256 else if (r > 0 || ( socket_errno == ENOTCONN))
00257 happened |= (POLLIN | POLLRDNORM) & sought;
00258
00259
00260 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
00261 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
00262 happened |= POLLHUP;
00263
00264 else
00265 happened |= POLLERR;
00266 }
00267
00268 if (FD_ISSET (fd, wfds))
00269 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
00270
00271 if (FD_ISSET (fd, efds))
00272 happened |= (POLLPRI | POLLRDBAND) & sought;
00273
00274 return happened;
00275 }
00276 #endif
00277
00278 int
00279 poll (pfd, nfd, timeout)
00280 struct pollfd *pfd;
00281 nfds_t nfd;
00282 int timeout;
00283 {
00284 #ifndef WIN32_NATIVE
00285 fd_set rfds, wfds, efds;
00286 struct timeval tv;
00287 struct timeval *ptv;
00288 int maxfd, rc;
00289 nfds_t i;
00290
00291 #ifdef _SC_OPEN_MAX
00292 static int sc_open_max = -1;
00293
00294 if (nfd < 0
00295 || (nfd > sc_open_max
00296 && (sc_open_max != -1
00297 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
00298 {
00299 errno = EINVAL;
00300 return -1;
00301 }
00302 #else
00303 #ifdef OPEN_MAX
00304 if (nfd < 0 || nfd > OPEN_MAX)
00305 {
00306 errno = EINVAL;
00307 return -1;
00308 }
00309 #endif
00310 #endif
00311
00312
00313
00314 if (!pfd)
00315 {
00316 errno = EFAULT;
00317 return -1;
00318 }
00319
00320
00321 if (timeout == 0)
00322 {
00323 ptv = &tv;
00324 ptv->tv_sec = 0;
00325 ptv->tv_usec = 0;
00326 }
00327 else if (timeout > 0)
00328 {
00329 ptv = &tv;
00330 ptv->tv_sec = timeout / 1000;
00331 ptv->tv_usec = (timeout % 1000) * 1000;
00332 }
00333 else if (timeout == INFTIM)
00334
00335 ptv = NULL;
00336 else
00337 {
00338 errno = EINVAL;
00339 return -1;
00340 }
00341
00342
00343 maxfd = -1;
00344 FD_ZERO (&rfds);
00345 FD_ZERO (&wfds);
00346 FD_ZERO (&efds);
00347 for (i = 0; i < nfd; i++)
00348 {
00349 if (pfd[i].fd < 0)
00350 continue;
00351
00352 if (pfd[i].events & (POLLIN | POLLRDNORM))
00353 FD_SET (pfd[i].fd, &rfds);
00354
00355
00356
00357
00358 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
00359 FD_SET (pfd[i].fd, &wfds);
00360 if (pfd[i].events & (POLLPRI | POLLRDBAND))
00361 FD_SET (pfd[i].fd, &efds);
00362 if (pfd[i].fd >= maxfd
00363 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
00364 | POLLRDNORM | POLLRDBAND
00365 | POLLWRNORM | POLLWRBAND)))
00366 {
00367 maxfd = pfd[i].fd;
00368 if (maxfd > FD_SETSIZE)
00369 {
00370 errno = EOVERFLOW;
00371 return -1;
00372 }
00373 }
00374 }
00375
00376
00377 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
00378 if (rc < 0)
00379 return rc;
00380
00381
00382 rc = 0;
00383 for (i = 0; i < nfd; i++)
00384 if (pfd[i].fd < 0)
00385 pfd[i].revents = 0;
00386 else
00387 {
00388 int happened = compute_revents (pfd[i].fd, pfd[i].events,
00389 &rfds, &wfds, &efds);
00390 if (happened)
00391 {
00392 pfd[i].revents = happened;
00393 rc++;
00394 }
00395 }
00396
00397 return rc;
00398 #else
00399 static struct timeval tv0;
00400 static HANDLE hEvent;
00401 WSANETWORKEVENTS ev;
00402 HANDLE h, handle_array[FD_SETSIZE + 2];
00403 DWORD ret, wait_timeout, nhandles;
00404 fd_set rfds, wfds, xfds;
00405 BOOL poll_again;
00406 MSG msg;
00407 char sockbuf[256];
00408 int rc;
00409 nfds_t i;
00410
00411 if (nfd < 0 || timeout < -1)
00412 {
00413 errno = EINVAL;
00414 return -1;
00415 }
00416
00417 if (!hEvent)
00418 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
00419
00420 handle_array[0] = hEvent;
00421 nhandles = 1;
00422 FD_ZERO (&rfds);
00423 FD_ZERO (&wfds);
00424 FD_ZERO (&xfds);
00425
00426
00427 for (i = 0; i < nfd; i++)
00428 {
00429 size_t optlen = sizeof(sockbuf);
00430 pfd[i].revents = 0;
00431 if (pfd[i].fd < 0)
00432 continue;
00433 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
00434 POLLOUT | POLLWRNORM | POLLWRBAND)))
00435 continue;
00436
00437 h = (HANDLE) _get_osfhandle (pfd[i].fd);
00438 assert (h != NULL);
00439
00440
00441
00442 ev.lNetworkEvents = 0xDEADBEEF;
00443 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
00444 if (ev.lNetworkEvents != 0xDEADBEEF)
00445 {
00446 int requested = FD_CLOSE;
00447
00448
00449 if (pfd[i].events & (POLLIN | POLLRDNORM))
00450 {
00451 requested |= FD_READ | FD_ACCEPT;
00452 FD_SET ((SOCKET) h, &rfds);
00453 }
00454 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
00455 {
00456 requested |= FD_WRITE | FD_CONNECT;
00457 FD_SET ((SOCKET) h, &wfds);
00458 }
00459 if (pfd[i].events & (POLLPRI | POLLRDBAND))
00460 {
00461 requested |= FD_OOB;
00462 FD_SET ((SOCKET) h, &xfds);
00463 }
00464
00465 if (requested)
00466 WSAEventSelect ((SOCKET) h, hEvent, requested);
00467 }
00468 else
00469 {
00470 handle_array[nhandles++] = h;
00471
00472
00473 pfd[i].revents = win32_compute_revents (h, pfd[i].events);
00474 if (pfd[i].revents)
00475 wait_timeout = 0;
00476 }
00477 }
00478
00479 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
00480 {
00481
00482
00483 poll_again = FALSE;
00484 wait_timeout = 0;
00485 }
00486 else
00487 {
00488 poll_again = TRUE;
00489 if (timeout == INFTIM)
00490 wait_timeout = INFINITE;
00491 else
00492 wait_timeout = timeout;
00493 }
00494
00495 for (;;)
00496 {
00497 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
00498 wait_timeout, QS_ALLINPUT);
00499
00500 if (ret == WAIT_OBJECT_0 + nhandles)
00501 {
00502
00503 BOOL bRet;
00504 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
00505 {
00506 TranslateMessage (&msg);
00507 DispatchMessage (&msg);
00508 }
00509 }
00510 else
00511 break;
00512 }
00513
00514 if (poll_again)
00515 select (0, &rfds, &wfds, &xfds, &tv0);
00516
00517
00518 handle_array[nhandles] = NULL;
00519 nhandles = 1;
00520 for (i = 0; i < nfd; i++)
00521 {
00522 int happened;
00523
00524 if (pfd[i].fd < 0)
00525 continue;
00526 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
00527 POLLOUT | POLLWRNORM | POLLWRBAND)))
00528 continue;
00529
00530 h = (HANDLE) _get_osfhandle (pfd[i].fd);
00531 if (h != handle_array[nhandles])
00532 {
00533
00534 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
00535 WSAEventSelect ((SOCKET) h, 0, 0);
00536
00537
00538
00539 if (FD_ISSET ((SOCKET) h, &rfds)
00540 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
00541 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
00542 if (FD_ISSET ((SOCKET) h, &wfds))
00543 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
00544 if (FD_ISSET ((SOCKET) h, &xfds))
00545 ev.lNetworkEvents |= FD_OOB;
00546
00547 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
00548 ev.lNetworkEvents);
00549 }
00550 else
00551 {
00552
00553 nhandles++;
00554 happened = win32_compute_revents (h, pfd[i].events);
00555 }
00556
00557 if ((pfd[i].revents |= happened) != 0)
00558 rc++;
00559 }
00560
00561 return rc;
00562 #endif
00563 }