home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / perl560.zip / ext / IO / poll.c < prev    next >
C/C++ Source or Header  |  2000-03-14  |  3KB  |  136 lines

  1. /*
  2.  * poll.c
  3.  *
  4.  * Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the same terms as Perl itself.
  7.  *
  8.  * For systems that do not have the poll() system call (for example Linux
  9.  * kernels < v2.1.23) try to emulate it as closely as possible using select()
  10.  *
  11.  */
  12.  
  13. #include "EXTERN.h"
  14. #include "perl.h"
  15. #include "poll.h"
  16. #ifdef I_SYS_TIME
  17. # include <sys/time.h>
  18. #endif
  19. #ifdef I_TIME
  20. # include <time.h>
  21. #endif
  22. #include <sys/types.h>
  23. #if defined(HAS_SOCKET) && !defined(VMS) /* VMS handles sockets via vmsish.h */
  24. #  include <sys/socket.h>
  25. #endif
  26. #include <sys/stat.h>
  27. #include <errno.h>
  28.  
  29. #ifdef HAS_SELECT
  30. #ifdef I_SYS_SELECT
  31. #include <sys/select.h>
  32. #endif
  33. #endif
  34.  
  35. #ifdef EMULATE_POLL_WITH_SELECT
  36.  
  37. # define POLL_CAN_READ    (POLLIN | POLLRDNORM )
  38. # define POLL_CAN_WRITE    (POLLOUT | POLLWRNORM | POLLWRBAND )
  39. # define POLL_HAS_EXCP    (POLLRDBAND | POLLPRI )
  40.  
  41. # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP)
  42.  
  43. int
  44. poll(struct pollfd *fds, unsigned long nfds, int timeout)
  45. {
  46.     int i,err;
  47.     fd_set rfd,wfd,efd,ifd;
  48.     struct timeval timebuf;
  49.     struct timeval *tbuf = (struct timeval *)0;
  50.     int n = 0;
  51.     int count;
  52.  
  53.     FD_ZERO(&ifd);
  54.  
  55. again:
  56.  
  57.     FD_ZERO(&rfd);
  58.     FD_ZERO(&wfd);
  59.     FD_ZERO(&efd);
  60.  
  61.     for(i = 0 ; i < nfds ; i++) {
  62.     int events = fds[i].events;
  63.     int fd = fds[i].fd;
  64.  
  65.     fds[i].revents = 0;
  66.  
  67.     if(fd < 0 || FD_ISSET(fd, &ifd))
  68.         continue;
  69.  
  70.     if(fd > n)
  71.         n = fd;
  72.  
  73.     if(events & POLL_CAN_READ)
  74.         FD_SET(fd, &rfd);
  75.  
  76.     if(events & POLL_CAN_WRITE)
  77.         FD_SET(fd, &wfd);
  78.  
  79.     if(events & POLL_HAS_EXCP)
  80.         FD_SET(fd, &efd);
  81.     }
  82.  
  83.     if(timeout >= 0) {
  84.     timebuf.tv_sec = timeout / 1000;
  85.     timebuf.tv_usec = (timeout % 1000) * 1000;
  86.     tbuf = &timebuf;
  87.     }
  88.  
  89.     err = select(n+1,&rfd,&wfd,&efd,tbuf);
  90.  
  91.     if(err < 0) {
  92. #ifdef HAS_FSTAT
  93.     if(errno == EBADF) {
  94.         for(i = 0 ; i < nfds ; i++) {
  95.         struct stat buf;
  96.         if((fstat(fds[i].fd,&buf) < 0) && (errno == EBADF)) {
  97.             FD_SET(fds[i].fd, &ifd);
  98.             goto again;
  99.         }
  100.         }
  101.     }
  102. #endif /* HAS_FSTAT */
  103.     return err;
  104.     }
  105.  
  106.     count = 0;
  107.  
  108.     for(i = 0 ; i < nfds ; i++) {
  109.     int revents = (fds[i].events & POLL_EVENTS_MASK);
  110.     int fd = fds[i].fd;
  111.  
  112.     if(fd < 0)
  113.         continue;
  114.  
  115.     if(FD_ISSET(fd, &ifd))
  116.         revents = POLLNVAL;
  117.     else {
  118.         if(!FD_ISSET(fd, &rfd))
  119.             revents &= ~POLL_CAN_READ;
  120.  
  121.         if(!FD_ISSET(fd, &wfd))
  122.             revents &= ~POLL_CAN_WRITE;
  123.  
  124.         if(!FD_ISSET(fd, &efd))
  125.             revents &= ~POLL_HAS_EXCP;
  126.     }
  127.  
  128.     if((fds[i].revents = revents) != 0)
  129.         count++;
  130.     }
  131.  
  132.     return count; 
  133. }
  134.  
  135. #endif /* EMULATE_POLL_WITH_SELECT */
  136.