summaryrefslogtreecommitdiff
path: root/lib/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/command.c')
-rw-r--r--lib/command.c95
1 files changed, 61 insertions, 34 deletions
diff --git a/lib/command.c b/lib/command.c
index 97ea200ff4..0288ab7599 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -10,6 +10,10 @@
*/
#include <zebra.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include <lib/version.h>
#include "command.h"
@@ -31,12 +35,16 @@
#include "jhash.h"
#include "hook.h"
#include "lib_errors.h"
+#include "mgmt_be_client.h"
+#include "mgmt_fe_client.h"
#include "northbound_cli.h"
#include "network.h"
#include "routemap.h"
#include "frrscript.h"
+#include "lib/config_paths.h"
+
DEFINE_MTYPE_STATIC(LIB, HOST, "Host config");
DEFINE_MTYPE(LIB, COMPLETION, "Completion item");
@@ -475,33 +483,18 @@ 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
+ else if (cputime_threshold != CONSUMED_TIME_CHECK)
vty_out(vty, "service cputime-warning %lu\n",
cputime_threshold / 1000);
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
+ else if (walltime_threshold != CONSUMED_TIME_CHECK)
vty_out(vty, "service walltime-warning %lu\n",
walltime_threshold / 1000);
@@ -685,6 +678,21 @@ vector cmd_describe_command(vector vline, struct vty *vty, int *status)
static struct list *varhandlers = NULL;
+static int __add_key_comp(const struct lyd_node *dnode, void *arg)
+{
+ const char *key_value = yang_dnode_get_string(dnode, NULL);
+
+ vector_set((vector)arg, XSTRDUP(MTYPE_COMPLETION, key_value));
+
+ return YANG_ITER_CONTINUE;
+}
+
+static void __get_list_keys(vector comps, const char *xpath)
+{
+ yang_dnode_iterate(__add_key_comp, comps,
+ vty_shared_candidate_config->dnode, "%s", xpath);
+}
+
void cmd_variable_complete(struct cmd_token *token, const char *arg,
vector comps)
{
@@ -701,7 +709,10 @@ void cmd_variable_complete(struct cmd_token *token, const char *arg,
if (cvh->varname && (!token->varname
|| strcmp(cvh->varname, token->varname)))
continue;
- cvh->completions(tmpcomps, token);
+ if (cvh->xpath)
+ __get_list_keys(tmpcomps, cvh->xpath);
+ if (cvh->completions)
+ cvh->completions(tmpcomps, token);
break;
}
@@ -733,9 +744,13 @@ char *cmd_variable_comp2str(vector comps, unsigned short cols)
char *item = vector_slot(comps, j);
itemlen = strlen(item);
- if (cs + itemlen + AUTOCOMP_INDENT + 3 >= bsz)
- buf = XREALLOC(MTYPE_TMP, buf, (bsz *= 2));
+ size_t next_sz = cs + itemlen + AUTOCOMP_INDENT + 3;
+ if (next_sz > bsz) {
+ /* Make sure the buf size is large enough */
+ bsz = next_sz;
+ buf = XREALLOC(MTYPE_TMP, buf, bsz);
+ }
if (lc + itemlen + 1 >= cols) {
cs += snprintf(&buf[cs], bsz - cs, "\n%*s",
AUTOCOMP_INDENT, "");
@@ -756,7 +771,7 @@ void cmd_variable_handler_register(const struct cmd_variable_handler *cvh)
if (!varhandlers)
return;
- for (; cvh->completions; cvh++)
+ for (; cvh->completions || cvh->xpath; cvh++)
listnode_add(varhandlers, (void *)cvh);
}
@@ -897,8 +912,7 @@ enum node_type node_parent(enum node_type node)
}
/* Execute command by argument vline vector. */
-static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
- struct vty *vty,
+static int cmd_execute_command_real(vector vline, struct vty *vty,
const struct cmd_element **cmd,
unsigned int up_level)
{
@@ -1035,8 +1049,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
vector_set_index(shifted_vline, index - 1,
vector_lookup(vline, index));
- ret = cmd_execute_command_real(shifted_vline, FILTER_RELAXED,
- vty, cmd, 0);
+ ret = cmd_execute_command_real(shifted_vline, vty, cmd, 0);
vector_free(shifted_vline);
vty->node = onode;
@@ -1045,7 +1058,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
}
saved_ret = ret =
- cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd, 0);
+ cmd_execute_command_real(vline, vty, cmd, 0);
if (vtysh)
return saved_ret;
@@ -1063,8 +1076,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
if (vty->xpath_index > 0 && !cnode->no_xpath)
vty->xpath_index--;
- ret = cmd_execute_command_real(vline, FILTER_RELAXED,
- vty, cmd, 0);
+ ret = cmd_execute_command_real(vline, vty, cmd, 0);
if (ret == CMD_SUCCESS || ret == CMD_WARNING
|| ret == CMD_ERR_AMBIGUOUS || ret == CMD_ERR_INCOMPLETE
|| ret == CMD_NOT_MY_INSTANCE
@@ -1096,7 +1108,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
int cmd_execute_command_strict(vector vline, struct vty *vty,
const struct cmd_element **cmd)
{
- return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd, 0);
+ return cmd_execute_command_real(vline, vty, cmd, 0);
}
/*
@@ -1268,8 +1280,7 @@ int command_config_read_one_line(struct vty *vty,
&& 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,
- ++up_level);
+ ret = cmd_execute_command_real(vline, vty, cmd, ++up_level);
if (ret == CMD_NO_LEVEL_UP)
ret = CMD_ERR_NO_MATCH;
@@ -1281,6 +1292,7 @@ int command_config_read_one_line(struct vty *vty,
memcpy(ve->error_buf, vty->buf, VTY_BUFSIZ);
ve->line_num = line_num;
+ ve->cmd_ret = ret;
if (!vty->error)
vty->error = list_new();
@@ -1301,6 +1313,14 @@ int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num)
while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
++(*line_num);
+ if (vty_log_commands) {
+ int len = strlen(vty->buf);
+
+ /* now log the command */
+ zlog_notice("config-from-file# %.*s", len ? len - 1 : 0,
+ vty->buf);
+ }
+
ret = command_config_read_one_line(vty, NULL, *line_num, 0);
if (ret != CMD_SUCCESS && ret != CMD_WARNING
@@ -1318,11 +1338,12 @@ int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num)
/* Configuration from terminal */
DEFUN (config_terminal,
config_terminal_cmd,
- "configure [terminal]",
+ "configure [terminal [file-lock]]",
"Configuration from vty interface\n"
- "Configuration terminal\n")
+ "Configuration terminal\n"
+ "Configuration with locked datastores\n")
{
- return vty_config_enter(vty, false, false);
+ return vty_config_enter(vty, false, false, argc == 3);
}
/* Enable command */
@@ -1632,6 +1653,10 @@ static int vty_write_config(struct vty *vty)
return CMD_SUCCESS;
}
+/* cross-reference frr_daemon_state_save in libfrr.c
+ * the code there is similar but not identical (state files always use the same
+ * name for the new write, and don't keep a backup of previous state.)
+ */
static int file_write_config(struct vty *vty)
{
int fd, dirfd;
@@ -2438,6 +2463,8 @@ const char *host_config_get(void)
void cmd_show_lib_debugs(struct vty *vty)
{
route_map_show_debug(vty);
+ mgmt_debug_be_client_show_debug(vty);
+ mgmt_debug_fe_client_show_debug(vty);
}
void install_default(enum node_type node)