From fe1b683fd0302f84d589c25987273abb3d8846c5 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 21 Feb 2019 12:36:32 -0600 Subject: [PATCH] virsh: Treat \n like ; in batch mode I wanted to do a demonstration with virsh batch mode, which takes multiple commands all packed into a single argument: $ virsh -c test:///default 'echo a; echo b;' a b but that produced a really long line, so I tried to make it more legible: $ virsh -c test:///default ' echo a; echo b; ' error: unknown command: ' ' Let's be more like the shell, and treat unquoted newline as a command separator just as we do for semicolon. In fact, with that, I can even now mix styles: $ virsh -c test:///default ' echo a; echo b echo c ' a b c Signed-off-by: Eric Blake Reviewed-by: John Ferlan --- tests/virshtest.c | 4 ++++ tools/virsh.pod | 4 ++-- tools/virt-admin.pod | 4 ++-- tools/vsh.c | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/virshtest.c b/tests/virshtest.c index 7fb701d580..bb053cec27 100644 --- a/tests/virshtest.c +++ b/tests/virshtest.c @@ -411,6 +411,10 @@ mymain(void) DO_TEST(34, "hello\n", "echo --str hello"); DO_TEST(35, "hello\n", "echo --hi"); + /* 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"); + # undef DO_TEST VIR_FREE(custom_uri); diff --git a/tools/virsh.pod b/tools/virsh.pod index 67edb57b14..146cd03e85 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -40,8 +40,8 @@ as a name. 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 -between commands. Within I, virsh understands the +and their arguments joined with whitespace and separated by semicolons or +newlines between commands. 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 3ddbbff934..d34f768fbb 100644 --- a/tools/virt-admin.pod +++ b/tools/virt-admin.pod @@ -23,8 +23,8 @@ Where I is one of the commands listed below. 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 -between commands. Within I, virt-admin understands the +and their arguments joined with whitespace and separated by semicolons or +newlines between commands. 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 610de4495b..823f3c1477 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1664,7 +1664,7 @@ vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res, if (*p == '\0') return VSH_TK_END; - if (*p == ';') { + if (*p == ';' || *p == '\n') { parser->pos = ++p; /* = \0 or begin of next command */ return VSH_TK_SUBCMD_END; } @@ -1672,7 +1672,7 @@ vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res, while (*p) { /* end of token is blank space or ';' */ if (!double_quote && !single_quote && - (*p == ' ' || *p == '\t' || *p == ';')) + (*p == ' ' || *p == '\t' || *p == ';' || *p == '\n')) break; if (!double_quote && *p == '\'') { /* single quote */