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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list