1 /* $NetBSD: peekfd.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* peekfd 3 6 /* SUMMARY 7 /* determine amount of data ready to read 8 /* SYNOPSIS 9 /* #include <iostuff.h> 10 /* 11 /* ssize_t peekfd(fd) 12 /* int fd; 13 /* DESCRIPTION 14 /* peekfd() attempts to find out how many bytes are available to 15 /* be read from the named file descriptor. The result value is 16 /* the number of available bytes. 17 /* DIAGNOSTICS 18 /* peekfd() returns -1 in case of trouble. The global \fIerrno\fR 19 /* variable reflects the nature of the problem. 20 /* BUGS 21 /* On some systems, non-blocking read() may fail even after a 22 /* positive return from peekfd(). The smtp-sink program works 23 /* around this by using the readable() function instead. 24 /* LICENSE 25 /* .ad 26 /* .fi 27 /* The Secure Mailer license must be distributed with this software. 28 /* AUTHOR(S) 29 /* Wietse Venema 30 /* IBM T.J. Watson Research 31 /* P.O. Box 704 32 /* Yorktown Heights, NY 10598, USA 33 /* 34 /* Wietse Venema 35 /* Google, Inc. 36 /* 111 8th Avenue 37 /* New York, NY 10011, USA 38 /*--*/ 39 40 /* System library. */ 41 42 #include <sys_defs.h> 43 #include <sys/ioctl.h> 44 #ifdef FIONREAD_IN_SYS_FILIO_H 45 #include <sys/filio.h> 46 #endif 47 #ifdef FIONREAD_IN_TERMIOS_H 48 #include <termios.h> 49 #endif 50 #include <unistd.h> 51 52 #ifndef SHUT_RDWR 53 #define SHUT_RDWR 2 54 #endif 55 56 /* Utility library. */ 57 58 #include "iostuff.h" 59 60 /* peekfd - return amount of data ready to read */ 61 62 ssize_t peekfd(int fd) 63 { 64 65 /* 66 * Anticipate a series of system-dependent code fragments. 67 */ 68 #ifdef FIONREAD 69 int count; 70 71 #ifdef SUNOS5 72 73 /* 74 * With Solaris10, write_wait() hangs in poll() until timeout, when 75 * invoked after peekfd() has received an ECONNRESET error indication. 76 * This happens when a client sends QUIT and closes the connection 77 * immediately. 78 */ 79 if (ioctl(fd, FIONREAD, (char *) &count) < 0) { 80 (void) shutdown(fd, SHUT_RDWR); 81 return (-1); 82 } else { 83 return (count); 84 } 85 #else /* SUNOS5 */ 86 return (ioctl(fd, FIONREAD, (char *) &count) < 0 ? -1 : count); 87 #endif /* SUNOS5 */ 88 #else 89 #error "don't know how to look ahead" 90 #endif 91 } 92