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(a)redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
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