Commit d298a8b6 authored by David Woodhouse's avatar David Woodhouse

Allow reading stdin on Windows instead of forcibly opening console

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: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 0b103e8d
......@@ -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)
......
......@@ -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>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment