From 7e1b03f763350fefa1a68e45764e2076063fdb15 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 12 Jun 2019 14:47:48 +0200 Subject: 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 --- src/vty/command.c | 51 +++++++++++++++++++++++++++----- tests/tdef/tdef_vty_test_config_root.vty | 11 +++---- tests/vty/vty_transcript_test.vty | 12 ++++---- 3 files changed, 56 insertions(+), 18 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 diff --git a/tests/tdef/tdef_vty_test_config_root.vty b/tests/tdef/tdef_vty_test_config_root.vty index 8613ff36..f3aba0f9 100644 --- a/tests/tdef/tdef_vty_test_config_root.vty +++ b/tests/tdef/tdef_vty_test_config_root.vty @@ -163,7 +163,6 @@ tdef_vty_test(config)# timer te T2 tdef_vty_test(config)# timer test T2 100 tdef_vty_test(config)# timer tes T2 100 -% Error: no timers found tdef_vty_test(config)# timer te T2 100 % Ambiguous command. @@ -219,7 +218,6 @@ tdef_vty_test(config)# timer softw T3 software: T3 = 480 m Fix bugs (default: 480 m) tdef_vty_test(config)# timer softw T3 23 -% Error: no timers found tdef_vty_test(config)# timer tea: T1 = 50 s Water Boiling Timeout (default: 50 s) @@ -234,7 +232,7 @@ test: T2147483647 = 4294967295 m Very large (default: 4294967295 m) test: X23 = 239471 s Negative T number (default: 239471 s) software: T1 = 13 m Write code (default: 30 m) software: T2 = 0 ms Hit segfault (default: 20 ms) -software: T3 = 480 m Fix bugs (default: 480 m) +software: T3 = 23 m Fix bugs (default: 480 m) tdef_vty_test(config)# do show timer tea: T1 = 50 s Water Boiling Timeout (default: 50 s) @@ -249,13 +247,14 @@ test: T2147483647 = 4294967295 m Very large (default: 4294967295 m) test: X23 = 239471 s Negative T number (default: 239471 s) software: T1 = 13 m Write code (default: 30 m) software: T2 = 0 ms Hit segfault (default: 20 ms) -software: T3 = 480 m Fix bugs (default: 480 m) +software: T3 = 23 m Fix bugs (default: 480 m) tdef_vty_test(config)# show running-config ... !timer timer tea T3 32 timer software T1 13 timer software T2 0 +timer software T3 23 ... !timer tdef_vty_test(config)# timer tea T3 default @@ -263,10 +262,12 @@ tdef_vty_test(config)# timer software T1 default tdef_vty_test(config)# show running-config ... !timer timer software T2 0 +timer software T3 23 ... !timer tdef_vty_test(config)# timer softw 2 default -% Error: no timers found tdef_vty_test(config)# timer software 2 default tdef_vty_test(config)# show running-config ... !timer +timer software T3 23 +... !timer diff --git a/tests/vty/vty_transcript_test.vty b/tests/vty/vty_transcript_test.vty index 15577446..f2dbacbf 100644 --- a/tests/vty/vty_transcript_test.vty +++ b/tests/vty/vty_transcript_test.vty @@ -16,13 +16,13 @@ vty_transcript_test> multi0 two ok argc=1 two vty_transcript_test> multi0 o -ok argc=1 o +ok argc=1 one vty_transcript_test> multi0 t % Ambiguous command. vty_transcript_test> multi0 th -ok argc=1 th +ok argc=1 three vty_transcript_test> multi0 % Command incomplete. @@ -39,13 +39,13 @@ vty_transcript_test> multi1 two ok argc=1 two vty_transcript_test> multi1 o -ok argc=1 o +ok argc=1 one vty_transcript_test> multi1 t % Ambiguous command. vty_transcript_test> multi1 th -ok argc=1 th +ok argc=1 three vty_transcript_test> multi1 ok argc=0 @@ -68,10 +68,10 @@ vty_transcript_test> multi2 ok argc=0 vty_transcript_test> multi0 thr -ok argc=1 thr +ok argc=1 three vty_transcript_test> multi1 on -ok argc=1 on +ok argc=1 one vty_transcript_test> multi2 t % Ambiguous command. -- cgit v1.2.3