diff options
author | Rodny Molina <rmolina@linkedin.com> | 2018-05-11 07:15:48 +0200 |
---|---|---|
committer | Rodny Molina <rmolina@linkedin.com> | 2018-05-13 03:59:11 +0200 |
commit | a4364a44ae3180536b8f6faac0ca2f1404915385 (patch) | |
tree | 94e751b708929ed85394e0ffffe38eda7dface30 /vtysh | |
parent | Merge pull request #2217 from donaldsharp/pim_threads (diff) | |
download | frr-a4364a44ae3180536b8f6faac0ca2f1404915385.tar.xz frr-a4364a44ae3180536b8f6faac0ca2f1404915385.zip |
vtysh: Extending vtysh to allow question-mark cmds
Currently, "vtysh -c" interface does not provide a logic to parse
commands ending with '?' character. In consequence, the following behavior
is observed:
$ vtysh -c "show bgp ?"
% Unknown command.
With these changes, i'm extending FRR's parser to be able to handle
these commands, which allow a more friendly interaction with users
that rely on "vtysh -c" interface. The typical use-case here is for
scenarios in which the final users relie on external/their-own CLI and
require a friendly interface to FRR's vtysh cli.
$ vtysh -c "show bgp ?"
<cr>
A.B.C.D Network in the BGP routing table to
display
A.B.C.D/M IPv4 prefix
X:X::X:X Network in the BGP routing table to display
X:X::X:X/M IPv6 prefix
attribute-info List all bgp attribute information
cidr-only Display only routes with non-natural netmasks
community Display routes matching the communities
community-info List all bgp community information
...
Signed-off-by: Rodny Molina <rmolina@linkedin.com>
Diffstat (limited to 'vtysh')
-rw-r--r-- | vtysh/vtysh.c | 78 | ||||
-rw-r--r-- | vtysh/vtysh.h | 1 | ||||
-rw-r--r-- | vtysh/vtysh_main.c | 11 |
3 files changed, 76 insertions, 14 deletions
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 01ba00776..785a16fba 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -845,27 +845,29 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp) return (retcode); } -/* We don't care about the point of the cursor when '?' is typed. */ -static int vtysh_rl_describe(void) +/* + * Function processes cli commands terminated with '?' character when entered + * through either 'vtysh' or 'vtysh -c' interfaces. + */ +static int vtysh_process_questionmark(const char *input, int input_len) { - int ret; + int ret, width = 0; unsigned int i; - vector vline; - vector describe; - int width; + vector vline, describe; struct cmd_token *token; - vline = cmd_make_strvec(rl_line_buffer); + if (!input) + return 1; + + vline = cmd_make_strvec(input); /* In case of '> ?'. */ if (vline == NULL) { vline = vector_init(1); vector_set(vline, NULL); - } else if (rl_end && isspace((int)rl_line_buffer[rl_end - 1])) + } else if (input_len && isspace((int)input[input_len - 1])) vector_set(vline, NULL); - fprintf(stdout, "\n"); - describe = cmd_describe_command(vline, vty, &ret); /* Ambiguous and no match error. */ @@ -874,7 +876,6 @@ static int vtysh_rl_describe(void) cmd_free_strvec(vline); vector_free(describe); fprintf(stdout, "%% Ambiguous command.\n"); - rl_on_new_line(); return 0; break; case CMD_ERR_NO_MATCH: @@ -882,7 +883,6 @@ static int vtysh_rl_describe(void) if (describe) vector_free(describe); fprintf(stdout, "%% There is no matched command.\n"); - rl_on_new_line(); return 0; break; } @@ -932,9 +932,61 @@ static int vtysh_rl_describe(void) cmd_free_strvec(vline); vector_free(describe); + return 0; +} + +/* + * Entry point for user commands terminated with '?' character and typed through + * the usual vtysh's stdin interface. This is the function being registered with + * readline() api's. + */ +static int vtysh_rl_describe(void) +{ + int ret; + + fprintf(stdout, "\n"); + + ret = vtysh_process_questionmark(rl_line_buffer, rl_end); rl_on_new_line(); - return 0; + return ret; +} + +/* + * Function in charged of processing vtysh instructions terminating with '?' + * character and received through the 'vtysh -c' interface. If user's + * instruction is well-formatted, we will call the same processing routine + * utilized by the traditional vtysh's stdin interface. + */ +int vtysh_execute_command_questionmark(char *input) +{ + int input_len, qmark_count = 0; + const char *str; + + if (!(input && *input)) + return 1; + + /* Finding out question_mark count and strlen */ + for (str = input; *str; ++str) { + if (*str == '?') + qmark_count++; + } + input_len = str - input; + + /* + * Verify that user's input terminates in '?' and that patterns such as + * 'cmd ? subcmd ?' are prevented. + */ + if (qmark_count != 1 || input[input_len - 1] != '?') + return 1; + + /* + * Questionmark-processing function is not expecting to receive '?' + * character in input string. + */ + input[input_len - 1] = '\0'; + + return vtysh_process_questionmark(input, input_len - 1); } /* Result of cmd_complete_command() call will be stored here diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index f3e58f309..ccfdd6557 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -71,6 +71,7 @@ void vtysh_user_init(void); int vtysh_execute(const char *); int vtysh_execute_no_pager(const char *); +int vtysh_execute_command_questionmark(char *input); char *vtysh_prompt(void); diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index cd59d8094..3dd70983b 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -611,7 +611,16 @@ int main(int argc, char **argv, char **env) if (logfile) log_it(cmd->line); - ret = vtysh_execute_no_pager(cmd->line); + /* + * Parsing logic for regular commands will be different than + * for those commands requiring further processing, such as + * cli instructions terminating with question-mark character. + */ + if (!vtysh_execute_command_questionmark(cmd->line)) + ret = CMD_SUCCESS; + else + ret = vtysh_execute_no_pager(cmd->line); + if (!no_error && !(ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON || ret == CMD_WARNING)) |