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