Home | History | Annotate | Line # | Download | only in util
      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