/* Distributed Checksum Clearinghouse * * --C-LICENSE-- * $Revision: 1.8 $ */ #include "dcc_clnt.h" #ifdef HAVE_ARPA_NAMESER_H #include #endif #ifdef HAVE_RESOLV_H #include #endif int /* -1=error, 0=timeout, 1=ready */ select_poll(DCC_EMSG *emsg, DCC_POLLFD *pollfds, int nfds, u_char rd, /* 1=read 0=write */ int us) /* <0=forever until signal */ { #ifdef DCC_USE_POLL int delay; int result; int n; for (;;) { if (us < 0) delay = INFTIM; else delay = (us+999)/1000; n = 0; do { if (nfds <= 0) dcc_logbad(EX_SOFTWARE, "no select_poll() FDs"); /* At least some versions of Linux have POLLRDNORM etc. * in asm/poll.h, but with definitions of POLLIN, * POLLPRI, etc. that conflict with their definitions * in sys/poll.h. * Perhaps it is not necessary to check for high or * low priority data, but the poll() documentation on * some systems says that asking about POLLIN does not * say anything about other data */ #define POLL_ERRORS (POLLERR | POLLHUP | POLLNVAL) #ifdef POLLRDNORM if (rd) pollfds[n].events = (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLL_ERRORS); else pollfds[n].events = (POLLOUT | POLLWRNORM | POLLWRBAND | POLLPRI | POLL_ERRORS); #else if (rd) pollfds[n].events = (POLLIN | POLL_ERRORS); else pollfds[n].events = (POLLOUT | POLL_ERRORS); #endif /* POLLRDNORM */ #undef POLL_ERRORS pollfds[n].revents = 0; /* the initial FDs or the last FD can be invalid */ if (pollfds[n].fd != INVALID_SOCKET) { ++n; } else { --nfds; if (n == 0) { ++pollfds; continue; } if (n == nfds) break; dcc_logbad(EX_SOFTWARE, "too few select_poll() FDs"); } } while (n < nfds); result = poll(pollfds, nfds, delay); if (result >= 0) return result; if (DELAY_ERROR()) { if (us < 0) /* stop forever on a signal */ return 0; continue; } dcc_pemsg(EX_OSERR, emsg, "poll(): %s", ERROR_STR()); return -1; } #else /* !DCC_USE_POLL */ struct timeval delay, *delayp; fd_set fds; #ifdef DCC_WIN32 u_int max_fd; #else int max_fd; #endif int result; int i, j; for (;;) { if (us < 0) { delayp = 0; } else { us2tv(&delay, us); delayp = &delay; } FD_ZERO(&fds); max_fd = 0; for (i = 0; i < nfds; ++i) { pollfds[i].revents = 0; if (pollfds[i].fd == INVALID_SOCKET) continue; if (max_fd < pollfds[i].fd) max_fd = pollfds[i].fd; FD_SET(pollfds[i].fd, &fds); } if (rd) result = select(max_fd+1, &fds, 0, 0, delayp); else result = select(max_fd+1, 0, &fds, 0, delayp); if (result == 0) return 0; if (result > 0) { j = result; i = 0; do { if (FD_ISSET(pollfds[i].fd, &fds)) { pollfds[i].revents = 1; --j; } } while (++i, j != 0); return result; } if (DELAY_ERROR()) { if (us < 0) /* stop forever on a signal */ return 0; continue; } dcc_pemsg(EX_OSERR, emsg, "select(): %s", ERROR_STR()); return -1; } #endif /* !DCC_USE_POLL */ }