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#include <time.h> 22#include <sys/types.h> 23#if defined(HAS_SOCKET) && !defined(VMS) && !defined(ultrix) /* VMS handles sockets via vmsish.h, ULTRIX dies of socket struct redefinitions */ 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 43int 44poll(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#ifdef HAS_FSTAT 56again: 57#endif 58 59 FD_ZERO(&rfd); 60 FD_ZERO(&wfd); 61 FD_ZERO(&efd); 62 63 for(i = 0 ; i < (int)nfds ; i++) { 64 int events = fds[i].events; 65 int fd = fds[i].fd; 66 67 fds[i].revents = 0; 68 69 if(fd < 0 || FD_ISSET(fd, &ifd)) 70 continue; 71 72 if(fd > n) 73 n = fd; 74 75 if(events & POLL_CAN_READ) 76 FD_SET(fd, &rfd); 77 78 if(events & POLL_CAN_WRITE) 79 FD_SET(fd, &wfd); 80 81 if(events & POLL_HAS_EXCP) 82 FD_SET(fd, &efd); 83 } 84 85 if(timeout >= 0) { 86 timebuf.tv_sec = timeout / 1000; 87 timebuf.tv_usec = (timeout % 1000) * 1000; 88 tbuf = &timebuf; 89 } 90 91 err = select(n+1,&rfd,&wfd,&efd,tbuf); 92 93 if(err < 0) { 94#ifdef HAS_FSTAT 95 if(errno == EBADF) { 96 for(i = 0 ; i < nfds ; i++) { 97 struct stat buf; 98 if((fstat(fds[i].fd,&buf) < 0) && (errno == EBADF)) { 99 FD_SET(fds[i].fd, &ifd); 100 goto again; 101 } 102 } 103 } 104#endif /* HAS_FSTAT */ 105 return err; 106 } 107 108 count = 0; 109 110 for(i = 0 ; i < (int)nfds ; i++) { 111 int revents = (fds[i].events & POLL_EVENTS_MASK); 112 int fd = fds[i].fd; 113 114 if(fd < 0) 115 continue; 116 117 if(FD_ISSET(fd, &ifd)) 118 revents = POLLNVAL; 119 else { 120 if(!FD_ISSET(fd, &rfd)) 121 revents &= ~POLL_CAN_READ; 122 123 if(!FD_ISSET(fd, &wfd)) 124 revents &= ~POLL_CAN_WRITE; 125 126 if(!FD_ISSET(fd, &efd)) 127 revents &= ~POLL_HAS_EXCP; 128 } 129 130 if((fds[i].revents = revents) != 0) 131 count++; 132 } 133 134 return count; 135} 136 137#endif /* EMULATE_POLL_WITH_SELECT */ 138 139/* gcc for SunOS 4 produces code from an empty (code/symbolwise) 140 * source code file that makes the SunOS 4.x /usr/bin/ld fail with 141 * ld: poll.o: premature EOF 142 * To avoid this, have at least something in here. */ 143#if defined(__sun) && !defined(__SVR4) && defined(__GNUC__) 144static int dummy; 145#endif 146 147