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