1 /* $NetBSD: peekfd.c,v 1.4 2025/02/25 19:15:52 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 SUNOS5 45 #include <sys/socket.h> /* shutdown(2) */ 46 #endif 47 #ifdef FIONREAD_IN_SYS_FILIO_H 48 #include <sys/filio.h> 49 #endif 50 #ifdef FIONREAD_IN_TERMIOS_H 51 #include <termios.h> 52 #endif 53 #include <unistd.h> 54 55 #ifndef SHUT_RDWR 56 #define SHUT_RDWR 2 57 #endif 58 59 /* Utility library. */ 60 61 #include "iostuff.h" 62 63 /* peekfd - return amount of data ready to read */ 64 65 ssize_t peekfd(int fd) 66 { 67 68 /* 69 * Anticipate a series of system-dependent code fragments. 70 */ 71 #ifdef FIONREAD 72 int count; 73 74 #ifdef SUNOS5 75 76 /* 77 * With Solaris10, write_wait() hangs in poll() until timeout, when 78 * invoked after peekfd() has received an ECONNRESET error indication. 79 * This happens when a client sends QUIT and closes the connection 80 * immediately. 81 */ 82 if (ioctl(fd, FIONREAD, (char *) &count) < 0) { 83 (void) shutdown(fd, SHUT_RDWR); 84 return (-1); 85 } else { 86 return (count); 87 } 88 #else /* SUNOS5 */ 89 return (ioctl(fd, FIONREAD, (char *) &count) < 0 ? -1 : count); 90 #endif /* SUNOS5 */ 91 #else 92 #error "don't know how to look ahead" 93 #endif 94 } 95