1 /* 2 * poll.c 3 * - wrappers for poll(2) 4 */ 5 /* 6 * This file is 7 * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk> 8 * 9 * It is part of adns, which is 10 * Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk> 11 * Copyright (C) 1999-2000 Tony Finch <dot@dotat.at> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2, or (at your option) 16 * any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software Foundation, 25 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 26 */ 27 28 #include <limits.h> 29 #include <string.h> 30 31 #include "internal.h" 32 33 #ifdef HAVE_POLL 34 35 int adns_beforepoll(adns_state ads, struct pollfd *fds, int *nfds_io, int *timeout_io, 36 const struct timeval *now) { 37 struct timeval tv_nowbuf, tv_tobuf, *tv_to; 38 int space, found, timeout_ms, r; 39 struct pollfd fds_tmp[MAX_POLLFDS]; 40 41 adns__consistency(ads,0,cc_entex); 42 43 if (timeout_io) { 44 adns__must_gettimeofday(ads,&now,&tv_nowbuf); 45 if (!now) { *nfds_io= 0; r= 0; goto xit; } 46 47 timeout_ms= *timeout_io; 48 if (timeout_ms == -1) { 49 tv_to= 0; 50 } else { 51 tv_tobuf.tv_sec= timeout_ms / 1000; 52 tv_tobuf.tv_usec= (timeout_ms % 1000)*1000; 53 tv_to= &tv_tobuf; 54 } 55 56 adns__timeouts(ads, 0, &tv_to,&tv_tobuf, *now); 57 58 if (tv_to) { 59 assert(tv_to == &tv_tobuf); 60 timeout_ms= (tv_tobuf.tv_usec+999)/1000; 61 assert(tv_tobuf.tv_sec < (INT_MAX-timeout_ms)/1000); 62 timeout_ms += tv_tobuf.tv_sec*1000; 63 } else { 64 timeout_ms= -1; 65 } 66 *timeout_io= timeout_ms; 67 } 68 69 space= *nfds_io; 70 if (space >= MAX_POLLFDS) { 71 found= adns__pollfds(ads,fds); 72 *nfds_io= found; 73 } else { 74 found= adns__pollfds(ads,fds_tmp); 75 *nfds_io= found; 76 if (space < found) { r= ERANGE; goto xit; } 77 memcpy(fds,fds_tmp,sizeof(struct pollfd)*found); 78 } 79 r= 0; 80 xit: 81 adns__consistency(ads,0,cc_entex); 82 return r; 83 } 84 85 void adns_afterpoll(adns_state ads, const struct pollfd *fds, int nfds, 86 const struct timeval *now) { 87 struct timeval tv_buf; 88 89 adns__consistency(ads,0,cc_entex); 90 adns__must_gettimeofday(ads,&now,&tv_buf); 91 if (now) { 92 adns__timeouts(ads, 1, 0,0, *now); 93 adns__fdevents(ads, fds,nfds, 0,0,0,0, *now,0); 94 } 95 adns__consistency(ads,0,cc_entex); 96 } 97 98 int adns_wait_poll(adns_state ads, 99 adns_query *query_io, 100 adns_answer **answer_r, 101 void **context_r) { 102 int r, nfds, to; 103 struct pollfd fds[MAX_POLLFDS]; 104 105 adns__consistency(ads,0,cc_entex); 106 107 for (;;) { 108 r= adns__internal_check(ads,query_io,answer_r,context_r); 109 if (r != EAGAIN) goto xit; 110 nfds= MAX_POLLFDS; to= -1; 111 adns_beforepoll(ads,fds,&nfds,&to,0); 112 r= poll(fds,nfds,to); 113 if (r == -1) { 114 if (errno == EINTR) { 115 if (ads->iflags & adns_if_eintr) { r= EINTR; goto xit; } 116 } else { 117 adns__diag(ads,-1,0,"poll failed in wait: %s",strerror(errno)); 118 adns_globalsystemfailure(ads); 119 } 120 } else { 121 assert(r >= 0); 122 adns_afterpoll(ads,fds,nfds,0); 123 } 124 } 125 126 xit: 127 adns__consistency(ads,0,cc_entex); 128 return r; 129 } 130 131 #endif 132