]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Allow reading stdin on Windows instead of forcibly opening console
authorDavid Woodhouse <dwmw2@infradead.org>
Mon, 14 Aug 2017 09:42:41 +0000 (10:42 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Mon, 14 Aug 2017 09:51:29 +0000 (10:51 +0100)
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 <dwmw2@infradead.org>
main.c
www/changelog.xml

diff --git a/main.c b/main.c
index a18bfd2218a57cf0f9893568a4c7206f649a6dee..935147f462dec1cc43540c09011bb8928c8fa1b4 100644 (file)
--- 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)
index 6016256ac3319a60aadb4acbefebed0046863baa..ed2d08b14953579d476d08b516c5f57f63ce45c4 100644 (file)
@@ -15,6 +15,7 @@
 <ul>
    <li><b>OpenConnect HEAD</b>
      <ul>
+       <li>Fix <tt>--passwd-on-stdin</tt> for Windows to not forcibly open console.</li>
        <li>Fix portability of shell scripts in test suite.</li>
        <li>Add Google Authenticator TOTP support for Juniper.</li>
        <li>Add RFC7469 key PIN support for cert hashes.</li>