By splitting generic parts from virsh we will need to preserve each client's
history, yet we use hardcoded names and paths. This patch fixes this
problem.
---
src/libvirt_private.syms | 1 +
src/util/virstring.c | 32 +++++++++++++++++++++++++++++
src/util/virstring.h | 1 +
tools/virsh.c | 14 ++++++-------
tools/vsh.c | 52 +++++++++++++++++++++++++++++-------------------
tools/vsh.h | 5 ++++-
6 files changed, 76 insertions(+), 29 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 45f42f5..e2140e4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2187,6 +2187,7 @@ virStringSplit;
virStringSplitCount;
virStringStripControlChars;
virStringStripIPv6Brackets;
+virStringToUpper;
virStrncpy;
virStrndup;
virStrToDouble;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 5794f96..4f0afe9 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -1020,3 +1020,35 @@ virStringStripControlChars(char *str)
}
str[j] = '\0';
}
+
+/**
+ * virStringToUpper:
+ * @str: string to capitalize
+ * @dst: where to store the new capitalized string
+ *
+ * Capitalize the string with replacement of all '-' characters for '_'
+ * characters. Caller frees the result.
+ *
+ * Returns 0 if src is NULL, 1 if capitalization was successfull, -1 on failure.
+ */
+int
+virStringToUpper(char **dst, const char *src)
+{
+ char *cap = NULL;
+ size_t i;
+
+ if (!src)
+ return 0;
+
+ if (VIR_ALLOC_N(cap, strlen(src) + 1) < 0)
+ return -1;
+
+ for (i = 0; src[i]; i++) {
+ cap[i] = c_toupper(src[i]);
+ if (cap[i] == '-')
+ cap[i] = '_';
+ }
+
+ *dst = cap;
+ return 1;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index e6dcb32..9848fb6 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -258,6 +258,7 @@ size_t virStringListLength(char **strings);
int virStringSortCompare(const void *a, const void *b);
int virStringSortRevCompare(const void *a, const void *b);
+int virStringToUpper(char **dst, const char *src);
ssize_t virStringSearch(const char *str,
const char *regexp,
diff --git a/tools/virsh.c b/tools/virsh.c
index 9f9e1d3..2d198cd 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -33,7 +33,6 @@
#include <errno.h>
#include <getopt.h>
#include <sys/time.h>
-#include "c-ctype.h"
#include <fcntl.h>
#include <locale.h>
#include <time.h>
@@ -169,7 +168,7 @@ virshReconnect(vshControl *ctl)
"disconnect from the hypervisor"));
}
- priv->conn = virshConnect(ctl, ctl->name, priv->readonly);
+ priv->conn = virshConnect(ctl, ctl->connname, priv->readonly);
if (!priv->conn) {
if (disconnected)
@@ -629,7 +628,7 @@ virshInit(vshControl *ctl)
NULL)) < 0)
return false;
- if (ctl->name) {
+ if (ctl->connname) {
virshReconnect(ctl);
/* Connecting to a named connection must succeed, but we delay
* connecting to the default connection until we need it
@@ -661,7 +660,7 @@ virshDeinit(vshControl *ctl)
virshControlPtr priv = ctl->privData;
vshDeinit(ctl);
- VIR_FREE(ctl->name);
+ VIR_FREE(ctl->connname);
if (priv->conn) {
int ret;
virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect);
@@ -937,8 +936,8 @@ virshParseArgv(vshControl *ctl, int argc, char **argv)
while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt,
&longindex)) != -1) {
switch (arg) {
case 'c':
- VIR_FREE(ctl->name);
- ctl->name = vshStrdup(ctl, optarg);
+ VIR_FREE(ctl->connname);
+ ctl->connname = vshStrdup(ctl, optarg);
break;
case 'd':
if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) {
@@ -1137,6 +1136,7 @@ main(int argc, char **argv)
memset(ctl, 0, sizeof(vshControl));
memset(&virshCtl, 0, sizeof(virshControl));
+ ctl->name = "virsh"; /* hardcoded name of the binary */
ctl->imode = true; /* default is interactive mode */
ctl->log_fd = -1; /* Initialize log file descriptor */
ctl->debug = VSH_DEBUG_DEFAULT;
@@ -1193,7 +1193,7 @@ main(int argc, char **argv)
virFileActivateDirOverride(argv[0]);
if ((defaultConn = virGetEnvBlockSUID("VIRSH_DEFAULT_CONNECT_URI")))
- ctl->name = vshStrdup(ctl, defaultConn);
+ ctl->connname = vshStrdup(ctl, defaultConn);
if (vshInit(ctl, cmdGroups, NULL) < 0)
exit(EXIT_FAILURE);
diff --git a/tools/vsh.c b/tools/vsh.c
index 62f57ca..043d0fb 100644
--- a/tools/vsh.c
+++ b/tools/vsh.c
@@ -2543,36 +2543,46 @@ vshReadlineCompletion(const char *text, int start,
return matches;
}
-# define VIRTSHELL_HISTSIZE_MAX 500000
+# define HISTSIZE_MAX 500000
static int
vshReadlineInit(vshControl *ctl)
{
char *userdir = NULL;
+ char *name_capitalized = NULL;
int max_history = 500;
- const char *histsize_str;
+ int ret = -1;
+ const char *histsize_str = NULL;
+ const char *histsize_env = NULL;
+ const char *strings[] = {
+ name_capitalized,
+ "HISTSIZE",
+ NULL
+ };
/* Allow conditional parsing of the ~/.inputrc file.
* Work around ancient readline 4.1 (hello Mac OS X),
* which declared it as 'char *' instead of 'const char *'.
*/
- rl_readline_name = (char *) "virtshell";
+ rl_readline_name = ctl->name;
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = vshReadlineCompletion;
+ if (virStringToUpper(&name_capitalized, ctl->name) < 0 ||
+ !(histsize_env = virStringJoin(strings, "_")))
+ goto cleanup;
+
/* Limit the total size of the history buffer */
- if ((histsize_str = virGetEnvBlockSUID("VIRTSHELL_HISTSIZE"))) {
+ if ((histsize_str = virGetEnvBlockSUID(histsize_env))) {
if (virStrToLong_i(histsize_str, NULL, 10, &max_history) < 0) {
- vshError(ctl, "%s", _("Bad $VIRTSHELL_HISTSIZE
value."));
- VIR_FREE(userdir);
- return -1;
- } else if (max_history > VIRTSHELL_HISTSIZE_MAX || max_history < 0) {
- vshError(ctl, _("$VIRTSHELL_HISTSIZE value should be between 0 "
+ vshError(ctl, _("Bad $%s value."), histsize_env);
+ goto cleanup;
+ } else if (max_history > HISTSIZE_MAX || max_history < 0) {
+ vshError(ctl, _("$%s value should be between 0 "
"and %d"),
- VIRTSHELL_HISTSIZE_MAX);
- VIR_FREE(userdir);
- return -1;
+ histsize_env, HISTSIZE_MAX);
+ goto cleanup;
}
}
stifle_history(max_history);
@@ -2584,26 +2594,26 @@ vshReadlineInit(vshControl *ctl)
if (userdir == NULL) {
vshError(ctl, "%s", _("Could not determine home
directory"));
- return -1;
+ goto cleanup;
}
- if (virAsprintf(&ctl->historydir, "%s/virtshell", userdir) < 0)
{
+ if (virAsprintf(&ctl->historydir, "%s/%s", userdir, ctl->name)
< 0) {
vshError(ctl, "%s", _("Out of memory"));
- VIR_FREE(userdir);
- return -1;
+ goto cleanup;
}
if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir)
< 0) {
vshError(ctl, "%s", _("Out of memory"));
- VIR_FREE(userdir);
- return -1;
+ goto cleanup;
}
- VIR_FREE(userdir);
-
read_history(ctl->historyfile);
+ ret = 0;
- return 0;
+ cleanup:
+ VIR_FREE(userdir);
+ VIR_FREE(name_capitalized);
+ return ret;
}
static void
diff --git a/tools/vsh.h b/tools/vsh.h
index ecf52e9..19862d0 100644
--- a/tools/vsh.h
+++ b/tools/vsh.h
@@ -194,7 +194,10 @@ struct _vshCmd {
* vshControl
*/
struct _vshControl {
- char *name; /* connection name */
+ const char *name; /* hardcoded name of the binary that cannot
+ * be changed without recompilation compared
+ * to program name */
+ char *connname; /* connection name */
char *progname; /* program name */
vshCmd *cmd; /* the current command */
char *cmdstr; /* string with command */
--
2.4.3