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 | 
