xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/peekfd.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
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 
peekfd(int fd)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