mirror of https://gitee.com/openkylin/libvirt.git
virsh: rework command parsing
Old virsh command parsing mashes all the args back into a string and miss the quotes, this patches fix it. It is also needed for introducing qemu-monitor-command which is very useful. This patches uses the new vshCommandParser abstraction and adds vshCommandArgvParse() for arguments vector, so we don't need to mash arguments vector into a command sting. And the usage was changed: old: virsh [options] [commands] new: virsh [options]... [<command_string>] virsh [options]... <command> [args...] So we still support commands like: "define D.xml; dumpxml D" was parsed as a commands-string. and support commands like: we will not mash them into a string, we use new argv parser for it. But we don't support the command like: "define D.xml; dumpxml" was parsed as a command-name, but we have no such command-name. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
This commit is contained in:
parent
a93f514f5f
commit
a2943243c4
|
@ -10336,11 +10336,51 @@ typedef enum {
|
|||
typedef struct __vshCommandParser {
|
||||
vshCommandToken (*getNextArg)(vshControl *, struct __vshCommandParser *,
|
||||
char **);
|
||||
/* vshCommandStringGetArg() */
|
||||
char *pos;
|
||||
/* vshCommandArgvGetArg() */
|
||||
char **arg_pos;
|
||||
char **arg_end;
|
||||
} vshCommandParser;
|
||||
|
||||
static int vshCommandParse(vshControl *ctl, vshCommandParser *parser);
|
||||
|
||||
/* ---------------
|
||||
* Command argv parsing
|
||||
* ---------------
|
||||
*/
|
||||
|
||||
static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
|
||||
vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
|
||||
{
|
||||
if (parser->arg_pos == parser->arg_end) {
|
||||
*res = NULL;
|
||||
return VSH_TK_END;
|
||||
}
|
||||
|
||||
*res = vshStrdup(ctl, *parser->arg_pos);
|
||||
parser->arg_pos++;
|
||||
return VSH_TK_ARG;
|
||||
}
|
||||
|
||||
static int vshCommandArgvParse(vshControl *ctl, int nargs, char **argv)
|
||||
{
|
||||
vshCommandParser parser;
|
||||
|
||||
if (nargs <= 0)
|
||||
return FALSE;
|
||||
|
||||
parser.arg_pos = argv;
|
||||
parser.arg_end = argv + nargs;
|
||||
parser.getNextArg = vshCommandArgvGetArg;
|
||||
return vshCommandParse(ctl, &parser);
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
* Command string parsing
|
||||
* ---------------
|
||||
*/
|
||||
|
||||
static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
|
||||
vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
|
||||
{
|
||||
|
@ -11045,7 +11085,8 @@ static void
|
|||
vshUsage(void)
|
||||
{
|
||||
const vshCmdDef *cmd;
|
||||
fprintf(stdout, _("\n%s [options] [commands]\n\n"
|
||||
fprintf(stdout, _("\n%s [options]... [<command_string>]"
|
||||
"\n%s [options]... <command> [args...]\n\n"
|
||||
" options:\n"
|
||||
" -c | --connect <uri> hypervisor connection URI\n"
|
||||
" -r | --readonly connect readonly\n"
|
||||
|
@ -11055,7 +11096,7 @@ vshUsage(void)
|
|||
" -t | --timing print timing information\n"
|
||||
" -l | --log <file> output logging to file\n"
|
||||
" -v | --version program version\n\n"
|
||||
" commands (non interactive mode):\n"), progname);
|
||||
" commands (non interactive mode):\n"), progname, progname);
|
||||
|
||||
for (cmd = commands; cmd->name; cmd++)
|
||||
fprintf(stdout,
|
||||
|
@ -11175,26 +11216,13 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
|
|||
|
||||
if (argc > end) {
|
||||
/* parse command */
|
||||
char *cmdstr;
|
||||
int sz = 0, ret;
|
||||
|
||||
ctl->imode = FALSE;
|
||||
|
||||
for (i = end; i < argc; i++)
|
||||
sz += strlen(argv[i]) + 1; /* +1 is for blank space between items */
|
||||
|
||||
cmdstr = vshCalloc(ctl, sz + 1, 1);
|
||||
|
||||
for (i = end; i < argc; i++) {
|
||||
strncat(cmdstr, argv[i], sz);
|
||||
sz -= strlen(argv[i]);
|
||||
strncat(cmdstr, " ", sz--);
|
||||
if (argc - end == 1) {
|
||||
vshDebug(ctl, 2, "commands: \"%s\"\n", argv[end]);
|
||||
return vshCommandStringParse(ctl, argv[end]);
|
||||
} else {
|
||||
return vshCommandArgvParse(ctl, argc - end, argv + end);
|
||||
}
|
||||
vshDebug(ctl, 2, "command: \"%s\"\n", cmdstr);
|
||||
ret = vshCommandStringParse(ctl, cmdstr);
|
||||
|
||||
VIR_FREE(cmdstr);
|
||||
return ret;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@ virsh - management user interface
|
|||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
virsh <subcommand> [args]
|
||||
B<virsh> [I<OPTION>]... [I<COMMAND_STRING>]
|
||||
|
||||
B<virsh> [I<OPTION>]... I<COMMAND> [I<ARG>]...
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
@ -22,20 +24,25 @@ KVM, LXC, OpenVZ, VirtualBox, OpenNebula, and VMware ESX.
|
|||
|
||||
The basic structure of most virsh usage is:
|
||||
|
||||
virsh <command> <domain-id> [OPTIONS]
|
||||
virsh <command> <domain-id> [ARG]...
|
||||
|
||||
Where I<command> is one of the commands listed below, I<domain-id>
|
||||
is the numeric domain id, or the domain name (which will be internally
|
||||
translated to domain id), and I<OPTIONS> are command specific
|
||||
translated to domain id), and I<ARGS> are command specific
|
||||
options. There are a few exceptions to this rule in the cases where
|
||||
the command in question acts on all domains, the entire machine,
|
||||
or directly on the xen hypervisor. Those exceptions will be clear for
|
||||
each of those commands.
|
||||
|
||||
The B<virsh> program can be used either to run one command at a time
|
||||
by giving the command as an argument on the command line, or as a shell
|
||||
if no command is given in the command line, it will then start a minimal
|
||||
interpreter waiting for your commands and the B<quit> command will then exit
|
||||
The B<virsh> program can be used either to run one I<COMMAND> by giving the
|
||||
command and its arguments on the shell command line, or a I<COMMAND_STRING>
|
||||
which is a single shell argument consisting of multiple I<COMMAND> actions
|
||||
and their arguments joined with whitespace, and separated by semicolons
|
||||
between commands. Within I<COMMAND_STRING>, 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<virsh> will then start a minimal
|
||||
interpreter waiting for your commands, and the B<quit> command will then exit
|
||||
the program.
|
||||
|
||||
=head1 NOTES
|
||||
|
|
Loading…
Reference in New Issue