From d298a8b6ceb2dd57b1e1d032122329704f05ef4f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 14 Aug 2017 10:42:41 +0100 Subject: [PATCH] Allow reading stdin on Windows instead of forcibly opening console MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was filed against Ľubomír Carik's github project for openconnect-gui; https://github.com/openconnect/openconnect-gui/issues/101 It isn't perfect, as the ANSI code page on Windows can be different from the OEM code page used for the console, so fgetws() is likely to do the wrong thing — which is why we force-opened the console and used ReadConsoleW() in the first place. But perfect is the enemy of good in this case, as reading from something other than stdin is *definitely* wrong. We still use ReadConsoleW() when stdin does happen to be the console, so that part shouldn't regress. I hate Windows... Signed-off-by: David Woodhouse --- main.c | 55 +++++++++++++++++++++-------------------------- www/changelog.xml | 1 + 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/main.c b/main.c index a18bfd22..935147f4 100644 --- a/main.c +++ b/main.c @@ -367,36 +367,37 @@ static char *convert_arg_to_utf8(char **argv, char *arg) static void read_stdin(char **string, int hidden, int allow_fail) { CONSOLE_READCONSOLE_CONTROL rcc = { sizeof(rcc), 0, 13, 0 }; - HANDLE conh, stdinh = GetStdHandle(STD_INPUT_HANDLE); + HANDLE stdinh = GetStdHandle(STD_INPUT_HANDLE); DWORD cmode, nr_read; wchar_t wbuf[1024]; char *buf; - conh = stdinh; - if (!GetConsoleMode(conh, &cmode)) { - /* STDIN is not a console? Try opening it explicitly */ - conh = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ, - 0,OPEN_EXISTING, 0, 0); - if (conh == INVALID_HANDLE_VALUE || !GetConsoleMode(conh, &cmode)) { + if (GetConsoleMode(stdinh, &cmode)) { + if (hidden) + SetConsoleMode(stdinh, cmode & (~ENABLE_ECHO_INPUT)); + + if (!ReadConsoleW(stdinh, wbuf, sizeof(wbuf)/2, &nr_read, &rcc)) { char *errstr = openconnect__win32_strerror(GetLastError()); - fprintf(stderr, _("Failed to open CONIN$: %s\n"), errstr); + fprintf(stderr, _("ReadConsole() failed: %s\n"), errstr); free(errstr); *string = NULL; - goto out; + if (hidden) + SetConsoleMode(stdinh, cmode); + return; } + if (hidden) + SetConsoleMode(stdinh, cmode); + } else { + /* Not a console; maybe reading from a piped stdin? */ + if (!fgetws(wbuf, sizeof(wbuf)/2, stdin)) { + char *errstr = openconnect__win32_strerror(GetLastError()); + fprintf(stderr, _("fgetws() failed: %s\n"), errstr); + free(errstr); + *string = NULL; + return; + } + nr_read = wcslen(wbuf); } - if (hidden) { - SetConsoleMode(conh, cmode & (~ENABLE_ECHO_INPUT)); - } - - if (!ReadConsoleW(conh, wbuf, sizeof(wbuf)/2, &nr_read, &rcc)) { - char *errstr = openconnect__win32_strerror(GetLastError()); - fprintf(stderr, _("ReadConsole() failed: %s\n"), errstr); - free(errstr); - *string = NULL; - goto out; - } - if (nr_read >= 2 && wbuf[nr_read - 1] == 10 && wbuf[nr_read - 2] == 13) { wbuf[nr_read - 2] = 0; nr_read -= 2; @@ -408,7 +409,7 @@ static void read_stdin(char **string, int hidden, int allow_fail) fprintf(stderr, _("Error converting console input: %s\n"), errstr); free(errstr); - goto out; + return; } buf = malloc(nr_read); if (!buf) { @@ -422,18 +423,10 @@ static void read_stdin(char **string, int hidden, int allow_fail) errstr); free(errstr); free(buf); - goto out; + return; } *string = buf; - -out: - if (hidden) { - SetConsoleMode(conh, cmode); - fprintf(stderr, "\n"); - } - if (conh != stdinh && conh != INVALID_HANDLE_VALUE) - CloseHandle(conh); } #elif defined(HAVE_ICONV) diff --git a/www/changelog.xml b/www/changelog.xml index 6016256a..ed2d08b1 100644 --- a/www/changelog.xml +++ b/www/changelog.xml @@ -15,6 +15,7 @@