summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2013-09-02 13:17:15 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-09-02 20:20:05 +0200
commit190acf6fd03f7f9a92b3e0044abf455b8a465c33 (patch)
tree57a4d24360da524887b1b60dab318cffe33b3897
parent96903c4b2d401f2c192f0c68ef251043bdf1967e (diff)
vty: Generalize ournode_exit() and ournode_end()
ournode_exit() duplicates most of bsc_vty_go_parent(). This patch fixes the inconsistencies of both functions within bsc_vty_go_parent() and replaces the implementation of ournode_exit() by a call to it. This makes 'exit' behave exactly like ^D in all openbsc nodes. ournode_end() has been changed to walk through the intermediate nodes until one of the top nodes is reached. This allows for cleanups to be done on the way. Note that in config mode if the tree is searched along the nodes toward the config node and a command is not found this way, a rollback is done by just replacing the vty's node and index member variable by the saved old values which might break the whole thing, when there has been a free() on the way.
-rw-r--r--openbsc/src/libcommon/common_vty.c140
1 files changed, 36 insertions, 104 deletions
diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c
index 7342f14..7aca4ca 100644
--- a/openbsc/src/libcommon/common_vty.c
+++ b/openbsc/src/libcommon/common_vty.c
@@ -48,6 +48,7 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
/* set vty->index correctly ! */
struct gsm_bts *bts = vty->index;
vty->index = bts->network;
+ vty->index_sub = NULL;
}
break;
case TRX_NODE:
@@ -56,6 +57,7 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
/* set vty->index correctly ! */
struct gsm_bts_trx *trx = vty->index;
vty->index = trx->bts;
+ vty->index_sub = &trx->bts->description;
}
break;
case TS_NODE:
@@ -64,18 +66,19 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
/* set vty->index correctly ! */
struct gsm_bts_trx_ts *ts = vty->index;
vty->index = ts->trx;
+ vty->index_sub = &ts->trx->description;
}
break;
case OML_NODE:
case OM2K_NODE:
vty->node = ENABLE_NODE;
+ /* NOTE: this only works because it's not part of the config
+ * tree, where outer commands are searched via vty_go_parent()
+ * and only (!) executed when a matching one is found.
+ */
talloc_free(vty->index);
vty->index = NULL;
break;
- case NAT_NODE:
- vty->node = CONFIG_NODE;
- vty->index = NULL;
- break;
case NAT_BSC_NODE:
vty->node = NAT_NODE;
{
@@ -85,19 +88,31 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
break;
case PGROUP_NODE:
vty->node = NAT_NODE;
+ vty->index = NULL;
break;
case TRUNK_NODE:
vty->node = MGCP_NODE;
+ vty->index = NULL;
break;
case SMPP_ESME_NODE:
vty->node = SMPP_NODE;
vty->index = NULL;
break;
case SMPP_NODE:
+ case MGCP_NODE:
+ case GBPROXY_NODE:
+ case SGSN_NODE:
+ case NAT_NODE:
+ case BSC_NODE:
case MSC_NODE:
case MNCC_INT_NODE:
default:
- vty->node = CONFIG_NODE;
+ if (bsc_vty_is_config_node(vty, vty->node))
+ vty->node = CONFIG_NODE;
+ else
+ vty->node = ENABLE_NODE;
+
+ vty->index = NULL;
}
return vty->node;
@@ -107,78 +122,7 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
gDEFUN(ournode_exit,
ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
{
- switch (vty->node) {
- case GSMNET_NODE:
- vty->node = CONFIG_NODE;
- vty->index = NULL;
- break;
- case BTS_NODE:
- vty->node = GSMNET_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts *bts = vty->index;
- vty->index = bts->network;
- vty->index_sub = NULL;
- }
- break;
- case TRX_NODE:
- vty->node = BTS_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts_trx *trx = vty->index;
- vty->index = trx->bts;
- vty->index_sub = &trx->bts->description;
- }
- break;
- case TS_NODE:
- vty->node = TRX_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts_trx_ts *ts = vty->index;
- vty->index = ts->trx;
- vty->index_sub = &ts->trx->description;
- }
- break;
- case NAT_BSC_NODE:
- vty->node = NAT_NODE;
- {
- struct bsc_config *bsc_config = vty->index;
- vty->index = bsc_config->nat;
- }
- break;
- case PGROUP_NODE:
- vty->node = NAT_NODE;
- break;
- case SMPP_ESME_NODE:
- vty->node = SMPP_NODE;
- vty->index = NULL;
- break;
- case SMPP_NODE:
- case MGCP_NODE:
- case GBPROXY_NODE:
- case SGSN_NODE:
- case NAT_NODE:
- case BSC_NODE:
- vty->node = CONFIG_NODE;
- vty->index = NULL;
- break;
- case OML_NODE:
- case OM2K_NODE:
- vty->node = ENABLE_NODE;
- talloc_free(vty->index);
- vty->index = NULL;
- break;
- case MSC_NODE:
- case MNCC_INT_NODE:
- vty->node = CONFIG_NODE;
- break;
- case TRUNK_NODE:
- vty->node = MGCP_NODE;
- vty->index = NULL;
- break;
- default:
- break;
- }
+ bsc_vty_go_parent (vty);
return CMD_SUCCESS;
}
@@ -186,36 +130,24 @@ gDEFUN(ournode_exit,
gDEFUN(ournode_end,
ournode_end_cmd, "end", "End current mode and change to enable mode.")
{
- switch (vty->node) {
- case VIEW_NODE:
- case ENABLE_NODE:
- /* Nothing to do. */
- break;
- case CONFIG_NODE:
- case GSMNET_NODE:
- case BTS_NODE:
- case TRX_NODE:
- case TS_NODE:
- case MGCP_NODE:
- case TRUNK_NODE:
- case GBPROXY_NODE:
- case SGSN_NODE:
- case VTY_NODE:
- case NAT_NODE:
- case NAT_BSC_NODE:
- case PGROUP_NODE:
- case MSC_NODE:
- case MNCC_INT_NODE:
- case SMPP_NODE:
- case SMPP_ESME_NODE:
- case BSC_NODE:
+ enum node_type last_node = CONFIG_NODE;
+
+ if (vty->node > ENABLE_NODE) {
+ /* Repeatedly call go_parent until a top node is reached. */
+ while (vty->node > CONFIG_NODE) {
+ if (vty->node == last_node) {
+ /* Ensure termination, this shouldn't happen. */
+ break;
+ }
+ last_node = vty->node;
+ bsc_vty_go_parent(vty);
+ }
+
vty_config_unlock(vty);
- vty->node = ENABLE_NODE;
+ if (vty->node > ENABLE_NODE)
+ vty->node = ENABLE_NODE;
vty->index = NULL;
vty->index_sub = NULL;
- break;
- default:
- break;
}
return CMD_SUCCESS;
}