xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/peekfd.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: peekfd.c,v 1.2 2017/02/14 01:16:49 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 
35 /* System library. */
36 
37 #include <sys_defs.h>
38 #include <sys/ioctl.h>
39 #ifdef FIONREAD_IN_SYS_FILIO_H
40 #include <sys/filio.h>
41 #endif
42 #ifdef FIONREAD_IN_TERMIOS_H
43 #include <termios.h>
44 #endif
45 #include <unistd.h>
46 
47 #ifndef SHUT_RDWR
48 #define SHUT_RDWR  2
49 #endif
50 
51 /* Utility library. */
52 
53 #include "iostuff.h"
54 
55 /* peekfd - return amount of data ready to read */
56 
57 ssize_t peekfd(int fd)
58 {
59 
60     /*
61      * Anticipate a series of system-dependent code fragments.
62      */
63 #ifdef FIONREAD
64     int     count;
65 
66 #ifdef SUNOS5
67 
68     /*
69      * With Solaris10, write_wait() hangs in poll() until timeout, when
70      * invoked after peekfd() has received an ECONNRESET error indication.
71      * This happens when a client sends QUIT and closes the connection
72      * immediately.
73      */
74     if (ioctl(fd, FIONREAD, (char *) &count) < 0) {
75 	(void) shutdown(fd, SHUT_RDWR);
76 	return (-1);
77     } else {
78 	return (count);
79     }
80 #else						/* SUNOS5 */
81     return (ioctl(fd, FIONREAD, (char *) &count) < 0 ? -1 : count);
82 #endif						/* SUNOS5 */
83 #else
84 #error "don't know how to look ahead"
85 #endif
86 }
87