This imports a simpler version of GNULIB's getpass() function impl for Windows. Note that GNULIB's impl was buggy as it returned a static string on UNIX, and a heap allocated string on Windows. This new impl always heap allocates. Reviewed-by: Pavel Hrdina <phrdina@xxxxxxxxxx> Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/libvirt.c | 9 ++++----- src/libvirt_private.syms | 1 + src/util/virutil.c | 29 +++++++++++++++++++++++++++++ src/util/virutil.h | 2 ++ 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 04f9fd7ab1..2d02808a89 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -30,7 +30,6 @@ #include <libxml/parser.h> #include <libxml/xpath.h> -#include "getpass.h" #ifdef WITH_CURL # include <curl/curl.h> @@ -157,9 +156,9 @@ virConnectAuthCallbackDefault(virConnectCredentialPtr cred, if (fflush(stdout) != 0) return -1; - bufptr = getpass(""); - if (!bufptr) - return -1; + bufptr = virGetPassword(); + if (STREQ(bufptr, "")) + VIR_FREE(bufptr); break; default: @@ -167,7 +166,7 @@ virConnectAuthCallbackDefault(virConnectCredentialPtr cred, } if (cred[i].type != VIR_CRED_EXTERNAL) { - cred[i].result = g_strdup(STREQ(bufptr, "") && cred[i].defresult ? cred[i].defresult : bufptr); + cred[i].result = bufptr ? bufptr : g_strdup(cred[i].defresult ? cred[i].defresult : ""); cred[i].resultlen = strlen(cred[i].result); } } diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 3608f73b4e..ed451f7bfc 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3374,6 +3374,7 @@ virGetGroupList; virGetGroupName; virGetHostname; virGetHostnameQuiet; +virGetPassword; virGetSelfLastChanged; virGetSystemPageSize; virGetSystemPageSizeKB; diff --git a/src/util/virutil.c b/src/util/virutil.c index 7c2c5a78f6..87ca16c088 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -28,6 +28,10 @@ #include <poll.h> #include <sys/stat.h> +#ifdef WIN32 +# include <conio.h> +#endif /* WIN32 */ + #ifdef MAJOR_IN_MKDEV # include <sys/mkdev.h> #elif MAJOR_IN_SYSMACROS @@ -1731,3 +1735,28 @@ virHostGetDRMRenderNode(void) VIR_DIR_CLOSE(driDir); return ret; } + +/* + * Get a password from the console input stream. + * The caller must free the returned password. + * + * Returns: the password, or NULL + */ +char *virGetPassword(void) +{ +#ifdef WIN32 + GString *pw = g_string_new(""); + + while (1) { + char c = _getch(); + if (c == '\r') + break; + + g_string_append_c(pw, c); + } + + return g_string_free(pw, FALSE); +#else /* !WIN32 */ + return g_strdup(getpass("")); +#endif /* ! WIN32 */ +} diff --git a/src/util/virutil.h b/src/util/virutil.h index 1a6ae1787a..62a53f34cb 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -159,3 +159,5 @@ char *virHostGetDRMRenderNode(void) G_GNUC_NO_INLINE; */ #define VIR_ASSIGN_IS_OVERFLOW(lvalue, rvalue) \ (((lvalue) = (rvalue)) != (rvalue)) + +char *virGetPassword(void); -- 2.24.1