From: Eric Blake Date: Tue, 26 Feb 2019 18:49:25 +0000 (-0600) Subject: virsh: Elide backslash-newline in batch mode X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=5817dec0149a909de65820236f3d8ba8d7bbf53f;p=libvirt.git virsh: Elide backslash-newline in batch mode The previous patch made it possible to split multiple commands by adding newline, but not to split a long single command. The sequence backslash-newline was being used as if it were a quoted newline character, rather than completely elided the way the shell does. Again, add more tests, although this time it seems more like I am suffering from a leaning-toothpick syndrome with all the \. Signed-off-by: Eric Blake Reviewed-by: John Ferlan --- diff --git a/tests/virshtest.c b/tests/virshtest.c index bb053cec27..d77d3d81d4 100644 --- a/tests/virshtest.c +++ b/tests/virshtest.c @@ -414,6 +414,9 @@ mymain(void) /* Tests of multiple commands. */ DO_TEST(36, "a\nb\n", " echo a; echo b;"); DO_TEST(37, "a\nb\n", "\necho a\n echo b\n"); + DO_TEST(38, "a\nb\n", "ec\\\nho a\n echo \\\n b;"); + DO_TEST(39, "a\n b\n", "\"ec\\\nho\" a\n echo \"\\\n b\";"); + DO_TEST(40, "a\n\\\n b\n", "ec\\\nho a\n echo '\\\n b';"); # undef DO_TEST diff --git a/tools/virsh.pod b/tools/virsh.pod index 146cd03e85..0533fb363f 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -41,7 +41,8 @@ The B program can be used either to run one I by giving the command and its arguments on the shell command line, or a I which is a single shell argument consisting of multiple I actions and their arguments joined with whitespace and separated by semicolons or -newlines between commands. Within I, virsh understands the +newlines between commands, where unquoted backslash-newline pairs are +elided. Within I, virsh understands the same single, double, and backslash escapes as the shell, although you must add another layer of shell escaping in creating the single shell argument. If no command is given in the command line, B will then start a minimal diff --git a/tools/virt-admin.pod b/tools/virt-admin.pod index d34f768fbb..9bbff42846 100644 --- a/tools/virt-admin.pod +++ b/tools/virt-admin.pod @@ -24,7 +24,8 @@ The B program can be used either to run one I by giving the command and its arguments on the shell command line, or a I which is a single shell argument consisting of multiple I actions and their arguments joined with whitespace and separated by semicolons or -newlines between commands. Within I, virt-admin understands the +newlines between commands, where unquoted backslash-newline pairs are +elided. Within I, virt-admin understands the same single, double, and backslash escapes as the shell, although you must add another layer of shell escaping in creating the single shell argument. If no command is given in the command line, B will then start a minimal diff --git a/tools/vsh.c b/tools/vsh.c index 823f3c1477..2fd1564d15 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1659,8 +1659,8 @@ vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res, *res = q; - while (*p && (*p == ' ' || *p == '\t')) - p++; + while (*p == ' ' || *p == '\t' || (*p == '\\' && p[1] == '\n')) + p += 1 + (*p == '\\'); if (*p == '\0') return VSH_TK_END; @@ -1681,7 +1681,7 @@ vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res, continue; } else if (!single_quote && *p == '\\') { /* escape */ /* - * The same as the bash, a \ in "" is an escaper, + * The same as in shell, a \ in "" is an escaper, * but a \ in '' is not an escaper. */ p++; @@ -1689,6 +1689,10 @@ vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res, if (report) vshError(ctl, "%s", _("dangling \\")); return VSH_TK_ERROR; + } else if (*p == '\n') { + /* Elide backslash-newline entirely */ + p++; + continue; } } else if (!single_quote && *p == '"') { /* double quote */ double_quote = !double_quote;