summaryrefslogtreecommitdiffstats
path: root/src/util/peekfd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/peekfd.c')
-rw-r--r--src/util/peekfd.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/util/peekfd.c b/src/util/peekfd.c
new file mode 100644
index 0000000..e9480a2
--- /dev/null
+++ b/src/util/peekfd.c
@@ -0,0 +1,89 @@
+/*++
+/* NAME
+/* peekfd 3
+/* SUMMARY
+/* determine amount of data ready to read
+/* SYNOPSIS
+/* #include <iostuff.h>
+/*
+/* ssize_t peekfd(fd)
+/* int fd;
+/* DESCRIPTION
+/* peekfd() attempts to find out how many bytes are available to
+/* be read from the named file descriptor. The result value is
+/* the number of available bytes.
+/* DIAGNOSTICS
+/* peekfd() returns -1 in case of trouble. The global \fIerrno\fR
+/* variable reflects the nature of the problem.
+/* BUGS
+/* On some systems, non-blocking read() may fail even after a
+/* positive return from peekfd(). The smtp-sink program works
+/* around this by using the readable() function instead.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/ioctl.h>
+#ifdef FIONREAD_IN_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#ifdef FIONREAD_IN_TERMIOS_H
+#include <termios.h>
+#endif
+#include <unistd.h>
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
+/* Utility library. */
+
+#include "iostuff.h"
+
+/* peekfd - return amount of data ready to read */
+
+ssize_t peekfd(int fd)
+{
+
+ /*
+ * Anticipate a series of system-dependent code fragments.
+ */
+#ifdef FIONREAD
+ int count;
+
+#ifdef SUNOS5
+
+ /*
+ * With Solaris10, write_wait() hangs in poll() until timeout, when
+ * invoked after peekfd() has received an ECONNRESET error indication.
+ * This happens when a client sends QUIT and closes the connection
+ * immediately.
+ */
+ if (ioctl(fd, FIONREAD, (char *) &count) < 0) {
+ (void) shutdown(fd, SHUT_RDWR);
+ return (-1);
+ } else {
+ return (count);
+ }
+#else /* SUNOS5 */
+ return (ioctl(fd, FIONREAD, (char *) &count) < 0 ? -1 : count);
+#endif /* SUNOS5 */
+#else
+#error "don't know how to look ahead"
+#endif
+}