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 "XSUB.h" 16 17 #include "poll.h" 18 #ifdef I_SYS_TIME 19 # include <sys/time.h> 20 #endif 21 #ifdef I_TIME 22 # include <time.h> 23 #endif 24 #include <sys/types.h> 25 #if defined(HAS_SOCKET) && !defined(VMS) && !defined(ultrix) /* VMS handles sockets via vmsish.h, ULTRIX dies of socket struct redefinitions */ 26 # include <sys/socket.h> 27 #endif 28 #include <sys/stat.h> 29 #include <errno.h> 30 31 #ifdef HAS_SELECT 32 #ifdef I_SYS_SELECT 33 #include <sys/select.h> 34 #endif 35 #endif 36 37 #ifdef EMULATE_POLL_WITH_SELECT 38 39 # define POLL_CAN_READ (POLLIN | POLLRDNORM ) 40 # define POLL_CAN_WRITE (POLLOUT | POLLWRNORM | POLLWRBAND ) 41 # define POLL_HAS_EXCP (POLLRDBAND | POLLPRI ) 42 43 # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP) 44 45 int 46 poll(struct pollfd *fds, unsigned long nfds, int timeout) 47 { 48 int i,err; 49 fd_set rfd,wfd,efd,ifd; 50 struct timeval timebuf; 51 struct timeval *tbuf = (struct timeval *)0; 52 int n = 0; 53 int count; 54 55 FD_ZERO(&ifd); 56 57 #ifdef HAS_FSTAT 58 again: 59 #endif 60 61 FD_ZERO(&rfd); 62 FD_ZERO(&wfd); 63 FD_ZERO(&efd); 64 65 for(i = 0 ; i < (int)nfds ; i++) { 66 int events = fds[i].events; 67 int fd = fds[i].fd; 68 69 fds[i].revents = 0; 70 71 if(fd < 0 || FD_ISSET(fd, &ifd)) 72 continue; 73 74 if(fd > n) 75 n = fd; 76 77 if(events & POLL_CAN_READ) 78 FD_SET(fd, &rfd); 79 80 if(events & POLL_CAN_WRITE) 81 FD_SET(fd, &wfd); 82 83 if(events & POLL_HAS_EXCP) 84 FD_SET(fd, &efd); 85 } 86 87 if(timeout >= 0) { 88 timebuf.tv_sec = timeout / 1000; 89 timebuf.tv_usec = (timeout % 1000) * 1000; 90 tbuf = &timebuf; 91 } 92 93 err = select(n+1,&rfd,&wfd,&efd,tbuf); 94 95 if(err < 0) { 96 #ifdef HAS_FSTAT 97 if(errno == EBADF) { 98 for(i = 0 ; i < nfds ; i++) { 99 struct stat buf; 100 if((fstat(fds[i].fd,&buf) < 0) && (errno == EBADF)) { 101 FD_SET(fds[i].fd, &ifd); 102 goto again; 103 } 104 } 105 } 106 #endif /* HAS_FSTAT */ 107 return err; 108 } 109 110 count = 0; 111 112 for(i = 0 ; i < (int)nfds ; i++) { 113 int revents = (fds[i].events & POLL_EVENTS_MASK); 114 int fd = fds[i].fd; 115 116 if(fd < 0) 117 continue; 118 119 if(FD_ISSET(fd, &ifd)) 120 revents = POLLNVAL; 121 else { 122 if(!FD_ISSET(fd, &rfd)) 123 revents &= ~POLL_CAN_READ; 124 125 if(!FD_ISSET(fd, &wfd)) 126 revents &= ~POLL_CAN_WRITE; 127 128 if(!FD_ISSET(fd, &efd)) 129 revents &= ~POLL_HAS_EXCP; 130 } 131 132 if((fds[i].revents = revents) != 0) 133 count++; 134 } 135 136 return count; 137 } 138 139 #endif /* EMULATE_POLL_WITH_SELECT */ 140 141 /* gcc for SunOS 4 produces code from an empty (code/symbolwise) 142 * source code file that makes the SunOS 4.x /usr/bin/ld fail with 143 * ld: poll.o: premature EOF 144 * To avoid this, have at least something in here. */ 145 #if defined(__sun) && !defined(__SVR4) && defined(__GNUC__) 146 static int dummy; 147 #endif 148 149