diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command.c | 36 | ||||
| -rw-r--r-- | lib/command.h | 5 | ||||
| -rw-r--r-- | lib/vty.c | 19 | ||||
| -rw-r--r-- | lib/vty.h | 1 |
4 files changed, 37 insertions, 24 deletions
diff --git a/lib/command.c b/lib/command.c index 8ec93c1b33..d51922dfa1 100644 --- a/lib/command.c +++ b/lib/command.c @@ -99,6 +99,8 @@ const char *cmd_domainname_get(void) return host.domainname; } +static int root_on_exit(struct vty *vty); + /* Standard command node structures. */ static struct cmd_node auth_node = { .name = "auth", @@ -110,6 +112,7 @@ static struct cmd_node view_node = { .name = "view", .node = VIEW_NODE, .prompt = "%s> ", + .node_exit = root_on_exit, }; static struct cmd_node auth_enable_node = { @@ -122,6 +125,7 @@ static struct cmd_node enable_node = { .name = "enable", .node = ENABLE_NODE, .prompt = "%s# ", + .node_exit = root_on_exit, }; static int config_write_host(struct vty *vty); @@ -131,6 +135,7 @@ static struct cmd_node config_node = { .parent_node = ENABLE_NODE, .prompt = "%s(config)# ", .config_write = config_write_host, + .node_exit = vty_config_node_exit, }; static const struct facility_map { @@ -1382,28 +1387,25 @@ DEFUN (config_exit, return CMD_SUCCESS; } +static int root_on_exit(struct vty *vty) +{ + if (vty_shell(vty)) + exit(0); + else + vty->status = VTY_CLOSE; + return 0; +} + void cmd_exit(struct vty *vty) { struct cmd_node *cnode = vector_lookup(cmdvec, vty->node); - switch (vty->node) { - case VIEW_NODE: - case ENABLE_NODE: - if (vty_shell(vty)) - exit(0); - else - vty->status = VTY_CLOSE; - break; - case CONFIG_NODE: - vty->node = ENABLE_NODE; - vty_config_exit(vty); - break; - default: - if (cnode->parent_node) - vty->node = cnode->parent_node; - break; + if (cnode->node_exit) { + if (!cnode->node_exit(vty)) + return; } - + if (cnode->parent_node) + vty->node = cnode->parent_node; if (vty->xpath_index > 0) vty->xpath_index--; } diff --git a/lib/command.h b/lib/command.h index 5629eb3679..e7c9ff4c52 100644 --- a/lib/command.h +++ b/lib/command.h @@ -182,6 +182,11 @@ struct cmd_node { /* Node's configuration write function */ int (*config_write)(struct vty *); + /* called when leaving the node on a VTY session. + * return 1 if normal exit processing should happen, 0 to suppress + */ + int (*node_exit)(struct vty *); + /* Node's command graph */ struct graph *cmdgraph; @@ -2199,6 +2199,9 @@ void vty_close(struct vty *vty) int i; bool was_stdio = false; + /* Drop out of configure / transaction if needed. */ + vty_config_exit(vty); + /* Cancel threads.*/ THREAD_OFF(vty->t_read); THREAD_OFF(vty->t_write); @@ -2242,9 +2245,6 @@ void vty_close(struct vty *vty) list_delete(&vty->error); } - /* Check configure. */ - vty_config_exit(vty); - /* OK free vty. */ XFREE(MTYPE_VTY, vty); @@ -2614,14 +2614,18 @@ void vty_config_exit(struct vty *vty) cnode = vector_lookup(cmdvec, node); node = cnode->parent_node; } - if (node != CONFIG_NODE) { - vty_out(vty, - "WARNING: vty_config_exit() from outside CONFIG_NODE!\n"); + if (node != CONFIG_NODE) + /* called outside config, e.g. vty_close() in ENABLE_NODE */ return; - } while (vty->node != ENABLE_NODE) + /* will call vty_config_node_exit() below */ cmd_exit(vty); +} + +int vty_config_node_exit(struct vty *vty) +{ + vty->xpath_index = 0; /* Check if there's a pending confirmed commit. */ if (vty->t_confirmed_commit_timeout) { @@ -2644,6 +2648,7 @@ void vty_config_exit(struct vty *vty) } vty->config = false; + return 1; } /* Master of the threads. */ @@ -323,6 +323,7 @@ extern void vty_log(const char *level, const char *proto, const char *msg, extern int vty_config_enter(struct vty *vty, bool private_config, bool exclusive); extern void vty_config_exit(struct vty *); +extern int vty_config_node_exit(struct vty *); extern int vty_shell(struct vty *); extern int vty_shell_serv(struct vty *); extern void vty_hello(struct vty *); |
