diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2019-06-12 14:47:48 +0200 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2019-06-14 17:44:16 +0200 |
commit | 7e1b03f763350fefa1a68e45764e2076063fdb15 (patch) | |
tree | 5783342be56399c9e033163e4f415bc774c5d6e5 /src/vty | |
parent | 14aadd5b6f12dddd055a7c82c19df4b5ec119843 (diff) |
vty: command.c: Fix: multi-choice args are no longer passed incomplete to vty func
For instance, take command "multi0 (one|two|three)":
If user executes "multi0 tw", VTY func will receive argv[0]="two"
instead of argv[0]="tw".
Fixes: OS#4045
Change-Id: I91b6621ac3d87fda5412a9b415e7bfb4736c8a9a
Diffstat (limited to 'src/vty')
-rw-r--r-- | src/vty/command.c | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/src/vty/command.c b/src/vty/command.c index 17d28fe6..3c91bfd3 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -2217,7 +2217,7 @@ static int cmd_execute_command_real(vector vline, struct vty *vty, struct cmd_element **cmd) { - unsigned int i; + unsigned int i, j; unsigned int index; vector cmd_vector; struct cmd_element *cmd_element; @@ -2228,6 +2228,10 @@ cmd_execute_command_real(vector vline, struct vty *vty, enum match_type match = 0; int varflag; char *command; + int rc; + /* Used for temporary storage of cmd_deopt() allocated arguments during + argv[] generation */ + void *cmd_deopt_ctx = NULL; /* Make copy of command elements. */ cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node)); @@ -2293,9 +2297,13 @@ cmd_execute_command_real(vector vline, struct vty *vty, varflag = 0; argc = 0; + cmd_deopt_ctx = talloc_named_const(tall_vty_cmd_ctx, 0, __func__); + for (i = 0; i < vector_active(vline); i++) { - if (argc == CMD_ARGC_MAX) - return CMD_ERR_EXEED_ARGC_MAX; + if (argc == CMD_ARGC_MAX) { + rc = CMD_ERR_EXEED_ARGC_MAX; + goto rc_free_deopt_ctx; + } if (varflag) { argv[argc++] = vector_slot(vline, i); continue; @@ -2313,7 +2321,32 @@ cmd_execute_command_real(vector vline, struct vty *vty, || CMD_OPTION(desc->cmd)) argv[argc++] = vector_slot(vline, i); } else { - argv[argc++] = vector_slot(vline, i); + /* multi choice argument. look up which choice + the user meant (can only be one after + filtering and checking for ambigous). For instance, + if user typed "th" for "(two|three)" arg, we + want to pass "three" in argv[]. */ + for (j = 0; j < vector_active(descvec); j++) { + struct desc *desc = vector_slot(descvec, j); + const char *tmp_cmd; + if (!desc) + continue; + if (cmd_match(desc->cmd, vector_slot(vline, i), ANY_MATCH, true) == NO_MATCH) + continue; + if (CMD_OPTION(desc->cmd)) { + /* we need to first remove the [] chars, then check to see what's inside (var or token) */ + tmp_cmd = cmd_deopt(cmd_deopt_ctx, desc->cmd); + } else { + tmp_cmd = desc->cmd; + } + + if(CMD_VARIABLE(tmp_cmd)) { + argv[argc++] = vector_slot(vline, i); + } else { + argv[argc++] = tmp_cmd; + } + break; + } } } @@ -2322,10 +2355,14 @@ cmd_execute_command_real(vector vline, struct vty *vty, *cmd = matched_element; if (matched_element->daemon) - return CMD_SUCCESS_DAEMON; + rc = CMD_SUCCESS_DAEMON; + else /* Execute matched command. */ + rc = (*matched_element->func) (matched_element, vty, argc, argv); - /* Execute matched command. */ - return (*matched_element->func) (matched_element, vty, argc, argv); +rc_free_deopt_ctx: + /* Now after we called the command func, we can free temporary strings */ + talloc_free(cmd_deopt_ctx); + return rc; } int |