aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2020-10-21 05:07:34 +0700
committerVadim Yanitskiy <vyanitskiy@sysmocom.de>2020-10-21 06:27:48 +0700
commit72b90883f9913a29581589cb5954e0f02ca63778 (patch)
tree1c9e9a6a618c1d0ed74be6be122e3d71746df4dc
parente7bf4354b9914aa41bd5b7e1fa95095bb77ba4c4 (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.h4
-rw-r--r--include/osmocom/vty/vty.h2
-rw-r--r--src/vty/command.c45
-rw-r--r--tests/vty/vty_transcript_test.c29
-rw-r--r--tests/vty/vty_transcript_test.vty59
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