From bc5dc7af74e6fa1c70aa4bbb1e482fd0c3663af3 Mon Sep 17 00:00:00 2001
From: Mats Erik Andersson <gnu@gisladisker.se>
Date: Sat, 15 Aug 2015 20:56:26 +0200
Subject: [PATCH 11/60] telnetd: Premature connection closure.

A change, part of 0b7e8687, but secondary to its
intention, turned out to cause service rejects during
conditions akin to connection flooding.  Revert this
particular part to gain established, good behaviour
on GNU/Linux.
Reported in `bug-inetutils/2015-07/msg00006.html'.
---
 ChangeLog         | 18 ++++++++++++++++++
 telnetd/telnetd.c |  8 +++++++-
 telnetd/utility.c |  8 ++++++++
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index 73b281b9..03bb8a78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2015-08-15  Mats Erik Andersson  <gnu@gisladisker.se>
+
+	telnetd: Premature connection closure.
+	When many connections are attempted in quick succession,
+	a substantial number of them are cancelled.  This does not
+	appear for manual use cases, but for contrived automated
+	set-ups.  The cause seems to be a change in the evaluation
+	of pty_read(), which was done to coincide with the condition
+	in use by the original BSD implementation.  Issue reported and
+	suggested by Chris Severance in
+	http://lists.gnu.org/archive/html/bug-inetutils/2015-07/msg00006.html
+
+	* telnetd/telnetd.c (telnetd_run): Break the loop only by the
+	stronger condition `pty_read() < 0', i.e., only on non-masked
+	read errors.  This reverts a change introduced in 2015-03-15.
+	* telnetd/utility.c (pty_read): Add a comment that the read
+	errors EWOULDBLOCK, EAGAIN, and EIO are treated specially.
+
 2015-08-07  Mats Erik Andersson  <gnu@gisladisker.se>
 
 	ifconfig: Statistics for BSD systems.
diff --git a/telnetd/telnetd.c b/telnetd/telnetd.c
index faecc072..0bf102ac 100644
--- a/telnetd/telnetd.c
+++ b/telnetd/telnetd.c
@@ -662,7 +662,13 @@ telnetd_run (void)
       if (FD_ISSET (pty, &ibits))
 	{
 	  /* Something to read from the pty... */
-	  if (pty_read () <= 0)
+
+	  /* Observe that pty_read() is masking a few select
+	   * read errors with the return value 0.  Let them
+	   * pass for further manipulation.  Issue reported in
+	   * http://lists.gnu.org/archive/html/bug-inetutils/2015-07/msg00006.html
+	   */
+	  if (pty_read () < 0)
 	    break;
 
 	  /* The first byte is now TIOCPKT data.  Peek at it.  */
diff --git a/telnetd/utility.c b/telnetd/utility.c
index e7ffb8ed..e493dff2 100644
--- a/telnetd/utility.c
+++ b/telnetd/utility.c
@@ -372,6 +372,14 @@ pty_input_putback (const char *str, size_t len)
   return 0;
 }
 
+/* pty_read()
+ *
+ * Read errors EWOULDBLOCK, EAGAIN, and EIO are
+ * tweeked into reporting zero bytes input.
+ * In particular, EIO is known to appear when
+ * reading off the master side, before having
+ * an active slave side.
+ */
 int
 pty_read (void)
 {
-- 
2.26.0.292.g33ef6b2f38

