summaryrefslogtreecommitdiffstats
path: root/vtysh
diff options
context:
space:
mode:
authorRodny Molina <rmolina@linkedin.com>2018-05-11 07:15:48 +0200
committerRodny Molina <rmolina@linkedin.com>2018-05-13 03:59:11 +0200
commita4364a44ae3180536b8f6faac0ca2f1404915385 (patch)
tree94e751b708929ed85394e0ffffe38eda7dface30 /vtysh
parentMerge pull request #2217 from donaldsharp/pim_threads (diff)
downloadfrr-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.c78
-rw-r--r--vtysh/vtysh.h1
-rw-r--r--vtysh/vtysh_main.c11
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))