#include "jhash.h"
#include "hook.h"
#include "lib_errors.h"
+#include "northbound_cli.h"
DEFINE_MTYPE(LIB, HOST, "Host config")
DEFINE_MTYPE(LIB, COMPLETION, "Completion item")
"config", // CONFIG_NODE,
"debug", // DEBUG_NODE,
"vrf debug", // VRF_DEBUG_NODE,
+ "northbound debug", // NORTHBOUND_DEBUG_NODE,
"vnc debug", // DEBUG_VNC_NODE,
"aaa", // AAA_NODE,
"keychain", // KEYCHAIN_NODE,
return jhash(p, size, 0);
}
-static int cmd_hash_cmp(const void *a, const void *b)
+static bool cmd_hash_cmp(const void *a, const void *b)
{
return a == b;
}
*/
static int compare_completions(const void *fst, const void *snd)
{
- struct cmd_token *first = *(struct cmd_token **)fst,
- *secnd = *(struct cmd_token **)snd;
+ const struct cmd_token *first = *(const struct cmd_token * const *)fst,
+ *secnd = *(const struct cmd_token * const *)snd;
return strcmp(first->text, secnd->text);
}
}
vector comps = completions_to_vec(completions);
- list_delete_and_null(&completions);
+ list_delete(&completions);
// set status code appropriately
switch (vector_active(comps)) {
if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
enum node_type onode;
+ int orig_xpath_index;
vector shifted_vline;
unsigned int index;
onode = vty->node;
+ orig_xpath_index = vty->xpath_index;
vty->node = ENABLE_NODE;
+ vty->xpath_index = 0;
/* We can try it on enable node, cos' the vty is authenticated
*/
vector_free(shifted_vline);
vty->node = onode;
+ vty->xpath_index = orig_xpath_index;
return ret;
}
// if matcher error, return corresponding CMD_ERR
if (MATCHER_ERROR(status)) {
if (argv_list)
- list_delete_and_null(&argv_list);
+ list_delete(&argv_list);
switch (status) {
case MATCHER_INCOMPLETE:
return CMD_ERR_INCOMPLETE;
int ret;
if (matched_element->daemon)
ret = CMD_SUCCESS_DAEMON;
- else
+ else {
+ /* Clear enqueued configuration changes. */
+ vty->num_cfg_changes = 0;
+ memset(&vty->cfg_changes, 0, sizeof(vty->cfg_changes));
+
ret = matched_element->func(matched_element, vty, argc, argv);
+ }
// delete list and cmd_token's in it
- list_delete_and_null(&argv_list);
+ list_delete(&argv_list);
XFREE(MTYPE_TMP, argv);
return ret;
{
int ret, saved_ret = 0;
enum node_type onode, try_node;
+ int orig_xpath_index;
onode = try_node = vty->node;
+ orig_xpath_index = vty->xpath_index;
if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
vector shifted_vline;
unsigned int index;
vty->node = ENABLE_NODE;
+ vty->xpath_index = 0;
/* We can try it on enable node, cos' the vty is authenticated
*/
vector_free(shifted_vline);
vty->node = onode;
+ vty->xpath_index = orig_xpath_index;
return ret;
}
while (vty->node > CONFIG_NODE) {
try_node = node_parent(try_node);
vty->node = try_node;
+ if (vty->xpath_index > 0)
+ vty->xpath_index--;
ret = cmd_execute_command_real(vline, FILTER_RELAXED,
vty, cmd);
if (ret == CMD_SUCCESS || ret == CMD_WARNING
}
/* no command succeeded, reset the vty to the original node */
vty->node = onode;
+ vty->xpath_index = orig_xpath_index;
}
/* return command status for original node */
* as to why no command could be executed.
*/
int command_config_read_one_line(struct vty *vty,
- const struct cmd_element **cmd, int use_daemon)
+ const struct cmd_element **cmd,
+ uint32_t line_num, int use_daemon)
{
vector vline;
- int saved_node;
int ret;
vline = cmd_make_strvec(vty->buf);
&& ret != CMD_SUCCESS && ret != CMD_WARNING
&& ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
&& vty->node != CONFIG_NODE) {
-
- saved_node = vty->node;
+ int saved_node = vty->node;
+ int saved_xpath_index = vty->xpath_index;
while (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING
&& vty->node > CONFIG_NODE) {
vty->node = node_parent(vty->node);
+ if (vty->xpath_index > 0)
+ vty->xpath_index--;
ret = cmd_execute_command_strict(vline, vty, cmd);
}
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING) {
vty->node = saved_node;
+ vty->xpath_index = saved_xpath_index;
}
}
- if (ret != CMD_SUCCESS && ret != CMD_WARNING)
- memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ);
+ if (ret != CMD_SUCCESS &&
+ ret != CMD_WARNING &&
+ ret != CMD_SUCCESS_DAEMON) {
+ struct vty_error *ve = XCALLOC(MTYPE_TMP, sizeof(*ve));
+
+ memcpy(ve->error_buf, vty->buf, VTY_BUFSIZ);
+ ve->line_num = line_num;
+ if (!vty->error)
+ vty->error = list_new();
+
+ listnode_add(vty->error, ve);
+ }
cmd_free_strvec(vline);
*line_num = 0;
while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
- if (!error_ret)
- ++(*line_num);
+ ++(*line_num);
- ret = command_config_read_one_line(vty, NULL, 0);
+ ret = command_config_read_one_line(vty, NULL, *line_num, 0);
if (ret != CMD_SUCCESS && ret != CMD_WARNING
&& ret != CMD_ERR_NOTHING_TODO)
"Configuration from vty interface\n"
"Configuration terminal\n")
{
- if (vty_config_lock(vty))
- vty->node = CONFIG_NODE;
- else {
- vty_out(vty, "VTY configuration is locked by other VTY\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- return CMD_SUCCESS;
+ return vty_config_enter(vty, false, false);
}
/* Enable command */
break;
case CONFIG_NODE:
vty->node = ENABLE_NODE;
- vty_config_unlock(vty);
+ vty_config_exit(vty);
break;
case INTERFACE_NODE:
case PW_NODE:
default:
break;
}
+
+ if (vty->xpath_index > 0)
+ vty->xpath_index--;
}
/* ALIAS_FIXME */
case LINK_PARAMS_NODE:
case BFD_NODE:
case BFD_PEER_NODE:
- vty_config_unlock(vty);
+ vty_config_exit(vty);
vty->node = ENABLE_NODE;
break;
default:
break;
}
+
+ vty->xpath_index = 0;
+
return CMD_SUCCESS;
}
install_element(node, &show_running_config_cmd);
install_element(node, &autocomplete_cmd);
+
+ nb_cli_install_default(node);
}
/* Initialize command interface. Install basic nodes and commands.
if (host.config)
XFREE(MTYPE_HOST, host.config);
- list_delete_and_null(&varhandlers);
+ list_delete(&varhandlers);
qobj_finish();
}