summaryrefslogtreecommitdiff
path: root/lib/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/command.c')
-rw-r--r--lib/command.c164
1 files changed, 138 insertions, 26 deletions
diff --git a/lib/command.c b/lib/command.c
index 7fb405bdfb..422544b70b 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -160,6 +160,9 @@ static bool vty_check_node_for_xpath_decrement(enum node_type target_node,
|| node == BGP_FLOWSPECV6_NODE))
return false;
+ if (target_node == INTERFACE_NODE && node == LINK_PARAMS_NODE)
+ return false;
+
return true;
}
@@ -255,6 +258,9 @@ static bool cmd_hash_cmp(const void *a, const void *b)
/* Install top node of command vector. */
void install_node(struct cmd_node *node)
{
+#define CMD_HASH_STR_SIZE 256
+ char hash_name[CMD_HASH_STR_SIZE];
+
vector_set_index(cmdvec, node->node, node);
node->cmdgraph = graph_new();
node->cmd_vector = vector_init(VECTOR_MIN_SIZE);
@@ -263,8 +269,10 @@ void install_node(struct cmd_node *node)
cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
graph_new_node(node->cmdgraph, token,
(void (*)(void *)) & cmd_token_del);
- node->cmd_hash = hash_create_size(16, cmd_hash_key, cmd_hash_cmp,
- "Command Hash");
+
+ snprintf(hash_name, sizeof(hash_name), "Command Hash: %s", node->name);
+ node->cmd_hash =
+ hash_create_size(16, cmd_hash_key, cmd_hash_cmp, hash_name);
}
/* Return prompt character of specified node. */
@@ -434,6 +442,36 @@ static int config_write_host(struct vty *vty)
}
log_config_write(vty);
+ /* print disable always, but enable only if default is flipped
+ * => prep for future removal of compile-time knob
+ */
+ if (!cputime_enabled)
+ vty_out(vty, "no service cputime-stats\n");
+#ifdef EXCLUDE_CPU_TIME
+ else
+ vty_out(vty, "service cputime-stats\n");
+#endif
+
+ if (!cputime_threshold)
+ vty_out(vty, "no service cputime-warning\n");
+#if defined(CONSUMED_TIME_CHECK) && CONSUMED_TIME_CHECK != 5000000
+ else /* again, always print non-default */
+#else
+ else if (cputime_threshold != 5000000)
+#endif
+ vty_out(vty, "service cputime-warning %lu\n",
+ cputime_threshold);
+
+ if (!walltime_threshold)
+ vty_out(vty, "no service walltime-warning\n");
+#if defined(CONSUMED_TIME_CHECK) && CONSUMED_TIME_CHECK != 5000000
+ else /* again, always print non-default */
+#else
+ else if (walltime_threshold != 5000000)
+#endif
+ vty_out(vty, "service walltime-warning %lu\n",
+ walltime_threshold);
+
if (host.advanced)
vty_out(vty, "service advanced-vty\n");
@@ -889,6 +927,15 @@ enum node_type node_parent(enum node_type node)
case PCEP_PCC_NODE:
ret = PCEP_NODE;
break;
+ case SRV6_NODE:
+ ret = SEGMENT_ROUTING_NODE;
+ break;
+ case SRV6_LOCS_NODE:
+ ret = SRV6_NODE;
+ break;
+ case SRV6_LOC_NODE:
+ ret = SRV6_LOCS_NODE;
+ break;
default:
ret = CONFIG_NODE;
break;
@@ -980,7 +1027,7 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
* non-YANG command.
*/
if (matched_element->attr != CMD_ATTR_YANG)
- nb_cli_pending_commit_check(vty);
+ (void)nb_cli_pending_commit_check(vty);
}
ret = matched_element->func(matched_element, vty, argc, argv);
@@ -1049,6 +1096,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
return saved_ret;
if (ret != CMD_SUCCESS && ret != CMD_WARNING
+ && ret != CMD_ERR_AMBIGUOUS && ret != CMD_ERR_INCOMPLETE
&& ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED) {
/* This assumes all nodes above CONFIG_NODE are childs of
* CONFIG_NODE */
@@ -1062,6 +1110,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
ret = cmd_execute_command_real(vline, FILTER_RELAXED,
vty, cmd, 0);
if (ret == CMD_SUCCESS || ret == CMD_WARNING
+ || ret == CMD_ERR_AMBIGUOUS || ret == CMD_ERR_INCOMPLETE
|| ret == CMD_NOT_MY_INSTANCE
|| ret == CMD_WARNING_CONFIG_FAILED)
return ret;
@@ -1260,6 +1309,7 @@ int command_config_read_one_line(struct vty *vty,
while (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING
+ && ret != CMD_ERR_AMBIGUOUS && ret != CMD_ERR_INCOMPLETE
&& ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
&& ret != CMD_NO_LEVEL_UP)
ret = cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd,
@@ -1484,6 +1534,56 @@ static void permute(struct graph_node *start, struct vty *vty)
list_delete_node(position, listtail(position));
}
+static void print_cmd(struct vty *vty, const char *cmd)
+{
+ int i, j, len = strlen(cmd);
+ char buf[len + 1];
+ bool skip = false;
+
+ j = 0;
+ for (i = 0; i < len; i++) {
+ /* skip varname */
+ if (cmd[i] == '$')
+ skip = true;
+ else if (strchr(" ()<>[]{}|", cmd[i]))
+ skip = false;
+
+ if (skip)
+ continue;
+
+ if (isspace(cmd[i])) {
+ /* skip leading whitespace */
+ if (i == 0)
+ continue;
+ /* skip trailing whitespace */
+ if (i == len - 1)
+ continue;
+ /* skip all whitespace after opening brackets or pipe */
+ if (strchr("(<[{|", cmd[i - 1])) {
+ while (isspace(cmd[i + 1]))
+ i++;
+ continue;
+ }
+ /* skip repeated whitespace */
+ if (isspace(cmd[i + 1]))
+ continue;
+ /* skip whitespace before closing brackets or pipe */
+ if (strchr(")>]}|", cmd[i + 1]))
+ continue;
+ /* convert tabs to spaces */
+ if (cmd[i] == '\t') {
+ buf[j++] = ' ';
+ continue;
+ }
+ }
+
+ buf[j++] = cmd[i];
+ }
+ buf[j] = 0;
+
+ vty_out(vty, "%s\n", buf);
+}
+
int cmd_list_cmds(struct vty *vty, int do_permute)
{
struct cmd_node *node = vector_slot(cmdvec, vty->node);
@@ -1497,8 +1597,10 @@ int cmd_list_cmds(struct vty *vty, int do_permute)
i++)
if ((element = vector_slot(node->cmd_vector, i))
&& element->attr != CMD_ATTR_DEPRECATED
- && element->attr != CMD_ATTR_HIDDEN)
- vty_out(vty, " %s\n", element->string);
+ && element->attr != CMD_ATTR_HIDDEN) {
+ vty_out(vty, " ");
+ print_cmd(vty, element->string);
+ }
}
return CMD_SUCCESS;
}
@@ -2231,11 +2333,7 @@ DEFUN (no_banner_motd,
return CMD_SUCCESS;
}
-DEFUN(find,
- find_cmd,
- "find REGEX...",
- "Find CLI command matching a regular expression\n"
- "Search pattern (POSIX regex)\n")
+int cmd_find_cmds(struct vty *vty, struct cmd_token **argv, int argc)
{
const struct cmd_node *node;
const struct cmd_element *cli;
@@ -2302,9 +2400,10 @@ DEFUN(find,
for (unsigned int j = 0; j < vector_active(clis); j++) {
cli = vector_slot(clis, j);
- if (regexec(&exp, cli->string, 0, NULL, 0) == 0)
- vty_out(vty, " (%s) %s\n",
- node->name, cli->string);
+ if (regexec(&exp, cli->string, 0, NULL, 0) == 0) {
+ vty_out(vty, " (%s) ", node->name);
+ print_cmd(vty, cli->string);
+ }
}
}
@@ -2313,27 +2412,40 @@ done:
return CMD_SUCCESS;
}
+DEFUN(find,
+ find_cmd,
+ "find REGEX...",
+ "Find CLI command matching a regular expression\n"
+ "Search pattern (POSIX regex)\n")
+{
+ return cmd_find_cmds(vty, argv, argc);
+}
+
#if defined(DEV_BUILD) && defined(HAVE_SCRIPTING)
-DEFUN(script,
- script_cmd,
- "script SCRIPT",
- "Test command - execute a script\n"
- "Script name (same as filename in /etc/frr/scripts/\n")
+DEFUN(script, script_cmd, "script SCRIPT FUNCTION",
+ "Test command - execute a function in a script\n"
+ "Script name (same as filename in /etc/frr/scripts/)\n"
+ "Function name (in the script)\n")
{
struct prefix p;
(void)str2prefix("1.2.3.4/24", &p);
+ struct frrscript *fs = frrscript_new(argv[1]->arg);
- struct frrscript *fs = frrscript_load(argv[1]->arg, NULL);
-
- if (fs == NULL) {
- vty_out(vty, "Script '/etc/frr/scripts/%s.lua' not found\n",
- argv[1]->arg);
- } else {
- int ret = frrscript_call(fs, NULL);
- vty_out(vty, "Script result: %d\n", ret);
+ if (frrscript_load(fs, argv[2]->arg, NULL)) {
+ vty_out(vty,
+ "/etc/frr/scripts/%s.lua or function '%s' not found\n",
+ argv[1]->arg, argv[2]->arg);
}
+ int ret = frrscript_call(fs, argv[2]->arg, ("p", &p));
+ char buf[40];
+ prefix2str(&p, buf, sizeof(buf));
+ vty_out(vty, "p: %s\n", buf);
+ vty_out(vty, "Script result: %d\n", ret);
+
+ frrscript_delete(fs);
+
return CMD_SUCCESS;
}
#endif