1/* $NetBSD$ */ 2 3/*++ 4/* NAME 5/* readable 3 6/* SUMMARY 7/* test if descriptor is readable 8/* SYNOPSIS 9/* #include <iostuff.h> 10/* 11/* int readable(fd) 12/* int fd; 13/* DESCRIPTION 14/* readable() asks the kernel if the specified file descriptor 15/* is readable, i.e. a read operation would not block. 16/* 17/* Arguments: 18/* .IP fd 19/* File descriptor in the range 0..FD_SETSIZE. 20/* DIAGNOSTICS 21/* All system call errors are fatal. 22/* LICENSE 23/* .ad 24/* .fi 25/* The Secure Mailer license must be distributed with this software. 26/* AUTHOR(S) 27/* Wietse Venema 28/* IBM T.J. Watson Research 29/* P.O. Box 704 30/* Yorktown Heights, NY 10598, USA 31/*--*/ 32 33/* System library. */ 34 35#include <sys_defs.h> 36#include <sys/time.h> 37#include <signal.h> 38#include <errno.h> 39#include <unistd.h> 40#include <string.h> 41 42#ifdef USE_SYSV_POLL 43#include <poll.h> 44#endif 45 46#ifdef USE_SYS_SELECT_H 47#include <sys/select.h> 48#endif 49 50/* Utility library. */ 51 52#include <msg.h> 53#include <iostuff.h> 54 55/* readable - see if file descriptor is readable */ 56 57int readable(int fd) 58{ 59#ifndef USE_SYSV_POLL 60 struct timeval tv; 61 fd_set read_fds; 62 fd_set except_fds; 63 64 /* 65 * Sanity checks. 66 */ 67 if (fd >= FD_SETSIZE) 68 msg_fatal("fd %d does not fit in FD_SETSIZE", fd); 69 70 /* 71 * Initialize. 72 */ 73 FD_ZERO(&read_fds); 74 FD_SET(fd, &read_fds); 75 FD_ZERO(&except_fds); 76 FD_SET(fd, &except_fds); 77 tv.tv_sec = 0; 78 tv.tv_usec = 0; 79 80 /* 81 * Loop until we have an authoritative answer. 82 */ 83 for (;;) { 84 switch (select(fd + 1, &read_fds, (fd_set *) 0, &except_fds, &tv)) { 85 case -1: 86 if (errno != EINTR) 87 msg_fatal("select: %m"); 88 continue; 89 default: 90 return (FD_ISSET(fd, &read_fds)); 91 case 0: 92 return (0); 93 } 94 } 95#else 96 97 /* 98 * System-V poll() is optimal for polling a few descriptors. 99 */ 100 struct pollfd pollfd; 101 102#define DONT_WAIT_FOR_EVENT 0 103 104 pollfd.fd = fd; 105 pollfd.events = POLLIN; 106 for (;;) { 107 switch (poll(&pollfd, 1, DONT_WAIT_FOR_EVENT)) { 108 case -1: 109 if (errno != EINTR) 110 msg_fatal("poll: %m"); 111 continue; 112 case 0: 113 return (0); 114 default: 115 if (pollfd.revents & POLLNVAL) 116 msg_fatal("poll: %m"); 117 return (1); 118 } 119 } 120#endif 121} 122