diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2020-10-21 05:07:34 +0700 |
---|---|---|
committer | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2020-10-21 06:27:48 +0700 |
commit | 72b90883f9913a29581589cb5954e0f02ca63778 (patch) | |
tree | 1c9e9a6a618c1d0ed74be6be122e3d71746df4dc | |
parent | e7bf4354b9914aa41bd5b7e1fa95095bb77ba4c4 (diff) |
vty: introduce the expert mode and a command to enable it
Some VTY commands are intentionally hidden, e.g. because they might
by relatively dangerous if used in production operation. We equip
such commands with a special attribute - CMD_ATTR_HIDDEN.
The problem is that neiter they appear in the XML VTY reference,
nor in the online VTY help, so it's a bit tricky to invoke them.
This change introduces so-called 'expert' mode, in which hidden
(but not deprecated) commands are getting visible.
In the (telnet) VTY session, this mode can be activated by passing
an additional argument to well-known 'enable' command:
OsmoApp> enable ?
[expert-mode] Enable the expert mode (show hidden commands)
OsmoApp> enable expert-mode
OsmoApp#
so then hidden commands will appear together with all the other
commands. They will be marked with a special '^' flag:
OsmoApp# list with-flags
^ ... foo-hidden [expert-mode]
. ... foo-regular-one
! ... foo-immediate
^ u.. app-hidden-unbelievable
For the XML reference generation, additional API needs to be
introduced. This will be implemented in subsequent patches.
Change-Id: Ie69c2a19b22fb31d7bd7f6412f0aeac86ea5048f
Related: SYS#4910
-rw-r--r-- | include/osmocom/vty/command.h | 4 | ||||
-rw-r--r-- | include/osmocom/vty/vty.h | 2 | ||||
-rw-r--r-- | src/vty/command.c | 45 | ||||
-rw-r--r-- | tests/vty/vty_transcript_test.c | 29 | ||||
-rw-r--r-- | tests/vty/vty_transcript_test.vty | 59 |
5 files changed, 126 insertions, 13 deletions
diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h index 2cb45dd3..92701fcb 100644 --- a/include/osmocom/vty/command.h +++ b/include/osmocom/vty/command.h @@ -24,6 +24,7 @@ #pragma once #include <stdio.h> +#include <stdbool.h> #include <sys/types.h> #include "vector.h" @@ -65,6 +66,9 @@ struct host { /*! VTY application information */ const struct vty_app_info *app_info; + + /*! Whether the expert mode is enabled. */ + bool expert_mode; }; /*! There are some command levels which called from command node. */ diff --git a/include/osmocom/vty/vty.h b/include/osmocom/vty/vty.h index 4e83b1bb..6a82d7e3 100644 --- a/include/osmocom/vty/vty.h +++ b/include/osmocom/vty/vty.h @@ -32,7 +32,7 @@ #define VTY_CMD_USR_ATTR_NUM 32 /* Flag characters reserved for global VTY attributes */ #define VTY_CMD_ATTR_FLAGS_RESERVED \ - { '.', '!', '@' } + { '.', '!', '@', '^' } /*! VTY events */ enum event { diff --git a/src/vty/command.c b/src/vty/command.c index d8649f58..0edfce5a 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -624,7 +624,7 @@ typedef int (*print_func_t)(void *data, const char *fmt, ...); static const struct value_string cmd_attr_desc[] = { { CMD_ATTR_DEPRECATED, "This command is deprecated" }, - { CMD_ATTR_HIDDEN, "This command is hidden" }, + { CMD_ATTR_HIDDEN, "This command is hidden (check expert mode)" }, { CMD_ATTR_IMMEDIATE, "This command applies immediately" }, { CMD_ATTR_NODE_EXIT, "This command applies on VTY node exit" }, /* CMD_ATTR_LIB_COMMAND is intentionally skipped */ @@ -639,6 +639,8 @@ static const struct value_string cmd_attr_desc[] = { static char cmd_attr_get_flag(unsigned int attr) { switch (attr) { + case CMD_ATTR_HIDDEN: + return '^'; case CMD_ATTR_IMMEDIATE: return '!'; case CMD_ATTR_NODE_EXIT: @@ -796,8 +798,11 @@ static int vty_dump_nodes(print_func_t print_func, void *data, const char *newli elem = vector_slot(cnode->cmd_vector, j); if (!vty_command_is_common(elem)) continue; - if (!(elem->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN))) - vty_dump_element(elem, print_func, data, newline); + if (elem->attr & CMD_ATTR_DEPRECATED) + continue; + if (!host.expert_mode && (elem->attr & CMD_ATTR_HIDDEN)) + continue; + vty_dump_element(elem, print_func, data, newline); } } print_func(data, " </node>%s", newline); @@ -834,8 +839,11 @@ static int vty_dump_nodes(print_func_t print_func, void *data, const char *newli elem = vector_slot(cnode->cmd_vector, j); if (vty_command_is_common(elem)) continue; - if (!(elem->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN))) - vty_dump_element(elem, print_func, data, newline); + if (elem->attr & CMD_ATTR_DEPRECATED) + continue; + if (!host.expert_mode && (elem->attr & CMD_ATTR_HIDDEN)) + continue; + vty_dump_element(elem, print_func, data, newline); } print_func(data, " </node>%s", newline); @@ -2007,7 +2015,9 @@ cmd_describe_command_real(vector vline, struct vty *vty, int *status) if (!cmd_element) continue; - if (cmd_element->attr & (CMD_ATTR_DEPRECATED|CMD_ATTR_HIDDEN)) + if (cmd_element->attr & CMD_ATTR_DEPRECATED) + continue; + if (!host.expert_mode && (cmd_element->attr & CMD_ATTR_HIDDEN)) continue; strvec = cmd_element->strvec; @@ -2867,7 +2877,10 @@ DEFUN(config_terminal, } /* Enable command */ -DEFUN(enable, config_enable_cmd, "enable", "Turn on privileged mode command\n") +DEFUN(enable, config_enable_cmd, + "enable [expert-mode]", + "Turn on privileged mode command\n" + "Enable the expert mode (show hidden commands)\n") { /* If enable password is NULL, change to ENABLE_NODE */ if ((host.enable == NULL && host.enable_encrypt == NULL) || @@ -2876,6 +2889,8 @@ DEFUN(enable, config_enable_cmd, "enable", "Turn on privileged mode command\n") else vty->node = AUTH_ENABLE_NODE; + host.expert_mode = argc > 0; + return CMD_SUCCESS; } @@ -2885,6 +2900,9 @@ DEFUN(disable, { if (vty->node == ENABLE_NODE) vty->node = VIEW_NODE; + + host.expert_mode = false; + return CMD_SUCCESS; } @@ -3083,7 +3101,9 @@ static unsigned int node_flag_mask(const struct cmd_node *cnode) if ((cmd = vector_slot(cnode->cmd_vector, i)) == NULL) continue; - if (cmd->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN)) + if (cmd->attr & CMD_ATTR_DEPRECATED) + continue; + if (!host.expert_mode && (cmd->attr & CMD_ATTR_HIDDEN)) continue; if (~cmd->usrattr & ((unsigned)1 << f)) continue; @@ -3111,7 +3131,9 @@ static const char *cmd_gflag_mask(const struct cmd_element *cmd) char *ptr = &char_mask[0]; /* Mutually exclusive global attributes */ - if (cmd->attr & CMD_ATTR_IMMEDIATE) + if (cmd->attr & CMD_ATTR_HIDDEN) + *(ptr++) = cmd_attr_get_flag(CMD_ATTR_HIDDEN); + else if (cmd->attr & CMD_ATTR_IMMEDIATE) *(ptr++) = cmd_attr_get_flag(CMD_ATTR_IMMEDIATE); else if (cmd->attr & CMD_ATTR_NODE_EXIT) *(ptr++) = cmd_attr_get_flag(CMD_ATTR_NODE_EXIT); @@ -3170,7 +3192,9 @@ gDEFUN(config_list, config_list_cmd, for (i = 0; i < vector_active(cnode->cmd_vector); i++) { if ((cmd = vector_slot(cnode->cmd_vector, i)) == NULL) continue; - if (cmd->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN)) + if (cmd->attr & CMD_ATTR_DEPRECATED) + continue; + if (!host.expert_mode && (cmd->attr & CMD_ATTR_HIDDEN)) continue; if (!argc) vty_out(vty, " %s%s", cmd->string, VTY_NEWLINE); @@ -4244,6 +4268,7 @@ void cmd_init(int terminal) host.lines = -1; host.motd = default_motd; host.motdfile = NULL; + host.expert_mode = false; /* Install top nodes. */ install_node_bare(&view_node, NULL); diff --git a/tests/vty/vty_transcript_test.c b/tests/vty/vty_transcript_test.c index abe37027..c9ecf186 100644 --- a/tests/vty/vty_transcript_test.c +++ b/tests/vty/vty_transcript_test.c @@ -232,6 +232,23 @@ DEFUN(cfg_attr_test, cfg_attr_test_cmd, return CMD_SUCCESS; } +DEFUN_DEPRECATED(cfg_attr_deprecated, + cfg_attr_deprecated_cmd, + "foo-deprecated", + "This command is deprecated\n") +{ + return CMD_WARNING; +} + +DEFUN_HIDDEN(cfg_attr_hidden, + cfg_attr_hidden_cmd, + "foo-hidden [expert-mode]", + "This command is hidden\n" + "But can be seen in the expert mode\n") +{ + return CMD_SUCCESS; +} + DEFUN_ATTR(cfg_attr_immediate, cfg_attr_immediate_cmd, "foo-immediate", "Applies immediately\n", @@ -293,6 +310,15 @@ DEFUN_USRATTR(cfg_app_attr_unbelievable_wonderful, return CMD_SUCCESS; } +DEFUN_ATTR_USRATTR(cfg_attr_hidden_app_attr_unbelievable, + cfg_attr_hidden_app_attr_unbelievable_cmd, + CMD_ATTR_HIDDEN, X(TEST_ATTR_UNBELIEVABLE), + "app-hidden-unbelievable", + "Hidden, but still unbelievable help message\n") +{ + return CMD_SUCCESS; +} + static void init_vty_cmds() { install_element_ve(&single0_cmd); @@ -302,6 +328,8 @@ static void init_vty_cmds() install_element(CONFIG_NODE, &cfg_attr_test_cmd); install_node(&attr_test_node, NULL); + install_element(ATTR_TEST_NODE, &cfg_attr_deprecated_cmd); + install_element(ATTR_TEST_NODE, &cfg_attr_hidden_cmd); install_element(ATTR_TEST_NODE, &cfg_attr_immediate_cmd); install_element(ATTR_TEST_NODE, &cfg_attr_node_exit_cmd); @@ -311,6 +339,7 @@ static void init_vty_cmds() install_element(ATTR_TEST_NODE, &cfg_app_attr_unbelievable_magnificent_cmd); install_element(ATTR_TEST_NODE, &cfg_app_attr_unbelievable_wonderful_cmd); + install_element(ATTR_TEST_NODE, &cfg_attr_hidden_app_attr_unbelievable_cmd); } int main(int argc, char **argv) diff --git a/tests/vty/vty_transcript_test.vty b/tests/vty/vty_transcript_test.vty index 2c618d89..7b8241eb 100644 --- a/tests/vty/vty_transcript_test.vty +++ b/tests/vty/vty_transcript_test.vty @@ -87,6 +87,7 @@ ok argc=0 vty_transcript_test> show vty-attributes Global attributes: + ^ This command is hidden (check expert mode) ! This command applies immediately @ This command applies on VTY node exit Library specific attributes: @@ -104,7 +105,7 @@ vty_transcript_test# configure terminal vty_transcript_test(config)# attribute-test vty_transcript_test(config-attr-test)# list -... +... !foo-(hidden|deprecated) foo-immediate foo-node-exit app-unbelievable @@ -112,9 +113,53 @@ vty_transcript_test(config-attr-test)# list app-wonderful app-unbelievable-magnificent app-unbelievable-wonderful +... !app-hidden-* vty_transcript_test(config-attr-test)# list with-flags -... +... !foo-(hidden|deprecated) + ! ... foo-immediate + @ ... foo-node-exit + . u.. app-unbelievable + . .m. app-magnificent + . ..w app-wonderful + . um. app-unbelievable-magnificent + . u.w app-unbelievable-wonderful +... !app-hidden-* + +vty_transcript_test(config-attr-test)# foo-deprecated? +% There is no matched command. +vty_transcript_test(config-attr-test)# foo-hidden? +% There is no matched command. +vty_transcript_test(config-attr-test)# app-hidden-unbelievable? +% There is no matched command. + +vty_transcript_test(config-attr-test)# end +vty_transcript_test# disable + +vty_transcript_test> enable? + enable Turn on privileged mode command +vty_transcript_test> enable ? + [expert-mode] Enable the expert mode (show hidden commands) + +vty_transcript_test> enable expert-mode +vty_transcript_test# configure terminal +vty_transcript_test(config)# attribute-test + +vty_transcript_test(config-attr-test)# list +... !foo-deprected + foo-hidden [expert-mode] + foo-immediate + foo-node-exit + app-unbelievable + app-magnificent + app-wonderful + app-unbelievable-magnificent + app-unbelievable-wonderful + app-hidden-unbelievable + +vty_transcript_test(config-attr-test)# list with-flags +... !foo-deprected + ^ ... foo-hidden [expert-mode] ! ... foo-immediate @ ... foo-node-exit . u.. app-unbelievable @@ -122,3 +167,13 @@ vty_transcript_test(config-attr-test)# list with-flags . ..w app-wonderful . um. app-unbelievable-magnificent . u.w app-unbelievable-wonderful + ^ u.. app-hidden-unbelievable + +vty_transcript_test(config-attr-test)# foo-deprecated? +% There is no matched command. +vty_transcript_test(config-attr-test)# foo-hidden? + foo-hidden This command is hidden +vty_transcript_test(config-attr-test)# foo-hidden ? + [expert-mode] But can be seen in the expert mode +vty_transcript_test(config-attr-test)# app-hidden-unbelievable? + app-hidden-unbelievable Hidden, but still unbelievable help message |