1/* $NetBSD$ */ 2 3/*++ 4/* NAME 5/* poll_fd 3 6/* SUMMARY 7/* wait until file descriptor becomes readable or writable 8/* SYNOPSIS 9/* #include <iostuff.h> 10/* 11/* int readable(fd) 12/* int fd; 13/* 14/* int writable(fd) 15/* int fd; 16/* 17/* int read_wait(fd, time_limit) 18/* int fd; 19/* int time_limit; 20/* 21/* int write_wait(fd, time_limit) 22/* int fd; 23/* int time_limit; 24/* 25/* int poll_fd(fd, request, time_limit, true_res, false_res) 26/* int fd; 27/* int request; 28/* int time_limit; 29/* int true_res; 30/* int false_res; 31/* DESCRIPTION 32/* The read*() and write*() functions in this module are macros 33/* that provide a convenient interface to poll_fd(). 34/* 35/* readable() asks the kernel if the specified file descriptor 36/* is readable, i.e. a read operation would not block. 37/* 38/* writable() asks the kernel if the specified file descriptor 39/* is writable, i.e. a write operation would not block. 40/* 41/* read_wait() waits until the specified file descriptor becomes 42/* readable, or until the time limit is reached. 43/* 44/* write_wait() waits until the specified file descriptor 45/* becomes writable, or until the time limit is reached. 46/* 47/* poll_fd() waits until the specified file descriptor becomes 48/* readable or writable, or until the time limit is reached. 49/* 50/* Arguments: 51/* .IP fd 52/* File descriptor. With implementations based on select(), a 53/* best effort is made to handle descriptors >=FD_SETSIZE. 54/* .IP request 55/* POLL_FD_READ (wait until readable) or POLL_FD_WRITE (wait 56/* until writable). 57/* .IP time_limit 58/* A positive value specifies a time limit in seconds. A zero 59/* value effects a poll (return immediately). A negative value 60/* means wait until the requested POLL_FD_READ or POLL_FD_WRITE 61/* condition becomes true. 62/* .IP true_res 63/* Result value when the requested POLL_FD_READ or POLL_FD_WRITE 64/* condition is true. 65/* .IP false_res 66/* Result value when the requested POLL_FD_READ or POLL_FD_WRITE 67/* condition is false. 68/* DIAGNOSTICS 69/* Panic: interface violation. All system call errors are fatal 70/* unless specified otherwise. 71/* 72/* readable() and writable() return 1 when the requested 73/* POLL_FD_READ or POLL_FD_WRITE condition is true, zero when 74/* it is false. They never return an error indication. 75/* 76/* read_wait() and write_wait() return zero when the requested 77/* POLL_FD_READ or POLL_FD_WRITE condition is true, -1 (with 78/* errno set to ETIMEDOUT) when it is false. 79/* 80/* poll_fd() returns true_res when the requested POLL_FD_READ 81/* or POLL_FD_WRITE condition is true, false_res when it is 82/* false. When poll_fd() returns a false_res value < 0, it 83/* also sets errno to ETIMEDOUT. 84/* LICENSE 85/* .ad 86/* .fi 87/* The Secure Mailer license must be distributed with this software. 88/* AUTHOR(S) 89/* Wietse Venema 90/* IBM T.J. Watson Research 91/* P.O. Box 704 92/* Yorktown Heights, NY 10598, USA 93/*--*/ 94 95/* System library. */ 96 97#include <sys_defs.h> 98#include <sys/time.h> 99#include <signal.h> 100#include <errno.h> 101#include <unistd.h> 102#include <string.h> 103 104 /* 105 * Use poll() with fall-back to select(). MacOSX needs this for devices. 106 */ 107#if defined(USE_SYSV_POLL_THEN_SELECT) 108#define poll_fd_sysv poll_fd 109#define USE_SYSV_POLL 110#define USE_BSD_SELECT 111int poll_fd_bsd(int, int, int, int, int); 112 113 /* 114 * Use select() only. 115 */ 116#elif defined(USE_BSD_SELECT) 117#define poll_fd_bsd poll_fd 118#undef USE_SYSV_POLL 119 120 /* 121 * Use poll() only. 122 */ 123#elif defined(USE_SYSV_POLL) 124#define poll_fd_sysv poll_fd 125 126 /* 127 * Sanity check. 128 */ 129#else 130#error "specify USE_SYSV_POLL, USE_BSD_SELECT or USE_SYSV_POLL_THEN_SELECT" 131#endif 132 133#ifdef USE_SYSV_POLL 134#include <poll.h> 135#endif 136 137#ifdef USE_SYS_SELECT_H 138#include <sys/select.h> 139#endif 140 141/* Utility library. */ 142 143#include <msg.h> 144#include <iostuff.h> 145 146#ifdef USE_BSD_SELECT 147 148/* poll_fd_bsd - block with time_limit until file descriptor is ready */ 149 150int poll_fd_bsd(int fd, int request, int time_limit, 151 int true_res, int false_res) 152{ 153 fd_set req_fds; 154 fd_set *read_fds; 155 fd_set *write_fds; 156 fd_set except_fds; 157 struct timeval tv; 158 struct timeval *tp; 159 int temp_fd = -1; 160 161 /* 162 * Sanity checks. 163 */ 164 if (FD_SETSIZE <= fd) { 165 if ((temp_fd = dup(fd)) < 0 || temp_fd >= FD_SETSIZE) 166 msg_fatal("descriptor %d does not fit FD_SETSIZE %d", fd, FD_SETSIZE); 167 fd = temp_fd; 168 } 169 170 /* 171 * Use select() so we do not depend on alarm() and on signal() handlers. 172 * Restart select() when interrupted by some signal. Some select() 173 * implementations reduce the time to wait when interrupted, which is 174 * exactly what we want. 175 */ 176 FD_ZERO(&req_fds); 177 FD_SET(fd, &req_fds); 178 except_fds = req_fds; 179 if (request == POLL_FD_READ) { 180 read_fds = &req_fds; 181 write_fds = 0; 182 } else if (request == POLL_FD_WRITE) { 183 read_fds = 0; 184 write_fds = &req_fds; 185 } else { 186 msg_panic("poll_fd: bad request %d", request); 187 } 188 189 if (time_limit >= 0) { 190 tv.tv_usec = 0; 191 tv.tv_sec = time_limit; 192 tp = &tv; 193 } else { 194 tp = 0; 195 } 196 197 for (;;) { 198 switch (select(fd + 1, read_fds, write_fds, &except_fds, tp)) { 199 case -1: 200 if (errno != EINTR) 201 msg_fatal("select: %m"); 202 continue; 203 case 0: 204 if (temp_fd != -1) 205 (void) close(temp_fd); 206 if (false_res < 0) 207 errno = ETIMEDOUT; 208 return (false_res); 209 default: 210 if (temp_fd != -1) 211 (void) close(temp_fd); 212 return (true_res); 213 } 214 } 215} 216 217#endif 218 219#ifdef USE_SYSV_POLL 220 221#ifdef USE_SYSV_POLL_THEN_SELECT 222#define HANDLE_SYSV_POLL_ERROR(fd, req, time_limit, true_res, false_res) \ 223 return (poll_fd_bsd((fd), (req), (time_limit), (true_res), (false_res))) 224#else 225#define HANDLE_SYSV_POLL_ERROR(fd, req, time_limit, true_res, false_res) \ 226 msg_fatal("poll: %m") 227#endif 228 229/* poll_fd_sysv - block with time_limit until file descriptor is ready */ 230 231int poll_fd_sysv(int fd, int request, int time_limit, 232 int true_res, int false_res) 233{ 234 struct pollfd pollfd; 235 236 /* 237 * System-V poll() is optimal for polling a few descriptors. 238 */ 239#define WAIT_FOR_EVENT (-1) 240 241 pollfd.fd = fd; 242 if (request == POLL_FD_READ) { 243 pollfd.events = POLLIN; 244 } else if (request == POLL_FD_WRITE) { 245 pollfd.events = POLLOUT; 246 } else { 247 msg_panic("poll_fd: bad request %d", request); 248 } 249 250 for (;;) { 251 switch (poll(&pollfd, 1, time_limit < 0 ? 252 WAIT_FOR_EVENT : time_limit * 1000)) { 253 case -1: 254 if (errno != EINTR) 255 HANDLE_SYSV_POLL_ERROR(fd, request, time_limit, 256 true_res, false_res); 257 continue; 258 case 0: 259 if (false_res < 0) 260 errno = ETIMEDOUT; 261 return (false_res); 262 default: 263 if (pollfd.revents & POLLNVAL) 264 HANDLE_SYSV_POLL_ERROR(fd, request, time_limit, 265 true_res, false_res); 266 return (true_res); 267 } 268 } 269} 270 271#endif 272