From 61fb1df74d11f16ebfde36027da91b6cc1635375 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Mon, 13 Nov 2017 13:34:54 +0100 Subject: [PATCH] vshReadlineParse: Escape returned results if needed When returning a string that needs escaping there are two scenarios that can happen. Firstly, user already started the string with a quote (or double quote) in which case we don't need to do anything - readline takes care of that. However, if they haven't typed anything yet, we need to escape the string ourselves. Signed-off-by: Michal Privoznik --- tools/vsh.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/vsh.c b/tools/vsh.c index 3c93e94d8d..e179a04070 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -2735,6 +2735,14 @@ vshReadlineParse(const char *text, int state) res = vshReadlineOptionsGenerator(text, state, cmd); } + if (res && + !rl_completion_quote_character) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + virBufferEscapeShell(&buf, res); + VIR_FREE(res); + res = virBufferContentAndReset(&buf); + } + if (!res) { vshCommandFree(partial); partial = NULL; @@ -2754,6 +2762,16 @@ vshReadlineCompletion(const char *text, return matches; } + +static int +vshReadlineCharIsQuoted(char *line, int idx) +{ + return idx > 0 && + line[idx - 1] == '\\' && + !vshReadlineCharIsQuoted(line, idx - 1); +} + + # define HISTSIZE_MAX 500000 static int @@ -2765,6 +2783,7 @@ vshReadlineInit(vshControl *ctl) char *histsize_env = NULL; const char *histsize_str = NULL; const char *break_characters = " \t\n\\`@$><=;|&{("; + const char *quote_characters = "\"'"; /* Opaque data for autocomplete callbacks. */ autoCompleteOpaque = ctl; @@ -2788,6 +2807,14 @@ vshReadlineInit(vshControl *ctl) rl_basic_word_break_characters = (char *) break_characters; # endif +# if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION > 0x0402 + rl_completer_quote_characters = quote_characters; + rl_char_is_quoted_p = vshReadlineCharIsQuoted; +# else + rl_completer_quote_characters = (char *) quote_characters; + rl_char_is_quoted_p = (Function *) vshReadlineCharIsQuoted; +# endif + if (virAsprintf(&histsize_env, "%s_HISTSIZE", ctl->env_prefix) < 0) goto cleanup;