diff options
-rw-r--r-- | include/osmocom/vty/vty.h | 9 | ||||
-rw-r--r-- | src/vty/command.c | 54 | ||||
-rw-r--r-- | tests/vty/vty_test.c | 16 |
3 files changed, 31 insertions, 48 deletions
diff --git a/include/osmocom/vty/vty.h b/include/osmocom/vty/vty.h index 03a29248..9acaa7d2 100644 --- a/include/osmocom/vty/vty.h +++ b/include/osmocom/vty/vty.h @@ -178,9 +178,14 @@ struct vty_app_info { const char *copyright; /*! \ref talloc context */ void *tall_ctx; - /*! call-back for returning to parent n ode */ + /*! Call-back for taking actions upon exiting a node. + * The return value is ignored, and changes to vty->node and vty->index made in this callback are ignored. + * Implicit parent node tracking always sets the correct parent node and vty->index after this callback exits, + * so this callback can handle only those nodes that should take specific actions upon node exit, or can be left + * NULL entirely. */ int (*go_parent_cb)(struct vty *vty); - /*! call-back to determine if node is config node */ + /*! OBSOLETED: Implicit parent node tracking has replaced the use of this callback. This callback is no longer + * called, ever, and can be left NULL. */ int (*is_config_node)(struct vty *vty, int node); /*! Check if the config is consistent before write */ int (*config_is_consistent)(struct vty *vty); diff --git a/src/vty/command.c b/src/vty/command.c index 6a9d18af..daee5c5a 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -200,18 +200,6 @@ static int cmp_desc(const void *p, const void *q) return strcmp(a->cmd, b->cmd); } -static int is_config_child(struct vty *vty) -{ - if (vty->node <= CONFIG_NODE) - return 0; - else if (vty->node > CONFIG_NODE && vty->node < _LAST_OSMOVTY_NODE) - return 1; - else if (host.app_info->is_config_node) - return host.app_info->is_config_node(vty, vty->node); - else - return vty->node > CONFIG_NODE; -} - /*! Sort each node's command element according to command string. */ void sort_node(void) { @@ -2187,25 +2175,10 @@ int vty_go_parent(struct vty *vty) vty_clear_parents(vty); break; - case CFG_LOG_NODE: - case VTY_NODE: - vty->node = CONFIG_NODE; - vty_clear_parents(vty); - break; - default: - if (host.app_info->go_parent_cb) { + if (host.app_info->go_parent_cb) host.app_info->go_parent_cb(vty); - vty_pop_parent(vty); - } - else if (is_config_child(vty)) { - vty->node = CONFIG_NODE; - vty_clear_parents(vty); - } - else { - vty->node = VIEW_NODE; - vty_clear_parents(vty); - } + vty_pop_parent(vty); break; } @@ -2365,9 +2338,30 @@ cmd_execute_command_real(vector vline, struct vty *vty, if (matched_element->daemon) rc = CMD_SUCCESS_DAEMON; - else /* Execute matched command. */ + else { + /* Execute matched command. */ + struct vty_parent_node this_node = { + .node = vty->node, + .priv = vty->priv, + .indent = vty->indent, + }; + struct vty_parent_node *parent = vty_parent(vty); rc = (*matched_element->func) (matched_element, vty, argc, argv); + /* If we have stepped down into a child node, push a parent frame. + * The causality is such: we don't expect every single node entry implementation to push + * a parent node entry onto vty->parent_nodes. Instead we expect vty_go_parent() to *pop* + * a parent node. Hence if the node changed without the parent node changing, we must + * have stepped into a child node. */ + if (vty->node != this_node.node && parent == vty_parent(vty) + && vty->node > CONFIG_NODE) { + /* Push the parent node. */ + parent = talloc_zero(vty, struct vty_parent_node); + *parent = this_node; + llist_add(&parent->entry, &vty->parent_nodes); + } + } + rc_free_deopt_ctx: /* Now after we called the command func, we can free temporary strings */ talloc_free(cmd_deopt_ctx); diff --git a/tests/vty/vty_test.c b/tests/vty/vty_test.c index 1139638d..9627b6d2 100644 --- a/tests/vty/vty_test.c +++ b/tests/vty/vty_test.c @@ -482,27 +482,11 @@ void test_is_cmd_ambiguous() destroy_test_vty(&test, vty); } -static int go_parent_cb(struct vty *vty) -{ - /* - * - For the interactive VTY tests above, it is expected to bounce back to - * the CONFIG_NODE. Hence do so in go_parent_cb(). - * - In the config file parsing tests, setting vty->node in go_parent_cb() has no - * effect, because we will subsequently pop a parent node from the parent stack - * and override to go to the node that was recorded as the actual parent. - */ - vty->node = CONFIG_NODE; - vty->index = NULL; - return 0; -} - int main(int argc, char **argv) { struct vty_app_info vty_info = { .name = "VtyTest", .version = 0, - .go_parent_cb = go_parent_cb, - .is_config_node = NULL, }; const struct log_info_cat default_categories[] = {}; |