Fix s_client/s_server waiting for stdin on Windows
authorMatt Caswell <matt@openssl.org>
Fri, 20 May 2016 10:53:26 +0000 (11:53 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 27 May 2016 14:18:46 +0000 (15:18 +0100)
On Windows we were using the function _kbhit() to determine whether there
was input waiting in stdin for us to read. Actually all this does is work
out whether there is a keyboard press event waiting to be processed in the
input buffer. This only seems to work in a standard Windows console (not
Msys console) and also doesn't work if you redirect the input from some
other source (as we do in TLSProxy tests). This commit changes things to
work differently depending on whether we are on the Windows console or not.

RT#4255

Reviewed-by: Richard Levitte <levitte@openssl.org>
apps/apps.c
apps/apps.h
apps/s_client.c
apps/s_server.c

index 5db4b22b3a6a4362586ec3def55c9d383b11f628..a3e1794c31d7b1eccd3d201973db3ab4cffa88bc 100644 (file)
@@ -14,6 +14,7 @@
  */
 # define _POSIX_C_SOURCE 2
 #endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -41,7 +42,7 @@
 #endif
 #include <openssl/bn.h>
 #include <openssl/ssl.h>
-
+#include "s_apps.h"
 #include "apps.h"
 
 #ifdef _WIN32
@@ -2550,3 +2551,31 @@ void wait_for_async(SSL *s)
     select(width, (void *)&asyncfds, NULL, NULL, NULL);
 #endif
 }
+
+/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */
+#if defined(OPENSSL_SYS_MSDOS)
+int has_stdin_waiting(void)
+{
+# if defined(OPENSSL_SYS_WINDOWS)
+    HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE);
+    DWORD events = 0;
+    INPUT_RECORD inputrec;
+    DWORD insize = 1;
+    BOOL peeked;
+
+    if (inhand == INVALID_HANDLE_VALUE) {
+        return 0;
+    }
+
+    peeked = PeekConsoleInput(inhand, &inputrec, insize, &events);
+    if (!peeked) {
+        /* Probably redirected input? _kbhit() does not work in this case */
+        if (!feof(stdin)) {
+            return 1;
+        }
+        return 0;
+    }
+# endif
+    return _kbhit();
+}
+#endif
index 83dc0c157be33454ff9919e26533aa1ee82ee863..6a0acab58c334586971a4ccec490606832276bb4 100644 (file)
@@ -67,6 +67,9 @@ CONF *app_load_config_quiet(const char *filename);
 int app_load_modules(const CONF *config);
 void unbuffer(FILE *fp);
 void wait_for_async(SSL *s);
+# if defined(OPENSSL_SYS_MSDOS)
+int has_stdin_waiting(void);
+# endif
 
 /*
  * Common verification options.
index d8678c39efe3f420abef5b4f758b95e117bc5267..fab5a5d807ed28e2e2ca65621915a460bcc5feae 100644 (file)
@@ -2160,18 +2160,8 @@ int s_client_main(int argc, char **argv)
                     tv.tv_usec = 0;
                     i = select(width, (void *)&readfds, (void *)&writefds,
                                NULL, &tv);
-# if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
-                    if (!i && (!_kbhit() || !read_tty))
+                    if (!i && (!has_stdin_waiting() || !read_tty))
                         continue;
-# else
-                    if (!i && (!((_kbhit())
-                                 || (WAIT_OBJECT_0 ==
-                                     WaitForSingleObject(GetStdHandle
-                                                         (STD_INPUT_HANDLE),
-                                                         0)))
-                               || !read_tty))
-                        continue;
-# endif
                 } else
                     i = select(width, (void *)&readfds, (void *)&writefds,
                                NULL, timeoutp);
@@ -2348,14 +2338,9 @@ int s_client_main(int argc, char **argv)
                 /* break; */
             }
         }
-#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
-# if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
-        else if (_kbhit())
-# else
-        else if ((_kbhit())
-                 || (WAIT_OBJECT_0 ==
-                     WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0)))
-# endif
+/* OPENSSL_SYS_MSDOS includes OPENSSL_SYS_WINDOWS */
+#if defined(OPENSSL_SYS_MSDOS)
+        else if (has_stdin_waiting())
 #else
         else if (FD_ISSET(fileno(stdin), &readfds))
 #endif
index 7271b611ef0968d6457e85a4a9d883a81a3d9cb2..08753c30fdb337acc144fbf9f75f48f033debd37 100644 (file)
@@ -2167,10 +2167,10 @@ static int sv_body(int s, int stype, unsigned char *context)
             tv.tv_sec = 1;
             tv.tv_usec = 0;
             i = select(width, (void *)&readfds, NULL, NULL, &tv);
-            if ((i < 0) || (!i && !_kbhit()))
-                continue;
-            if (_kbhit())
+            if (has_stdin_waiting())
                 read_from_terminal = 1;
+            if ((i < 0) || (!i && !read_from_terminal))
+                continue;
 #else
             if ((SSL_version(con) == DTLS1_VERSION) &&
                 DTLSv1_get_timeout(con, &timeout))