From 0eda390d68c456975289471e68b615ae096ab33b Mon Sep 17 00:00:00 2001
From: Ron Yorston <rmy@pobox.com>
Date: Fri, 8 Feb 2019 09:54:21 +0000
Subject: ash: improve handling of 'read -t 0'

Instead of always returning that no input is available:

- for a disk file return 'available';
- for the console return 'not available';
- for anything else (e.g. pipe) return whatever poll says.

This fixes the test ash-read/read_t0.tests.
---
 shell/shell_common.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

(limited to 'shell')

diff --git a/shell/shell_common.c b/shell/shell_common.c
index e7c07e6a9..70ecf2095 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -136,20 +136,28 @@ shell_builtin_read(struct builtin_read_params *params)
 	}
 
 	if (params->opt_t && end_ms == 0) {
-#if !ENABLE_PLATFORM_MINGW32
 		/* "If timeout is 0, read returns immediately, without trying
 		 * to read any data. The exit status is 0 if input is available
 		 * on the specified file descriptor, non-zero otherwise."
 		 * bash seems to ignore -p PROMPT for this use case.
 		 */
 		int r;
+#if ENABLE_PLATFORM_MINGW32
+		HANDLE handle = (HANDLE)_get_osfhandle(fd);
+		DWORD filetype = FILE_TYPE_UNKNOWN;
+
+		if (handle != INVALID_HANDLE_VALUE)
+			filetype = GetFileType(handle);
+		/* poll uses WaitForSingleObject which can't handle disk files */
+		if (filetype == FILE_TYPE_DISK || filetype == FILE_TYPE_UNKNOWN)
+			return (const char *)(uintptr_t)(0);
+		if (isatty(fd))
+			return (const char *)(uintptr_t)(1);
+#endif
 		pfd[0].events = POLLIN;
 		r = poll(pfd, 1, /*timeout:*/ 0);
 		/* Return 0 only if poll returns 1 ("one fd ready"), else return 1: */
 		return (const char *)(uintptr_t)(r <= 0);
-#else
-		return (const char *)(uintptr_t)(1);
-#endif
 	}
 
 	if (params->opt_p && isatty(fd)) {
-- 
cgit v1.2.3-55-g6feb