[PATCH v2 03/10] mesh: Make meshctl use bt_shell helpers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

This makes meshctl use bt_shell to manage the menus and command
handling.
---
 Makefile.tools       |   1 -
 mesh/agent.c         |  22 +-
 mesh/config-client.c | 190 ++++++++---------
 mesh/config-model.h  |   1 -
 mesh/config-server.c |  17 +-
 mesh/gatt.c          |  36 ++--
 mesh/main.c          | 592 ++++++++++++++-------------------------------------
 mesh/net.c           |  16 +-
 mesh/node.c          |  10 +-
 mesh/onoff-model.c   |  91 +++-----
 mesh/prov-db.c       |  25 ++-
 mesh/prov.c          |  16 +-
 mesh/util.c          | 179 ++--------------
 mesh/util.h          |  16 +-
 14 files changed, 360 insertions(+), 852 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 561302fa1..ba717e6cf 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -30,7 +30,6 @@ mesh_meshctl_SOURCES = mesh/main.c \
 				mesh/config-model.h mesh/config-client.c \
 				mesh/config-server.c \
 				mesh/onoff-model.h mesh/onoff-model.c \
-				client/display.h client/display.c \
 				monitor/uuid.h monitor/uuid.c
 mesh_meshctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
 				lib/libbluetooth-internal.la \
diff --git a/mesh/agent.c b/mesh/agent.c
index efb8937d9..b8a14f015 100644
--- a/mesh/agent.c
+++ b/mesh/agent.c
@@ -29,12 +29,12 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <inttypes.h>
-#include <readline/readline.h>
 
 #include <glib.h>
 
 #include <lib/bluetooth.h>
-#include "client/display.h"
+
+#include "src/shared/shell.h"
 #include "mesh/util.h"
 #include "mesh/agent.h"
 
@@ -68,7 +68,7 @@ static void response_hexadecimal(const char *input, void *user_data)
 	uint8_t buf[MAX_HEXADECIMAL_OOB_LEN];
 
 	if (!str2hex(input, strlen(input), buf, pending_request.len) ) {
-		rl_printf("Incorrect input: expecting %d hex octets\n",
+		bt_shell_printf("Incorrect input: expecting %d hex octets\n",
 			  pending_request.len);
 		return;
 	}
@@ -110,8 +110,8 @@ static bool request_hexadecimal(uint16_t len)
 	if (len > MAX_HEXADECIMAL_OOB_LEN)
 		return false;
 
-	rl_printf("Request hexadecimal key (hex %d octets)\n", len);
-	rl_prompt_input("mesh", "Enter key (hex number):", response_hexadecimal,
+	bt_shell_printf("Request hexadecimal key (hex %d octets)\n", len);
+	bt_shell_prompt_input("mesh", "Enter key (hex number):", response_hexadecimal,
 								NULL);
 
 	return true;
@@ -129,8 +129,8 @@ static uint32_t power_ten(uint8_t power)
 
 static bool request_decimal(uint16_t len)
 {
-	rl_printf("Request decimal key (0 - %d)\n", power_ten(len) - 1);
-	rl_prompt_input("mesh", "Enter Numeric key:", response_decimal, NULL);
+	bt_shell_printf("Request decimal key (0 - %d)\n", power_ten(len) - 1);
+	bt_shell_prompt_input("mesh", "Enter Numeric key:", response_decimal, NULL);
 
 	return true;
 }
@@ -140,8 +140,8 @@ static bool request_ascii(uint16_t len)
 	if (len > MAX_ASCII_OOB_LEN)
 		return false;
 
-	rl_printf("Request ASCII key (max characters %d)\n", len);
-	rl_prompt_input("mesh", "Enter key (ascii string):", response_ascii,
+	bt_shell_printf("Request ASCII key (max characters %d)\n", len);
+	bt_shell_prompt_input("mesh", "Enter key (ascii string):", response_ascii,
 									NULL);
 
 	return true;
@@ -194,7 +194,7 @@ bool agent_output_request(const char* str)
 		return false;
 
 	pending_request.type = OUTPUT;
-	rl_prompt_input("mesh", str, response_output, NULL);
+	bt_shell_prompt_input("mesh", str, response_output, NULL);
 	return true;
 }
 
@@ -203,5 +203,5 @@ void agent_output_request_cancel(void)
 	if (pending_request.type != OUTPUT)
 		return;
 	pending_request.type = NONE;
-	rl_release_prompt("");
+	bt_shell_release_prompt("");
 }
diff --git a/mesh/config-client.c b/mesh/config-client.c
index 782781602..7aabe6ce7 100644
--- a/mesh/config-client.c
+++ b/mesh/config-client.c
@@ -34,12 +34,11 @@
 #include <stdbool.h>
 #include <sys/uio.h>
 #include <wordexp.h>
-#include <readline/readline.h>
-#include <readline/history.h>
+
 #include <glib.h>
 
+#include "src/shared/shell.h"
 #include "src/shared/util.h"
-#include "client/display.h"
 #include "mesh/mesh-net.h"
 #include "mesh/keys.h"
 #include "mesh/net.h"
@@ -101,12 +100,12 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 		if (len != 4)
 			break;
 
-		rl_printf("Node %4.4x AppKey Status %s\n", src,
+		bt_shell_printf("Node %4.4x AppKey Status %s\n", src,
 						mesh_status_str(data[0]));
 		net_idx = get_le16(data + 1) & 0xfff;
 		app_idx = get_le16(data + 2) >> 4;
 
-		rl_printf("\tNetKey %3.3x, AppKey %3.3x\n", net_idx, app_idx);
+		bt_shell_printf("\tNetKey %3.3x, AppKey %3.3x\n", net_idx, app_idx);
 
 		if (data[0] != MESH_STATUS_SUCCESS &&
 				data[0] != MESH_STATUS_IDX_ALREADY_STORED &&
@@ -119,11 +118,11 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 		if (len != 3)
 			break;
 
-		rl_printf("Node %4.4x NetKey Status %s\n", src,
+		bt_shell_printf("Node %4.4x NetKey Status %s\n", src,
 						mesh_status_str(data[0]));
 		net_idx = get_le16(data + 1) & 0xfff;
 
-		rl_printf("\tNetKey %3.3x\n", net_idx);
+		bt_shell_printf("\tNetKey %3.3x\n", net_idx);
 
 		if (data[0] != MESH_STATUS_SUCCESS &&
 				data[0] != MESH_STATUS_IDX_ALREADY_STORED &&
@@ -136,20 +135,20 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 		if (len != 7 && len != 9)
 			break;
 
-		rl_printf("Node %4.4x Model App Status %s\n", src,
+		bt_shell_printf("Node %4.4x Model App Status %s\n", src,
 						mesh_status_str(data[0]));
 		addr = get_le16(data + 1);
 		app_idx = get_le16(data + 3);
 
-		rl_printf("\tElement %4.4x AppIdx %3.3x\n ", addr, app_idx);
+		bt_shell_printf("\tElement %4.4x AppIdx %3.3x\n ", addr, app_idx);
 
 		if (len == 7) {
 			mod_id = get_le16(data + 5);
-			rl_printf("ModelId %4.4x\n", mod_id);
+			bt_shell_printf("ModelId %4.4x\n", mod_id);
 			mod_id = 0xffff0000 | mod_id;
 		} else {
 			mod_id = get_le16(data + 7);
-			rl_printf("ModelId %4.4x %4.4x\n", get_le16(data + 5),
+			bt_shell_printf("ModelId %4.4x %4.4x\n", get_le16(data + 5),
 									mod_id);
 			mod_id = get_le16(data + 5) << 16 | mod_id;
 		}
@@ -162,7 +161,7 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 	case OP_CONFIG_DEFAULT_TTL_STATUS:
 		if (len != 1)
 			return true;
-		rl_printf("Node %4.4x Default TTL %d\n", src, data[0]);
+		bt_shell_printf("Node %4.4x Default TTL %d\n", src, data[0]);
 		if (node_set_default_ttl (node, data[0]))
 			prov_db_node_set_ttl(node, data[0]);
 		break;
@@ -171,7 +170,7 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 		if (len != 12 && len != 14)
 			return true;
 
-		rl_printf("\nSet publication for node %4.4x status: %s\n", src,
+		bt_shell_printf("\nSet publication for node %4.4x status: %s\n", src,
 				data[0] == MESH_STATUS_SUCCESS ? "Success" :
 						mesh_status_str(data[0]));
 
@@ -192,22 +191,22 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 		n = (data[8] & 0x3f);
 		switch (data[8] >> 6) {
 		case 0:
-			rl_printf("Period: %d ms\n", n * 100);
+			bt_shell_printf("Period: %d ms\n", n * 100);
 			break;
 		case 2:
 			n *= 10;
 			/* fall through */
 		case 1:
-			rl_printf("Period: %d sec\n", n);
+			bt_shell_printf("Period: %d sec\n", n);
 			break;
 		case 3:
-			rl_printf("Period: %d min\n", n * 10);
+			bt_shell_printf("Period: %d min\n", n * 10);
 			break;
 		}
 
 		pub.retransmit = data[9];
-		rl_printf("Retransmit count: %d\n", data[9] >> 5);
-		rl_printf("Retransmit Interval Steps: %d\n", data[9] & 0x1f);
+		bt_shell_printf("Retransmit count: %d\n", data[9] >> 5);
+		bt_shell_printf("Retransmit Interval Steps: %d\n", data[9] & 0x1f);
 
 		ele_idx = ele_addr - node_get_primary(node);
 
@@ -226,45 +225,43 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 static uint32_t target;
 static uint32_t parms[8];
 
-static uint32_t read_input_parameters(const char *args)
+static uint32_t read_input_parameters(int argc, char *argv[])
 {
 	uint32_t i;
 
-	if (!args)
+	--argc;
+	++argv;
+
+	if (!argc || argv[1][0] == '\0')
 		return 0;
 
 	memset(parms, 0xff, sizeof(parms));
 
-	for (i = 0; i < sizeof(parms)/sizeof(parms[0]); i++) {
-		int n;
-
-		sscanf(args, "%x", &parms[i]);
+	for (i = 0; i < sizeof(parms)/sizeof(parms[0]) && i < (unsigned) argc;
+									i++) {
+		sscanf(argv[i], "%x", &parms[i]);
 		if (parms[i] == 0xffffffff)
 			break;
-
-		n = strcspn(args, " \t");
-		args = args + n + strspn(args + n, " \t");
 	}
 
 	return i;
 }
 
-static void cmd_set_node(const char *args)
+static void cmd_set_node(int argc, char *argv[])
 {
 	uint32_t dst;
 	char *end;
 
-	dst = strtol(args, &end, 16);
-	if (end != (args + 4)) {
-		rl_printf("Bad unicast address %s: "
-					"expected format 4 digit hex\n", args);
+	dst = strtol(argv[1], &end, 16);
+	if (end != (argv[1] + 4)) {
+		bt_shell_printf("Bad unicast address %s: "
+				"expected format 4 digit hex\n", argv[1]);
 		target = UNASSIGNED_ADDRESS;
 	} else {
-		rl_printf("Configuring node %4.4x\n", dst);
+		bt_shell_printf("Configuring node %4.4x\n", dst);
 		target = dst;
-		set_menu_prompt("config", args);
+		set_menu_prompt("config", argv[1]);
 	}
-
 }
 
 static bool config_send(uint8_t *buf, uint16_t len)
@@ -287,14 +284,14 @@ static bool config_send(uint8_t *buf, uint16_t len)
 
 }
 
-static void cmd_get_composition(const char *args)
+static void cmd_get_composition(int argc, char *argv[])
 {
 	uint16_t n;
 	uint8_t msg[32];
 	struct mesh_node *node;
 
 	if (IS_UNASSIGNED(target)) {
-		rl_printf("Destination not set\n");
+		bt_shell_printf("Destination not set\n");
 		return;
 	}
 
@@ -306,13 +303,13 @@ static void cmd_get_composition(const char *args)
 	n = mesh_opcode_set(OP_DEV_COMP_GET, msg);
 
 	/* By default, use page 0 */
-	msg[n++] = (read_input_parameters(args) == 1) ? parms[0] : 0;
+	msg[n++] = (read_input_parameters(argc, argv) == 1) ? parms[0] : 0;
 
 	if (!config_send(msg, n))
-		rl_printf("Failed to send \"GET NODE COMPOSITION\"\n");
+		bt_shell_printf("Failed to send \"GET NODE COMPOSITION\"\n");
 }
 
-static void cmd_net_key(const char *args, uint32_t opcode)
+static void cmd_net_key(int argc, char *argv[], uint32_t opcode)
 {
 	uint16_t n;
 	uint8_t msg[32];
@@ -321,20 +318,20 @@ static void cmd_net_key(const char *args, uint32_t opcode)
 	struct mesh_node *node;
 
 	if (IS_UNASSIGNED(target)) {
-		rl_printf("Destination not set\n");
+		bt_shell_printf("Destination not set\n");
 		return;
 	}
 
 	n = mesh_opcode_set(opcode, msg);
 
-	if (read_input_parameters(args) != 1) {
-		rl_printf("Bad arguments %s\n", args);
+	if (read_input_parameters(argc, argv) != 1) {
+		bt_shell_printf("Bad arguments %s\n", argv[1]);
 		return;
 	}
 
 	node = node_find_by_addr(target);
 	if (!node) {
-		rl_printf("Node %4.4x\n not found", target);
+		bt_shell_printf("Node %4.4x\n not found", target);
 		return;
 	}
 
@@ -344,7 +341,7 @@ static void cmd_net_key(const char *args, uint32_t opcode)
 
 		key = keys_net_key_get(net_idx, true);
 		if (!key) {
-			rl_printf("Network key with index %4.4x not found\n",
+			bt_shell_printf("Network key with index %4.4x not found\n",
 								net_idx);
 			return;
 		}
@@ -357,7 +354,7 @@ static void cmd_net_key(const char *args, uint32_t opcode)
 	}
 
 	if (!config_send(msg, n)) {
-		rl_printf("Failed to send \"%s NET KEY\"\n",
+		bt_shell_printf("Failed to send \"%s NET KEY\"\n",
 				opcode == OP_NETKEY_ADD ? "ADD" : "DEL");
 		return;
 	}
@@ -374,17 +371,17 @@ static void cmd_net_key(const char *args, uint32_t opcode)
 
 }
 
-static void cmd_add_net_key(const char *args)
+static void cmd_add_net_key(int argc, char *argv[])
 {
-	cmd_net_key(args, OP_NETKEY_ADD);
+	cmd_net_key(argc, argv, OP_NETKEY_ADD);
 }
 
-static void cmd_del_net_key(const char *args)
+static void cmd_del_net_key(int argc, char *argv[])
 {
-	cmd_net_key(args, OP_NETKEY_DELETE);
+	cmd_net_key(argc, argv, OP_NETKEY_DELETE);
 }
 
-static void cmd_app_key(const char *args, uint32_t opcode)
+static void cmd_app_key(int argc, char *argv[], uint32_t opcode)
 {
 	uint16_t n;
 	uint8_t msg[32];
@@ -394,18 +391,18 @@ static void cmd_app_key(const char *args, uint32_t opcode)
 	struct mesh_node *node;
 
 	if (IS_UNASSIGNED(target)) {
-		rl_printf("Destination not set\n");
+		bt_shell_printf("Destination not set\n");
 		return;
 	}
 
-	if (read_input_parameters(args) != 1) {
-		rl_printf("Bad arguments %s\n", args);
+	if (read_input_parameters(argc, argv) != 1) {
+		bt_shell_printf("Bad arguments %s\n", argv[1]);
 		return;
 	}
 
 	node = node_find_by_addr(target);
 	if (!node) {
-		rl_printf("Node %4.4x\n not found", target);
+		bt_shell_printf("Node %4.4x\n not found", target);
 		return;
 	}
 
@@ -414,7 +411,7 @@ static void cmd_app_key(const char *args, uint32_t opcode)
 	app_idx = parms[0];
 	net_idx = keys_app_key_get_bound(app_idx);
 	if (net_idx == NET_IDX_INVALID) {
-		rl_printf("App key with index %4.4x not found\n", app_idx);
+		bt_shell_printf("App key with index %4.4x not found\n", app_idx);
 		return;
 	}
 
@@ -426,7 +423,7 @@ static void cmd_app_key(const char *args, uint32_t opcode)
 	if (opcode != OP_APPKEY_DELETE) {
 		key = keys_app_key_get(app_idx, true);
 		if (!key) {
-			rl_printf("App key %4.4x not found\n", net_idx);
+			bt_shell_printf("App key %4.4x not found\n", net_idx);
 			return;
 		}
 
@@ -435,7 +432,7 @@ static void cmd_app_key(const char *args, uint32_t opcode)
 	}
 
 	if (!config_send(msg, n)) {
-		rl_printf("Failed to send \"ADD %s KEY\"\n",
+		bt_shell_printf("Failed to send \"ADD %s KEY\"\n",
 				opcode == OP_APPKEY_ADD ? "ADD" : "DEL");
 		return;
 	}
@@ -451,14 +448,14 @@ static void cmd_app_key(const char *args, uint32_t opcode)
 	}
 }
 
-static void cmd_add_app_key(const char *args)
+static void cmd_add_app_key(int argc, char *argv[])
 {
-	cmd_app_key(args, OP_APPKEY_ADD);
+	cmd_app_key(argc, argv, OP_APPKEY_ADD);
 }
 
-static void cmd_del_app_key(const char *args)
+static void cmd_del_app_key(int argc, char *argv[])
 {
-	cmd_app_key(args, OP_APPKEY_DELETE);
+	cmd_app_key(argc, argv, OP_APPKEY_DELETE);
 }
 
 static bool verify_config_target(uint32_t dst)
@@ -466,25 +463,25 @@ static bool verify_config_target(uint32_t dst)
 	struct mesh_node *node;
 
 	if (IS_UNASSIGNED(dst)) {
-		rl_printf("Destination not set\n");
+		bt_shell_printf("Destination not set\n");
 		return false;
 	}
 
 	node = node_find_by_addr(dst);
 	if (!node) {
-		rl_printf("Node with unicast address %4.4x unknown\n", dst);
+		bt_shell_printf("Node with unicast address %4.4x unknown\n", dst);
 		return false;
 	}
 
 	if (!node_get_composition(node)) {
-		rl_printf("Node composition for %4.4x unknown\n", dst);
+		bt_shell_printf("Node composition for %4.4x unknown\n", dst);
 		return false;
 	}
 
 	return true;
 }
 
-static void cmd_bind(const char *args)
+static void cmd_bind(int argc, char *argv[])
 {
 	uint16_t n;
 	uint8_t msg[32];
@@ -493,9 +490,9 @@ static void cmd_bind(const char *args)
 	if (!verify_config_target(target))
 		return;
 
-	parm_cnt = read_input_parameters(args);
+	parm_cnt = read_input_parameters(argc, argv);
 	if (parm_cnt != 3 && parm_cnt != 4) {
-		rl_printf("Bad arguments %s\n", args);
+		bt_shell_printf("Bad arguments\n");
 		return;
 	}
 
@@ -515,10 +512,10 @@ static void cmd_bind(const char *args)
 	}
 
 	if (!config_send(msg, n))
-		rl_printf("Failed to send \"MODEL APP BIND\"\n");
+		bt_shell_printf("Failed to send \"MODEL APP BIND\"\n");
 }
 
-static void cmd_set_ttl(const char *args)
+static void cmd_set_ttl(int argc, char *argv[])
 {
 	uint16_t n;
 	uint8_t msg[32];
@@ -526,13 +523,13 @@ static void cmd_set_ttl(const char *args)
 	uint8_t ttl;
 
 	if (IS_UNASSIGNED(target)) {
-		rl_printf("Destination not set\n");
+		bt_shell_printf("Destination not set\n");
 		return;
 	}
 
 	n = mesh_opcode_set(OP_CONFIG_DEFAULT_TTL_SET, msg);
 
-	parm_cnt = read_input_parameters(args);
+	parm_cnt = read_input_parameters(argc, argv);
 	if (parm_cnt) {
 		ttl = parms[0] & TTL_MASK;
 	} else
@@ -541,10 +538,10 @@ static void cmd_set_ttl(const char *args)
 	msg[n++] = ttl;
 
 	if (!config_send(msg, n))
-		rl_printf("Failed to send \"SET_DEFAULT TTL\"\n");
+		bt_shell_printf("Failed to send \"SET_DEFAULT TTL\"\n");
 }
 
-static void cmd_set_pub(const char *args)
+static void cmd_set_pub(int argc, char *argv[])
 {
 	uint16_t n;
 	uint8_t msg[32];
@@ -555,9 +552,9 @@ static void cmd_set_pub(const char *args)
 
 	n = mesh_opcode_set(OP_CONFIG_MODEL_PUB_SET, msg);
 
-	parm_cnt = read_input_parameters(args);
+	parm_cnt = read_input_parameters(argc, argv);
 	if (parm_cnt != 5) {
-		rl_printf("Bad arguments: %s\n", args);
+		bt_shell_printf("Bad arguments\n");
 		return;
 	}
 
@@ -586,7 +583,7 @@ static void cmd_set_pub(const char *args)
 	}
 
 	if (!config_send(msg, n))
-		rl_printf("Failed to send \"SET MODEL PUBLICATION\"\n");
+		bt_shell_printf("Failed to send \"SET MODEL PUBLICATION\"\n");
 }
 
 static void cmd_default(uint32_t opcode)
@@ -595,29 +592,25 @@ static void cmd_default(uint32_t opcode)
 	uint8_t msg[32];
 
 	if (IS_UNASSIGNED(target)) {
-		rl_printf("Destination not set\n");
+		bt_shell_printf("Destination not set\n");
 		return;
 	}
 
 	n = mesh_opcode_set(opcode, msg);
 
 	if (!config_send(msg, n))
-		rl_printf("Failed to send command (opcode 0x%x)\n", opcode);
+		bt_shell_printf("Failed to send command (opcode 0x%x)\n",
+								opcode);
 }
 
-static void cmd_get_ttl(const char *args)
+static void cmd_get_ttl(int argc, char *argv[])
 {
 	cmd_default(OP_CONFIG_DEFAULT_TTL_GET);
 }
 
-static void cmd_back(const char *args)
-{
-	cmd_menu_main(false);
-}
-
-static void cmd_help(const char *args);
-
-static const struct menu_entry cfg_menu[] = {
+static const struct bt_shell_menu cfg_menu = {
+	.name = "config",
+	.entries = {
 	{"target",		"<unicast>",			cmd_set_node,
 						"Set target node to configure"},
 	{"get-composition",	"[<page_num>]",		cmd_get_composition,
@@ -639,30 +632,15 @@ static const struct menu_entry cfg_menu[] = {
 	{"set-pub", "<ele_addr> <pub_addr> <app_idx> "
 						"<period (step|res)> <model>",
 				cmd_set_pub,	"Set publication"},
-	{"back",		NULL,				cmd_back,
-						"Back to main menu"},
-	{"help",		NULL,				cmd_help,
-						"Config Commands"},
-	{}
+	{} },
 };
 
-static void cmd_help(const char *args)
-{
-	rl_printf("Client Configuration Menu\n");
-	print_cmd_menu(cfg_menu);
-}
-
-void config_set_node(const char *args)
-{
-	cmd_set_node(args);
-}
-
 void config_client_get_composition(uint32_t dst)
 {
 	uint32_t tmp = target;
 
 	target = dst;
-	cmd_get_composition("");
+	cmd_get_composition(0, NULL);
 	target = tmp;
 }
 
@@ -680,7 +658,7 @@ bool config_client_init(void)
 						&client_cbs, NULL))
 		return false;
 
-	add_cmd_menu("configure", cfg_menu);
+	bt_shell_add_submenu(&cfg_menu);
 
 	return true;
 }
diff --git a/mesh/config-model.h b/mesh/config-model.h
index d7ee5e61f..a5b811365 100644
--- a/mesh/config-model.h
+++ b/mesh/config-model.h
@@ -99,4 +99,3 @@
 bool config_server_init(void);
 bool config_client_init(void);
 void config_client_get_composition(uint32_t dst);
-void config_set_node(const char *args);
diff --git a/mesh/config-server.c b/mesh/config-server.c
index 938ec2275..10fead6e2 100644
--- a/mesh/config-server.c
+++ b/mesh/config-server.c
@@ -34,12 +34,11 @@
 #include <stdbool.h>
 #include <sys/uio.h>
 #include <wordexp.h>
-#include <readline/readline.h>
-#include <readline/history.h>
+
 #include <glib.h>
 
 #include "src/shared/util.h"
-#include "client/display.h"
+#include "src/shared/shell.h"
 #include "mesh/mesh-net.h"
 #include "mesh/keys.h"
 #include "mesh/net.h"
@@ -99,7 +98,7 @@ static bool server_msg_recvd(uint16_t src, uint8_t *data,
 		if (len != 11 && len != 13)
 			return true;
 
-		rl_printf("Set publication\n");
+		bt_shell_printf("Set publication\n");
 
 		ele_addr = get_le16(data);
 		mod_id = get_le16(data + 9);
@@ -115,22 +114,22 @@ static bool server_msg_recvd(uint16_t src, uint8_t *data,
 		m = (data[7] & 0x3f);
 		switch (data[7] >> 6) {
 		case 0:
-			rl_printf("Period: %d ms\n", m * 100);
+			bt_shell_printf("Period: %d ms\n", m * 100);
 			break;
 		case 2:
 			m *= 10;
 			/* fall through */
 		case 1:
-			rl_printf("Period: %d sec\n", m);
+			bt_shell_printf("Period: %d sec\n", m);
 			break;
 		case 3:
-			rl_printf("Period: %d min\n", m * 10);
+			bt_shell_printf("Period: %d min\n", m * 10);
 			break;
 		}
 
 		pub.retransmit = data[8];
-		rl_printf("Retransmit count: %d\n", data[8] >> 5);
-		rl_printf("Retransmit Interval Steps: %d\n", data[8] & 0x1f);
+		bt_shell_printf("Retransmit count: %d\n", data[8] >> 5);
+		bt_shell_printf("Retransmit Interval Steps: %d\n", data[8] & 0x1f);
 
 		ele_idx = ele_addr - node_get_primary(node);
 
diff --git a/mesh/gatt.c b/mesh/gatt.c
index 001eb17a8..197291e67 100644
--- a/mesh/gatt.c
+++ b/mesh/gatt.c
@@ -33,15 +33,13 @@
 #include <sys/uio.h>
 #include <wordexp.h>
 
-#include <readline/readline.h>
-#include <readline/history.h>
 #include <glib.h>
 
 #include "src/shared/io.h"
+#include "src/shared/shell.h"
 #include "gdbus/gdbus.h"
 #include "lib/bluetooth.h"
 #include "lib/uuid.h"
-#include "client/display.h"
 #include "mesh/node.h"
 #include "mesh/util.h"
 #include "mesh/gatt.h"
@@ -216,7 +214,7 @@ static bool pipe_write(struct io *io, void *user_data)
 
 		err = io_send(io, iov, 2);
 		if (err < 0) {
-			rl_printf("Failed to write: %s\n", strerror(-err));
+			bt_shell_printf("Failed to write: %s\n", strerror(-err));
 			write_data_free(data);
 			return false;
 		}
@@ -259,7 +257,7 @@ static void write_reply(DBusMessage *message, void *user_data)
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("Failed to write: %s\n", error.name);
+		bt_shell_printf("Failed to write: %s\n", error.name);
 		dbus_error_free(&error);
 		return;
 	}
@@ -307,7 +305,7 @@ static void write_reply(DBusMessage *message, void *user_data)
 
 	if (g_dbus_proxy_method_call(data->proxy, "WriteValue", write_setup,
 				write_reply, data, write_data_free) == FALSE) {
-		rl_printf("Failed to write\n");
+		bt_shell_printf("Failed to write\n");
 		write_data_free(data);
 		return;
 	}
@@ -330,7 +328,7 @@ static void notify_io_destroy(void)
 
 static bool pipe_hup(struct io *io, void *user_data)
 {
-	rl_printf("%s closed\n", io == notify_io ? "Notify" : "Write");
+	bt_shell_printf("%s closed\n", io == notify_io ? "Notify" : "Write");
 
 	if (io == notify_io)
 		notify_io_destroy();
@@ -366,7 +364,7 @@ static void acquire_write_reply(DBusMessage *message, void *user_data)
 		if (g_dbus_proxy_method_call(data->proxy, "WriteValue",
 				write_setup, write_reply, data,
 				write_data_free) == FALSE) {
-			rl_printf("Failed to write\n");
+			bt_shell_printf("Failed to write\n");
 			write_data_free(data);
 		}
 		return;
@@ -375,11 +373,11 @@ static void acquire_write_reply(DBusMessage *message, void *user_data)
 	if ((dbus_message_get_args(message, NULL, DBUS_TYPE_UNIX_FD, &fd,
 					DBUS_TYPE_UINT16, &write_mtu,
 					DBUS_TYPE_INVALID) == false)) {
-		rl_printf("Invalid AcquireWrite response\n");
+		bt_shell_printf("Invalid AcquireWrite response\n");
 		return;
 	}
 
-	rl_printf("AcquireWrite success: fd %d MTU %u\n", fd, write_mtu);
+	bt_shell_printf("AcquireWrite success: fd %d MTU %u\n", fd, write_mtu);
 
 	write_io = pipe_io_new(fd);
 
@@ -441,7 +439,7 @@ bool mesh_gatt_write(GDBusProxy *proxy, uint8_t *buf, uint16_t len,
 		if (g_dbus_proxy_method_call(proxy, "AcquireWrite",
 					acquire_setup, acquire_write_reply,
 					data, NULL) == FALSE) {
-			rl_printf("Failed to AcquireWrite\n");
+			bt_shell_printf("Failed to AcquireWrite\n");
 			write_data_free(data);
 			return false;
 		}
@@ -449,12 +447,12 @@ bool mesh_gatt_write(GDBusProxy *proxy, uint8_t *buf, uint16_t len,
 		if (g_dbus_proxy_method_call(data->proxy, "WriteValue",
 				write_setup, write_reply, data,
 				write_data_free) == FALSE) {
-			rl_printf("Failed to write\n");
+			bt_shell_printf("Failed to write\n");
 			write_data_free(data);
 			return false;
 		}
 		print_byte_array("GATT-TX: ", buf, len);
-		rl_printf("Attempting to write %s\n",
+		bt_shell_printf("Attempting to write %s\n",
 						g_dbus_proxy_get_path(proxy));
 	}
 
@@ -469,13 +467,13 @@ static void notify_reply(DBusMessage *message, void *user_data)
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("Failed to %s notify: %s\n",
+		bt_shell_printf("Failed to %s notify: %s\n",
 				data->enable ? "start" : "stop", error.name);
 		dbus_error_free(&error);
 		goto done;
 	}
 
-	rl_printf("Notify %s\n", data->enable ? "started" : "stopped");
+	bt_shell_printf("Notify %s\n", data->enable ? "started" : "stopped");
 
 done:
 	if (data->cb)
@@ -535,7 +533,7 @@ static void acquire_notify_reply(DBusMessage *message, void *user_data)
 		dbus_error_free(&error);
 		if (g_dbus_proxy_method_call(data->proxy, "StartNotify", NULL,
 					notify_reply, data, NULL) == FALSE) {
-			rl_printf("Failed to StartNotify\n");
+			bt_shell_printf("Failed to StartNotify\n");
 			g_free(data);
 		}
 		return;
@@ -553,13 +551,13 @@ static void acquire_notify_reply(DBusMessage *message, void *user_data)
 					DBUS_TYPE_INVALID) == false)) {
 		if (g_dbus_proxy_method_call(data->proxy, "StartNotify", NULL,
 					notify_reply, data, NULL) == FALSE) {
-			rl_printf("Failed to StartNotify\n");
+			bt_shell_printf("Failed to StartNotify\n");
 			g_free(data);
 		}
 		return;
 	}
 
-	rl_printf("AcquireNotify success: fd %d MTU %u\n", fd, notify_mtu);
+	bt_shell_printf("AcquireNotify success: fd %d MTU %u\n", fd, notify_mtu);
 
 	if (g_dbus_proxy_get_property(data->proxy, "UUID", &iter) == FALSE)
 		goto done;
@@ -619,7 +617,7 @@ bool mesh_gatt_notify(GDBusProxy *proxy, bool enable, GDBusReturnFunction cb,
 
 	if (g_dbus_proxy_method_call(proxy, method, setup, cb,
 					data, NULL) == FALSE) {
-		rl_printf("Failed to %s\n", method);
+		bt_shell_printf("Failed to %s\n", method);
 		return false;
 	}
 	return true;
diff --git a/mesh/main.c b/mesh/main.c
index 1d444977a..05841363f 100644
--- a/mesh/main.c
+++ b/mesh/main.c
@@ -30,8 +30,6 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdbool.h>
-#include <signal.h>
-#include <sys/signalfd.h>
 #include <wordexp.h>
 
 #include <inttypes.h>
@@ -41,16 +39,14 @@
 #include <sys/stat.h>
 #include "bluetooth/bluetooth.h"
 
-#include <readline/readline.h>
-#include <readline/history.h>
 #include <glib.h>
 
 #include "lib/bluetooth.h"
 #include "lib/uuid.h"
+#include "src/shared/shell.h"
 #include "src/shared/util.h"
 #include "gdbus/gdbus.h"
 #include "monitor/uuid.h"
-#include "client/display.h"
 #include "mesh/mesh-net.h"
 #include "mesh/gatt.h"
 #include "mesh/crypto.h"
@@ -77,7 +73,6 @@
 #define MESH_PROXY_DATA_IN_UUID_STR	"00002add-0000-1000-8000-00805f9b34fb"
 #define MESH_PROXY_DATA_OUT_UUID_STR	"00002ade-0000-1000-8000-00805f9b34fb"
 
-static GMainLoop *main_loop;
 static DBusConnection *dbus_conn;
 
 struct adapter {
@@ -103,8 +98,7 @@ static char *mesh_local_config_filename;
 static bool discovering = false;
 static bool discover_mesh;
 static uint16_t prov_net_key_index = NET_IDX_PRIMARY;
-
-static guint input = 0;
+static const struct bt_shell_menu main_menu;
 
 #define CONN_TYPE_NETWORK	0x00
 #define CONN_TYPE_IDENTITY	0x01
@@ -175,7 +169,7 @@ static bool char_is_mesh(GDBusProxy *proxy, const char *target_uuid)
 static gboolean check_default_ctrl(void)
 {
 	if (!default_ctrl) {
-		rl_printf("No default controller available\n");
+		bt_shell_printf("No default controller available\n");
 		return FALSE;
 	}
 
@@ -184,60 +178,19 @@ static gboolean check_default_ctrl(void)
 
 static void proxy_leak(gpointer data)
 {
-	rl_printf("Leaking proxy %p\n", data);
-}
-
-static gboolean input_handler(GIOChannel *channel, GIOCondition condition,
-							gpointer user_data)
-{
-	if (condition & G_IO_IN) {
-		rl_callback_read_char();
-		return TRUE;
-	}
-
-	if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
-		g_main_loop_quit(main_loop);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static guint setup_standard_input(void)
-{
-	GIOChannel *channel;
-	guint source;
-
-	channel = g_io_channel_unix_new(fileno(stdin));
-
-	source = g_io_add_watch(channel,
-				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-				input_handler, NULL);
-
-	g_io_channel_unref(channel);
-
-	return source;
+	bt_shell_printf("Leaking proxy %p\n", data);
 }
 
 static void connect_handler(DBusConnection *connection, void *user_data)
 {
-	rl_set_prompt(PROMPT_ON);
-	rl_printf("\r");
-	rl_on_new_line();
-	rl_redisplay();
+	bt_shell_set_prompt(PROMPT_ON);
 }
 
 static void disconnect_handler(DBusConnection *connection, void *user_data)
 {
-	if (input > 0) {
-		g_source_remove(input);
-		input = 0;
-	}
+	bt_shell_detach();
 
-	rl_set_prompt(PROMPT_OFF);
-	rl_printf("\r");
-	rl_on_new_line();
-	rl_redisplay();
+	bt_shell_set_prompt(PROMPT_OFF);
 
 	g_list_free_full(ctrl_list, proxy_leak);
 	ctrl_list = NULL;
@@ -260,7 +213,7 @@ static void print_adapter(GDBusProxy *proxy, const char *description)
 	else
 		name = "<unknown>";
 
-	rl_printf("%s%s%sController %s %s %s\n",
+	bt_shell_printf("%s%s%sController %s %s %s\n",
 				description ? "[" : "",
 				description ? : "",
 				description ? "] " : "",
@@ -286,7 +239,7 @@ static void print_device(GDBusProxy *proxy, const char *description)
 	else
 		name = "<unknown>";
 
-	rl_printf("%s%s%sDevice %s %s\n",
+	bt_shell_printf("%s%s%sDevice %s %s\n",
 				description ? "[" : "",
 				description ? : "",
 				description ? "] " : "",
@@ -306,39 +259,39 @@ static void print_iter(const char *label, const char *name,
 	char *entry;
 
 	if (iter == NULL) {
-		rl_printf("%s%s is nil\n", label, name);
+		bt_shell_printf("%s%s is nil\n", label, name);
 		return;
 	}
 
 	switch (dbus_message_iter_get_arg_type(iter)) {
 	case DBUS_TYPE_INVALID:
-		rl_printf("%s%s is invalid\n", label, name);
+		bt_shell_printf("%s%s is invalid\n", label, name);
 		break;
 	case DBUS_TYPE_STRING:
 	case DBUS_TYPE_OBJECT_PATH:
 		dbus_message_iter_get_basic(iter, &valstr);
-		rl_printf("%s%s: %s\n", label, name, valstr);
+		bt_shell_printf("%s%s: %s\n", label, name, valstr);
 		break;
 	case DBUS_TYPE_BOOLEAN:
 		dbus_message_iter_get_basic(iter, &valbool);
-		rl_printf("%s%s: %s\n", label, name,
+		bt_shell_printf("%s%s: %s\n", label, name,
 					valbool == TRUE ? "yes" : "no");
 		break;
 	case DBUS_TYPE_UINT32:
 		dbus_message_iter_get_basic(iter, &valu32);
-		rl_printf("%s%s: 0x%06x\n", label, name, valu32);
+		bt_shell_printf("%s%s: 0x%06x\n", label, name, valu32);
 		break;
 	case DBUS_TYPE_UINT16:
 		dbus_message_iter_get_basic(iter, &valu16);
-		rl_printf("%s%s: 0x%04x\n", label, name, valu16);
+		bt_shell_printf("%s%s: 0x%04x\n", label, name, valu16);
 		break;
 	case DBUS_TYPE_INT16:
 		dbus_message_iter_get_basic(iter, &vals16);
-		rl_printf("%s%s: %d\n", label, name, vals16);
+		bt_shell_printf("%s%s: %d\n", label, name, vals16);
 		break;
 	case DBUS_TYPE_BYTE:
 		dbus_message_iter_get_basic(iter, &byte);
-		rl_printf("%s%s: 0x%02x\n", label, name, byte);
+		bt_shell_printf("%s%s: 0x%02x\n", label, name, byte);
 		break;
 	case DBUS_TYPE_VARIANT:
 		dbus_message_iter_recurse(iter, &subiter);
@@ -364,7 +317,7 @@ static void print_iter(const char *label, const char *name,
 		g_free(entry);
 		break;
 	default:
-		rl_printf("%s%s has unsupported type\n", label, name);
+		bt_shell_printf("%s%s has unsupported type\n", label, name);
 		break;
 	}
 }
@@ -405,14 +358,14 @@ static void print_prov_service(struct prov_svc_data *prov_data)
 	char txt_uuid[16 * 2 + 1];
 	int i;
 
-	rl_printf("%sMesh Provisioning Service (%s)\n", prefix,
+	bt_shell_printf("%sMesh Provisioning Service (%s)\n", prefix,
 							MESH_PROV_SVC_UUID);
 	for (i = 0; i < 16; ++i) {
 		sprintf(txt_uuid + (i * 2), "%2.2x", prov_data->dev_uuid[i]);
 	}
 
-	rl_printf("%s\tDevice UUID: %s\n", prefix, txt_uuid);
-	rl_printf("%s\tOOB: %4.4x\n", prefix, prov_data->oob);
+	bt_shell_printf("%s\tDevice UUID: %s\n", prefix, txt_uuid);
+	bt_shell_printf("%s\tOOB: %4.4x\n", prefix, prov_data->oob);
 
 }
 
@@ -440,7 +393,7 @@ static bool parse_mesh_service_data(const char *uuid, uint8_t *data, int len,
 	const char *prefix = "\t\t";
 
 	if (!(len == 9 && data[0] == 0x00) && !(len == 17 && data[0] == 0x01)) {
-		rl_printf("Unexpected mesh proxy service data length %d\n",
+		bt_shell_printf("Unexpected mesh proxy service data length %d\n",
 									len);
 		return false;
 	}
@@ -453,7 +406,7 @@ static bool parse_mesh_service_data(const char *uuid, uint8_t *data, int len,
 
 		if (IS_UNASSIGNED(connection.unicast)) {
 			/* This would be a bug */
-			rl_printf("Error: Searching identity with "
+			bt_shell_printf("Error: Searching identity with "
 							"unicast 0000\n");
 			return false;
 		}
@@ -467,9 +420,9 @@ static bool parse_mesh_service_data(const char *uuid, uint8_t *data, int len,
 			return false;
 
 		if (discovering) {
-			rl_printf("\n%sMesh Proxy Service (%s)\n", prefix,
+			bt_shell_printf("\n%sMesh Proxy Service (%s)\n", prefix,
 									uuid);
-			rl_printf("%sIdentity for node %4.4x\n", prefix,
+			bt_shell_printf("%sIdentity for node %4.4x\n", prefix,
 							connection.unicast);
 		}
 
@@ -480,9 +433,9 @@ static bool parse_mesh_service_data(const char *uuid, uint8_t *data, int len,
 			return false;
 
 		if (discovering) {
-			rl_printf("\n%sMesh Proxy Service (%s)\n", prefix,
+			bt_shell_printf("\n%sMesh Proxy Service (%s)\n", prefix,
 									uuid);
-			rl_printf("%sNetwork Beacon for net index %4.4x\n",
+			bt_shell_printf("%sNetwork Beacon for net index %4.4x\n",
 							prefix, net_idx);
 		}
 	}
@@ -590,10 +543,10 @@ static void print_uuids(GDBusProxy *proxy)
 				n = sizeof(str) - 1;
 			}
 
-			rl_printf("\tUUID: %s%*c(%s)\n",
+			bt_shell_printf("\tUUID: %s%*c(%s)\n",
 						str, 26 - n, ' ', uuid);
 		} else
-			rl_printf("\tUUID: %*c(%s)\n", 26, ' ', uuid);
+			bt_shell_printf("\tUUID: %*c(%s)\n", 26, ' ', uuid);
 
 		dbus_message_iter_next(&value);
 	}
@@ -666,14 +619,12 @@ static void set_connected_device(GDBusProxy *proxy)
 				mesh ? buf : "");
 
 done:
-	rl_set_prompt(desc ? desc : PROMPT_ON);
-	rl_printf("\r");
-	rl_on_new_line();
+	bt_shell_set_prompt(desc ? desc : PROMPT_ON);
 	g_free(desc);
 
 	/* If disconnected, return to main menu */
 	if (proxy == NULL)
-		cmd_menu_main(true);
+		bt_shell_set_menu(&main_menu);
 }
 
 static void connect_reply(DBusMessage *message, void *user_data)
@@ -684,13 +635,13 @@ static void connect_reply(DBusMessage *message, void *user_data)
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("Failed to connect: %s\n", error.name);
+		bt_shell_printf("Failed to connect: %s\n", error.name);
 		dbus_error_free(&error);
 		set_connected_device(NULL);
 		return;
 	}
 
-	rl_printf("Connection successful\n");
+	bt_shell_printf("Connection successful\n");
 
 	set_connected_device(proxy);
 }
@@ -757,10 +708,10 @@ static void update_device_info(GDBusProxy *proxy)
 						connect_reply, proxy, NULL);
 
 		if (!res)
-			rl_printf("Failed to connect to mesh\n");
+			bt_shell_printf("Failed to connect to mesh\n");
 
 		else
-			rl_printf("Trying to connect to mesh\n");
+			bt_shell_printf("Trying to connect to mesh\n");
 
 	}
 }
@@ -786,10 +737,10 @@ static void data_out_notify(GDBusProxy *proxy, bool enable,
 	node = node_find_by_uuid(connection.dev_uuid);
 
 	if (!mesh_gatt_notify(proxy, enable, cb, node))
-		rl_printf("Failed to %s notification on %s\n", enable ?
+		bt_shell_printf("Failed to %s notification on %s\n", enable ?
 				"start" : "stop", g_dbus_proxy_get_path(proxy));
 	else
-		rl_printf("%s notification on %s\n", enable ?
+		bt_shell_printf("%s notification on %s\n", enable ?
 			  "Start" : "Stop", g_dbus_proxy_get_path(proxy));
 }
 
@@ -810,14 +761,14 @@ static void disconnect(GDBusReturnFunction cb, void *user_data)
 
 	if (g_dbus_proxy_method_call(proxy, "Disconnect", NULL, cb, user_data,
 							NULL) == FALSE) {
-		rl_printf("Failed to disconnect\n");
+		bt_shell_printf("Failed to disconnect\n");
 		return;
 	}
 
 	if (g_dbus_proxy_get_property(proxy, "Address", &iter) == TRUE)
 			dbus_message_iter_get_basic(&iter, &addr);
 
-	rl_printf("Attempting to disconnect from %s\n", addr);
+	bt_shell_printf("Attempting to disconnect from %s\n", addr);
 }
 
 static void disc_notify_cb(DBusMessage *message, void *user_data)
@@ -863,49 +814,49 @@ static void notify_prov_out_cb(DBusMessage *message, void *user_data)
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("Failed to start notify: %s\n", error.name);
+		bt_shell_printf("Failed to start notify: %s\n", error.name);
 		dbus_error_free(&error);
 		return;
 	}
 
-	rl_printf("Notify for Mesh Provisioning Out Data started\n");
+	bt_shell_printf("Notify for Mesh Provisioning Out Data started\n");
 
 	if (connection.type != CONN_TYPE_PROVISION) {
-		rl_printf("Error: wrong connection type %d (expected %d)\n",
+		bt_shell_printf("Error: wrong connection type %d (expected %d)\n",
 			connection.type, CONN_TYPE_PROVISION);
 		return;
 	}
 
 	if (!connection.data_in) {
-		rl_printf("Error: don't have mesh provisioning data in\n");
+		bt_shell_printf("Error: don't have mesh provisioning data in\n");
 		return;
 	}
 
 	if (!node) {
-		rl_printf("Error: provisioning node not present\n");
+		bt_shell_printf("Error: provisioning node not present\n");
 		return;
 	}
 
 	if(!prov_open(node, connection.data_in, prov_net_key_index,
 			mesh_prov_done, node))
 	{
-		rl_printf("Failed to start provisioning\n");
+		bt_shell_printf("Failed to start provisioning\n");
 		node_free(node);
 		disconnect_device(NULL, NULL);
 	} else
-		rl_printf("Initiated provisioning\n");
+		bt_shell_printf("Initiated provisioning\n");
 
 }
 
 static void session_open_cb (int status)
 {
 	if (status) {
-		rl_printf("Failed to open Mesh session\n");
+		bt_shell_printf("Failed to open Mesh session\n");
 		disconnect_device(NULL, NULL);
 		return;
 	}
 
-	rl_printf("Mesh session is open\n");
+	bt_shell_printf("Mesh session is open\n");
 
 	/* Get composition data for a newly provisioned node */
 	if (connection.type == CONN_TYPE_IDENTITY)
@@ -919,27 +870,27 @@ static void notify_proxy_out_cb(DBusMessage *message, void *user_data)
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("Failed to start notify: %s\n", error.name);
+		bt_shell_printf("Failed to start notify: %s\n", error.name);
 		dbus_error_free(&error);
 		return;
 	}
 
-	rl_printf("Notify for Mesh Proxy Out Data started\n");
+	bt_shell_printf("Notify for Mesh Proxy Out Data started\n");
 
 	if (connection.type != CONN_TYPE_IDENTITY &&
 			connection.type != CONN_TYPE_NETWORK) {
-		rl_printf("Error: wrong connection type %d "
+		bt_shell_printf("Error: wrong connection type %d "
 				"(expected %d or %d)\n", connection.type,
 				CONN_TYPE_IDENTITY, CONN_TYPE_NETWORK);
 		return;
 	}
 
 	if (!connection.data_in) {
-		rl_printf("Error: don't have mesh proxy data in\n");
+		bt_shell_printf("Error: don't have mesh proxy data in\n");
 		return;
 	}
 
-	rl_printf("Trying to open mesh session\n");
+	bt_shell_printf("Trying to open mesh session\n");
 	net_session_open(connection.data_in, true, session_open_cb);
 	connection.session_open = true;
 }
@@ -964,14 +915,14 @@ static GDBusProxy *get_characteristic(GDBusProxy *device, const char *char_uuid)
 	if (l)
 		service = l->data;
 	else {
-		rl_printf("Mesh service not found\n");
+		bt_shell_printf("Mesh service not found\n");
 		return	NULL;
 	}
 
 	for (l = char_list; l; l = l->next) {
 		if (mesh_gatt_is_child(l->data, service, "Service") &&
 					char_is_mesh(l->data, char_uuid)) {
-			rl_printf("Found matching char: path %s, uuid %s\n",
+			bt_shell_printf("Found matching char: path %s, uuid %s\n",
 				g_dbus_proxy_get_path(l->data), char_uuid);
 			return l->data;
 		}
@@ -1013,7 +964,7 @@ static void mesh_session_setup(GDBusProxy *proxy)
 
 fail:
 
-	rl_printf("Services resolved, mesh characteristics not found\n");
+	bt_shell_printf("Services resolved, mesh characteristics not found\n");
 }
 
 static void proxy_added(GDBusProxy *proxy, void *user_data)
@@ -1032,13 +983,13 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
 	} else if (!strcmp(interface, "org.bluez.GattService1") &&
 						service_is_mesh(proxy, NULL)) {
 
-		rl_printf("Service added %s\n", g_dbus_proxy_get_path(proxy));
+		bt_shell_printf("Service added %s\n", g_dbus_proxy_get_path(proxy));
 		service_list = g_list_append(service_list, proxy);
 
 	} else if (!strcmp(interface, "org.bluez.GattCharacteristic1") &&
 						char_is_mesh(proxy, NULL)) {
 
-		rl_printf("Char added %s:\n", g_dbus_proxy_get_path(proxy));
+		bt_shell_printf("Char added %s:\n", g_dbus_proxy_get_path(proxy));
 
 		char_list = g_list_append(char_list, proxy);
 	}
@@ -1052,13 +1003,13 @@ static void start_discovery_reply(DBusMessage *message, void *user_data)
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("Failed to %s discovery: %s\n",
+		bt_shell_printf("Failed to %s discovery: %s\n",
 				enable == TRUE ? "start" : "stop", error.name);
 		dbus_error_free(&error);
 		return;
 	}
 
-	rl_printf("Discovery %s\n", enable == TRUE ? "started" : "stopped");
+	bt_shell_printf("Discovery %s\n", enable == TRUE ? "started" : "stopped");
 }
 
 static struct mesh_device *find_device_by_proxy(GList *source,
@@ -1210,7 +1161,7 @@ static bool process_mesh_characteristic(GDBusProxy *proxy)
 			node = node_find_by_uuid(connection.dev_uuid);
 
 			if (!node) {
-				rl_printf("Node not found?\n");
+				bt_shell_printf("Node not found?\n");
 				return false;
 			}
 
@@ -1256,7 +1207,7 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 
 				dbus_message_iter_get_basic(iter, &resolved);
 
-				rl_printf("Services resolved %s\n", resolved ?
+				bt_shell_printf("Services resolved %s\n", resolved ?
 								"yes" : "no");
 
 				if (resolved)
@@ -1268,7 +1219,7 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 		DBusMessageIter addr_iter;
 		char *str;
 
-		rl_printf("Adapter property changed \n");
+		bt_shell_printf("Adapter property changed \n");
 		if (g_dbus_proxy_get_property(proxy, "Address",
 						&addr_iter) == TRUE) {
 			const char *address;
@@ -1289,10 +1240,10 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 		print_iter(str, name, iter);
 		g_free(str);
 	} else if (!strcmp(interface, "org.bluez.GattService1")) {
-		rl_printf("Service property changed %s\n",
+		bt_shell_printf("Service property changed %s\n",
 						g_dbus_proxy_get_path(proxy));
 	} else if (!strcmp(interface, "org.bluez.GattCharacteristic1")) {
-		rl_printf("Characteristic property changed %s\n",
+		bt_shell_printf("Characteristic property changed %s\n",
 						g_dbus_proxy_get_path(proxy));
 
 		if ((strcmp(name, "Value") == 0) &&
@@ -1305,7 +1256,7 @@ static void property_changed(GDBusProxy *proxy, const char *name,
 static void message_handler(DBusConnection *connection,
 					DBusMessage *message, void *user_data)
 {
-	rl_printf("[SIGNAL] %s.%s\n", dbus_message_get_interface(message),
+	bt_shell_printf("[SIGNAL] %s.%s\n", dbus_message_get_interface(message),
 					dbus_message_get_member(message));
 }
 
@@ -1331,28 +1282,24 @@ static struct adapter *find_ctrl_by_address(GList *source, const char *address)
 	return NULL;
 }
 
-static gboolean parse_argument_on_off(const char *arg, dbus_bool_t *value)
+static gboolean parse_argument_on_off(int argc, char *argv[],
+					dbus_bool_t *value)
 {
-	if (!arg || !strlen(arg)) {
-		rl_printf("Missing on/off argument\n");
-		return FALSE;
-	}
-
-	if (!strcmp(arg, "on") || !strcmp(arg, "yes")) {
+	if (!strcmp(argv[1], "on") || !strcmp(argv[1], "yes")) {
 		*value = TRUE;
 		return TRUE;
 	}
 
-	if (!strcmp(arg, "off") || !strcmp(arg, "no")) {
+	if (!strcmp(argv[1], "off") || !strcmp(argv[1], "no")) {
 		*value = FALSE;
 		return TRUE;
 	}
 
-	rl_printf("Invalid argument %s\n", arg);
+	bt_shell_printf("Invalid argument %s\n", argv[1]);
 	return FALSE;
 }
 
-static void cmd_list(const char *arg)
+static void cmd_list(int argc, char *argv[])
 {
 	GList *list;
 
@@ -1362,7 +1309,7 @@ static void cmd_list(const char *arg)
 	}
 }
 
-static void cmd_show(const char *arg)
+static void cmd_show(int argc, char *argv[])
 {
 	struct adapter *adapter;
 	GDBusProxy *proxy;
@@ -1370,15 +1317,16 @@ static void cmd_show(const char *arg)
 	const char *address;
 
 
-	if (!arg || !strlen(arg)) {
+	if (argc < 2 || !strlen(argv[1])) {
 		if (check_default_ctrl() == FALSE)
 			return;
 
 		proxy = default_ctrl->proxy;
 	} else {
-		adapter = find_ctrl_by_address(ctrl_list, arg);
+		adapter = find_ctrl_by_address(ctrl_list, argv[1]);
 		if (!adapter) {
-			rl_printf("Controller %s not available\n", arg);
+			bt_shell_printf("Controller %s not available\n",
+								argv[1]);
 			return;
 		}
 		proxy = adapter->proxy;
@@ -1388,7 +1336,7 @@ static void cmd_show(const char *arg)
 		return;
 
 	dbus_message_iter_get_basic(&iter, &address);
-	rl_printf("Controller %s\n", address);
+	bt_shell_printf("Controller %s\n", address);
 
 	print_property(proxy, "Name");
 	print_property(proxy, "Alias");
@@ -1400,18 +1348,13 @@ static void cmd_show(const char *arg)
 	print_property(proxy, "Discovering");
 }
 
-static void cmd_select(const char *arg)
+static void cmd_select(int argc, char *argv[])
 {
 	struct adapter *adapter;
 
-	if (!arg || !strlen(arg)) {
-		rl_printf("Missing controller address argument\n");
-		return;
-	}
-
-	adapter = find_ctrl_by_address(ctrl_list, arg);
+	adapter = find_ctrl_by_address(ctrl_list, argv[1]);
 	if (!adapter) {
-		rl_printf("Controller %s not available\n", arg);
+		bt_shell_printf("Controller %s not available\n", argv[1]);
 		return;
 	}
 
@@ -1429,17 +1372,17 @@ static void generic_callback(const DBusError *error, void *user_data)
 	char *str = user_data;
 
 	if (dbus_error_is_set(error))
-		rl_printf("Failed to set %s: %s\n", str, error->name);
+		bt_shell_printf("Failed to set %s: %s\n", str, error->name);
 	else
-		rl_printf("Changing %s succeeded\n", str);
+		bt_shell_printf("Changing %s succeeded\n", str);
 }
 
-static void cmd_power(const char *arg)
+static void cmd_power(int argc, char *argv[])
 {
 	dbus_bool_t powered;
 	char *str;
 
-	if (parse_argument_on_off(arg, &powered) == FALSE)
+	if (parse_argument_on_off(argc, argv, &powered) == FALSE)
 		return;
 
 	if (check_default_ctrl() == FALSE)
@@ -1455,12 +1398,12 @@ static void cmd_power(const char *arg)
 	g_free(str);
 }
 
-static void cmd_scan(const char *arg)
+static void cmd_scan(int argc, char *argv[])
 {
 	dbus_bool_t enable;
 	const char *method;
 
-	if (parse_argument_on_off(arg, &enable) == FALSE)
+	if (parse_argument_on_off(argc, argv, &enable) == FALSE)
 		return;
 
 	if (check_default_ctrl() == FALSE)
@@ -1475,7 +1418,7 @@ static void cmd_scan(const char *arg)
 	if (g_dbus_proxy_method_call(default_ctrl->proxy, method,
 				NULL, start_discovery_reply,
 				GUINT_TO_POINTER(enable), NULL) == FALSE) {
-		rl_printf("Failed to %s discovery\n",
+		bt_shell_printf("Failed to %s discovery\n",
 					enable == TRUE ? "start" : "stop");
 		return;
 	}
@@ -1617,12 +1560,12 @@ static void set_discovery_filter_reply(DBusMessage *message, void *user_data)
 
 	dbus_error_init(&error);
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("SetDiscoveryFilter failed: %s\n", error.name);
+		bt_shell_printf("SetDiscoveryFilter failed: %s\n", error.name);
 		dbus_error_free(&error);
 		return;
 	}
 
-	rl_printf("SetDiscoveryFilter success\n");
+	bt_shell_printf("SetDiscoveryFilter success\n");
 }
 
 static gint filtered_scan_rssi = DISTANCE_VAL_INVALID;
@@ -1648,24 +1591,23 @@ static void set_scan_filter_commit(void)
 	if (g_dbus_proxy_method_call(default_ctrl->proxy, "SetDiscoveryFilter",
 		set_discovery_filter_setup, set_discovery_filter_reply,
 		&args, NULL) == FALSE) {
-		rl_printf("Failed to set discovery filter\n");
+		bt_shell_printf("Failed to set discovery filter\n");
 		return;
 	}
 }
 
-static void set_scan_filter_uuids(const char *arg)
+static void set_scan_filter_uuids(int argc, char *argv[])
 {
 	g_strfreev(filtered_scan_uuids);
 	filtered_scan_uuids = NULL;
 	filtered_scan_uuids_len = 0;
 
-	if (!arg || !strlen(arg))
+	if (!argc || !strlen(argv[0]))
 		goto commit;
 
-	rl_printf("set_scan_filter_uuids %s\n", arg);
-	filtered_scan_uuids = g_strsplit(arg, " ", -1);
+	filtered_scan_uuids = g_strdupv(argv);
 	if (!filtered_scan_uuids) {
-		rl_printf("Failed to parse input\n");
+		bt_shell_printf("Failed to parse input\n");
 		return;
 	}
 
@@ -1675,21 +1617,22 @@ commit:
 	set_scan_filter_commit();
 }
 
-static void cmd_scan_unprovisioned_devices(const char *arg)
+static void cmd_scan_unprovisioned_devices(int argc, char *argv[])
 {
 	dbus_bool_t enable;
+	char *filters[] = { MESH_PROV_SVC_UUID, NULL };
 
-	if (parse_argument_on_off(arg, &enable) == FALSE)
+	if (parse_argument_on_off(argc, argv, &enable) == FALSE)
 		return;
 
 	if (enable == TRUE) {
 		discover_mesh = false;
-		set_scan_filter_uuids(MESH_PROV_SVC_UUID);
+		set_scan_filter_uuids(1, filters);
 	}
-	cmd_scan(arg);
+	cmd_scan(argc, argv);
 }
 
-static void cmd_info(const char *arg)
+static void cmd_info(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
 	DBusMessageIter iter;
@@ -1703,7 +1646,7 @@ static void cmd_info(const char *arg)
 		return;
 
 	dbus_message_iter_get_basic(&iter, &address);
-	rl_printf("Device %s\n", address);
+	bt_shell_printf("Device %s\n", address);
 
 	print_property(proxy, "Name");
 	print_property(proxy, "Alias");
@@ -1735,71 +1678,67 @@ static const char *security2str(uint8_t level)
 	}
 }
 
-static void cmd_security(const char *arg)
+static void cmd_security(int argc, char *argv[])
 {
 	uint8_t level;
 	char *end;
 
-	if (!arg || arg[0] == '\0') {
-		level = prov_get_sec_level();
-		goto done;
-	}
-
-	level = strtol(arg, &end, 10);
-	if (end == arg || !prov_set_sec_level(level)) {
-		rl_printf("Invalid security level %s\n", arg);
+	level = strtol(argv[1], &end, 10);
+	if (end == argv[1] || !prov_set_sec_level(level)) {
+		bt_shell_printf("Invalid security level %s\n", argv[1]);
 		return;
 	}
 
-done:
-	rl_printf("Provision Security Level set to %u (%s)\n", level,
+	bt_shell_printf("Provision Security Level set to %u (%s)\n", level,
 						security2str(level));
 }
 
-static void cmd_connect(const char *arg)
+static void cmd_connect(int argc, char *argv[])
 {
+	char *filters[] = { MESH_PROXY_SVC_UUID, NULL };
+
 	if (check_default_ctrl() == FALSE)
 		return;
 
 	memset(&connection, 0, sizeof(connection));
 
-	if (!arg || !strlen(arg)) {
+	if (argc < 2 || !strlen(argv[1])) {
 		connection.net_idx = NET_IDX_PRIMARY;
 	} else {
 		char *end;
-		connection.net_idx = strtol(arg, &end, 16);
-		if (end == arg) {
+		connection.net_idx = strtol(argv[1], &end, 16);
+		if (end == argv[1]) {
 			connection.net_idx = NET_IDX_INVALID;
-			rl_printf("Invalid network index %s\n", arg);
+			bt_shell_printf("Invalid network index %s\n", argv[1]);
 			return;
 		}
 
-		connection.unicast = strtol(end, NULL, 16);
+		if (argc > 2)
+			connection.unicast = strtol(argv[2], NULL, 16);
 	}
 
 	if (discovering)
 		g_dbus_proxy_method_call(default_ctrl->proxy, "StopDiscovery",
 						NULL, NULL, NULL, NULL);
 
-	set_scan_filter_uuids(MESH_PROXY_SVC_UUID);
+	set_scan_filter_uuids(1, filters);
 	discover_mesh = true;
 
 	if (connection.unicast == UNASSIGNED_ADDRESS) {
 		connection.type = CONN_TYPE_NETWORK;
-		rl_printf("Looking for mesh network with net index %4.4x\n",
-				connection.net_idx);
+		bt_shell_printf("Looking for mesh network with net index "
+				"%4.4x\n", connection.net_idx);
 	} else {
 		connection.type = CONN_TYPE_IDENTITY;
-		rl_printf("Looking for node id %4.4x"
+		bt_shell_printf("Looking for node id %4.4x"
 				" on network with net index %4.4x\n",
 				connection.unicast, connection.net_idx);
 	}
 
-
 	if (g_dbus_proxy_method_call(default_ctrl->proxy,
 			"StartDiscovery", NULL, start_discovery_reply,
 				GUINT_TO_POINTER(TRUE), NULL) == FALSE)
-		rl_printf("Failed to start mesh proxy discovery\n");
+		bt_shell_printf("Failed to start mesh proxy discovery\n");
 
 	g_dbus_proxy_method_call(default_ctrl->proxy, "StartDiscovery",
 						NULL, NULL, NULL, NULL);
@@ -1809,19 +1748,20 @@ static void cmd_connect(const char *arg)
 static void prov_disconn_reply(DBusMessage *message, void *user_data)
 {
 	struct mesh_node *node = user_data;
+	char *filters[] = { MESH_PROXY_SVC_UUID, NULL };
 	DBusError error;
 
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("Failed to disconnect: %s\n", error.name);
+		bt_shell_printf("Failed to disconnect: %s\n", error.name);
 		dbus_error_free(&error);
 		return;
 	}
 
 	set_connected_device(NULL);
 
-	set_scan_filter_uuids(MESH_PROXY_SVC_UUID);
+	set_scan_filter_uuids(1, filters);
 	discover_mesh = true;
 
 	connection.type = CONN_TYPE_IDENTITY;
@@ -1832,7 +1772,7 @@ static void prov_disconn_reply(DBusMessage *message, void *user_data)
 	if (g_dbus_proxy_method_call(default_ctrl->proxy,
 			"StartDiscovery", NULL, start_discovery_reply,
 				GUINT_TO_POINTER(TRUE), NULL) == FALSE)
-		rl_printf("Failed to start mesh proxy discovery\n");
+		bt_shell_printf("Failed to start mesh proxy discovery\n");
 
 }
 
@@ -1844,12 +1784,12 @@ static void disconn_reply(DBusMessage *message, void *user_data)
 	dbus_error_init(&error);
 
 	if (dbus_set_error_from_message(&error, message) == TRUE) {
-		rl_printf("Failed to disconnect: %s\n", error.name);
+		bt_shell_printf("Failed to disconnect: %s\n", error.name);
 		dbus_error_free(&error);
 		return;
 	}
 
-	rl_printf("Successfully disconnected\n");
+	bt_shell_printf("Successfully disconnected\n");
 
 	if (proxy != connection.device)
 		return;
@@ -1857,7 +1797,7 @@ static void disconn_reply(DBusMessage *message, void *user_data)
 	set_connected_device(NULL);
 }
 
-static void cmd_disconn(const char *arg)
+static void cmd_disconn(int argc, char *argv[])
 {
 	if (connection.type == CONN_TYPE_PROVISION) {
 		struct mesh_node *node = node_find_by_uuid(connection.dev_uuid);
@@ -1873,53 +1813,49 @@ static void mesh_prov_done(void *user_data, int status)
 	struct mesh_node *node = user_data;
 
 	if (status){
-		rl_printf("Provisioning failed\n");
+		bt_shell_printf("Provisioning failed\n");
 		node_free(node);
 		disconnect_device(NULL, NULL);
 		return;
 	}
 
-	rl_printf("Provision success. Assigned Primary Unicast %4.4x\n",
+	bt_shell_printf("Provision success. Assigned Primary Unicast %4.4x\n",
 						node_get_primary(node));
 
 	if (!prov_db_add_new_node(node))
-		rl_printf("Failed to add node to provisioning DB\n");
+		bt_shell_printf("Failed to add node to provisioning DB\n");
 
 	disconnect_device(prov_disconn_reply, node);
 }
 
-static void cmd_start_prov(const char *arg)
+static void cmd_start_prov(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
 	struct mesh_device *dev;
 	struct mesh_node *node;
 	int len;
 
-	if (!arg) {
-		rl_printf("Mesh Device UUID is required\n");
-		return;
-	}
-
-	len = strlen(arg);
+	len = strlen(argv[1]);
 	if ( len > 32 || len % 2) {
-		rl_printf("Incorrect UUID size %d\n", len);
+		bt_shell_printf("Incorrect UUID size %d\n", len);
 	}
 
 	disconnect_device(NULL, NULL);
 
 	memset(connection.dev_uuid, 0, 16);
-	str2hex(arg, len, connection.dev_uuid, len/2);
+	str2hex(argv[1], len, connection.dev_uuid, len/2);
 
 	node = node_find_by_uuid(connection.dev_uuid);
 	if (!node) {
-		rl_printf("Device with UUID %s not found.\n", arg);
-		rl_printf("Stale services? Remove device and re-discover\n");
+		bt_shell_printf("Device with UUID %s not found.\n", argv[1]);
+		bt_shell_printf("Stale services? Remove device and "
+						"re-discover\n");
 		return;
 	}
 
 	/* TODO: add command to remove a node from mesh, i.e., "unprovision" */
 	if (node_is_provisioned(node)) {
-		rl_printf("Already provisioned with unicast %4.4x\n",
+		bt_shell_printf("Already provisioned with unicast %4.4x\n",
 				node_get_primary(node));
 		return;
 	}
@@ -1927,7 +1863,7 @@ static void cmd_start_prov(const char *arg)
 	dev = find_device_by_uuid(default_ctrl->mesh_devices,
 				  connection.dev_uuid);
 	if (!dev || !dev->proxy) {
-		rl_printf("Could not find device proxy\n");
+		bt_shell_printf("Could not find device proxy\n");
 		memset(connection.dev_uuid, 0, 16);
 		return;
 	}
@@ -1942,71 +1878,32 @@ static void cmd_start_prov(const char *arg)
 
 	if (g_dbus_proxy_method_call(proxy, "Connect", NULL, connect_reply,
 							proxy, NULL) == FALSE) {
-		rl_printf("Failed to connect ");
+		bt_shell_printf("Failed to connect ");
 		print_device(proxy, NULL);
 		return;
 	} else {
-		rl_printf("Trying to connect ");
+		bt_shell_printf("Trying to connect ");
 		print_device(proxy, NULL);
 	}
 
 }
 
-static void cmd_config(const char *arg)
-{
-	rl_printf("Switching to Mesh Client configuration menu\n");
-
-	if (!switch_cmd_menu("configure"))
-		return;
-
-	set_menu_prompt("config", NULL);
-
-	if (arg && strlen(arg))
-		config_set_node(arg);
-}
-
-static void cmd_onoff_cli(const char *arg)
-{
-	rl_printf("Switching to Mesh Generic ON OFF Client menu\n");
-
-	if (!switch_cmd_menu("onoff"))
-		return;
-
-	set_menu_prompt("on/off", NULL);
-
-	if (arg && strlen(arg))
-		onoff_set_node(arg);
-}
-
-static void cmd_print_mesh(const char *arg)
+static void cmd_print_mesh(int argc, char *argv[])
 {
 	if (!prov_db_show(mesh_prov_db_filename))
-		rl_printf("Unavailable\n");
+		bt_shell_printf("Unavailable\n");
 
 }
 
- static void cmd_print_local(const char *arg)
+ static void cmd_print_local(int argc, char *argv[])
 {
 	if (!prov_db_show(mesh_local_config_filename))
-		rl_printf("Unavailable\n");
-}
-
-static void disc_quit_cb(DBusMessage *message, void *user_data)
-{
-	g_main_loop_quit(main_loop);
+		bt_shell_printf("Unavailable\n");
 }
 
-static void cmd_quit(const char *arg)
-{
-	if (connection.device) {
-		disconnect_device(disc_quit_cb, NULL);
-		return;
-	}
-
-	g_main_loop_quit(main_loop);
-}
-
-static const struct menu_entry meshctl_cmd_table[] = {
+static const struct bt_shell_menu main_menu = {
+	.name = "main",
+	.entries = {
 	{ "list",         NULL,       cmd_list, "List available controllers"},
 	{ "show",         "[ctrl]",   cmd_show, "Controller information"},
 	{ "select",       "<ctrl>",   cmd_select, "Select default controller"},
@@ -2023,195 +1920,44 @@ static const struct menu_entry meshctl_cmd_table[] = {
 	{ "mesh-info",    NULL,       cmd_print_mesh,
 					"Mesh networkinfo (provisioner)" },
 	{ "local-info",    NULL,      cmd_print_local, "Local mesh node info" },
-	{ "configure",    "[dst]",    cmd_config, "Config client model menu"},
-	{ "onoff",        "[dst]",    cmd_onoff_cli,
-						"Generic On/Off model menu"},
-	{ "quit",         NULL,       cmd_quit, "Quit program" },
-	{ "exit",         NULL,       cmd_quit },
-	{ "help" },
-	{ }
+	{ } },
 };
 
-static void rl_handler(char *input)
-{
-	char *cmd, *arg;
-
-	if (!input) {
-		rl_insert_text("quit");
-		rl_redisplay();
-		rl_crlf();
-		g_main_loop_quit(main_loop);
-		return;
-	}
-
-	if (!strlen(input))
-		goto done;
-	else if (!strcmp(input, "q") || !strcmp(input, "quit")
-						|| !strcmp(input, "exit")) {
-		cmd_quit(NULL);
-		goto done;
-	}
-
-	if (!rl_release_prompt(input))
-		goto done;
-
-	add_history(input);
-
-	cmd = strtok_r(input, " \t\r\n", &arg);
-	if (!cmd)
-		goto done;
-
-	process_menu_cmd(cmd, arg);
-
-done:
-	free(input);
-}
-
-static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
-							gpointer user_data)
-{
-	static bool terminated = false;
-	struct signalfd_siginfo si;
-	ssize_t result;
-	int fd;
-
-	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
-		g_main_loop_quit(main_loop);
-		return FALSE;
-	}
-
-	fd = g_io_channel_unix_get_fd(channel);
-
-	result = read(fd, &si, sizeof(si));
-	if (result != sizeof(si))
-		return FALSE;
-
-	switch (si.ssi_signo) {
-	case SIGINT:
-		if (input) {
-			rl_replace_line("", 0);
-			rl_crlf();
-			rl_on_new_line();
-			rl_redisplay();
-			break;
-		}
-
-		/*
-		 * If input was not yet setup up that means signal was received
-		 * while daemon was not yet running. Since user is not able
-		 * to terminate client by CTRL-D or typing exit treat this as
-		 * exit and fall through.
-		 */
-
-		/* fall through */
-	case SIGTERM:
-		if (!terminated) {
-			rl_replace_line("", 0);
-			rl_crlf();
-			g_main_loop_quit(main_loop);
-		}
-
-		terminated = true;
-		break;
-	}
-
-	return TRUE;
-}
-
-static guint setup_signalfd(void)
-{
-	GIOChannel *channel;
-	guint source;
-	sigset_t mask;
-	int fd;
-
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGINT);
-	sigaddset(&mask, SIGTERM);
-
-	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
-		perror("Failed to set signal mask");
-		return 0;
-	}
-
-	fd = signalfd(-1, &mask, 0);
-	if (fd < 0) {
-		perror("Failed to create signal descriptor");
-		return 0;
-	}
-
-	channel = g_io_channel_unix_new(fd);
-
-	g_io_channel_set_close_on_unref(channel, TRUE);
-	g_io_channel_set_encoding(channel, NULL, NULL);
-	g_io_channel_set_buffered(channel, FALSE);
-
-	source = g_io_add_watch(channel,
-				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-				signal_handler, NULL);
-
-	g_io_channel_unref(channel);
-
-	return source;
-}
-
-static gboolean option_version = FALSE;
 static const char *mesh_config_dir;
 
 static GOptionEntry options[] = {
 	{ "config", 'c', 0, G_OPTION_ARG_STRING, &mesh_config_dir,
 			"Read local mesh config JSON files from <directory>" },
-	{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
-				"Show version information and exit" },
 	{ NULL },
 };
 
 static void client_ready(GDBusClient *client, void *user_data)
 {
-	if (!input)
-		input = setup_standard_input();
+	bt_shell_attach(fileno(stdin));
 }
 
 int main(int argc, char *argv[])
 {
-	GOptionContext *context;
-	GError *error = NULL;
 	GDBusClient *client;
-	guint signal;
 	int len;
 	int extra;
 
-	context = g_option_context_new(NULL);
-	g_option_context_add_main_entries(context, options, NULL);
-
-	if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
-		if (error != NULL) {
-			g_printerr("%s\n", error->message);
-			g_error_free(error);
-		} else
-			g_printerr("An unknown error occurred\n");
-		exit(1);
-	}
-
-	g_option_context_free(context);
-
-	if (option_version == TRUE) {
-		rl_printf("%s\n", VERSION);
-		exit(0);
-	}
+	bt_shell_init(&argc, &argv, options);
+	bt_shell_set_menu(&main_menu);
+	bt_shell_set_prompt(PROMPT_OFF);
 
 	if (!mesh_config_dir) {
-		rl_printf("Local config directory not provided.\n");
+		bt_shell_printf("Local config directory not provided.\n");
 		mesh_config_dir = "";
 	} else {
-		rl_printf("Reading prov_db.json and local_node.json from %s\n",
+		bt_shell_printf("Reading prov_db.json and local_node.json from %s\n",
 							mesh_config_dir);
 	}
 
 	len = strlen(mesh_config_dir);
 	if (len && mesh_config_dir[len - 1] != '/') {
 		extra = 1;
-		rl_printf("mesh_config_dir[%d] %s\n", len,
+		bt_shell_printf("mesh_config_dir[%d] %s\n", len,
 						&mesh_config_dir[len - 1]);
 	} else {
 		extra = 0;
@@ -2257,18 +2003,7 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
-	main_loop = g_main_loop_new(NULL, FALSE);
 	dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
-
-	setlinebuf(stdout);
-
-	rl_erase_empty_line = 1;
-	rl_callback_handler_install(NULL, rl_handler);
-
-	rl_set_prompt(PROMPT_OFF);
-	rl_redisplay();
-
-	signal = setup_signalfd();
 	client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
 
 	g_dbus_client_set_connect_watch(client, connect_handler, NULL);
@@ -2280,8 +2015,6 @@ int main(int argc, char *argv[])
 
 	g_dbus_client_set_ready_watch(client, client_ready, NULL);
 
-	cmd_menu_init(meshctl_cmd_table);
-
 	if (!config_client_init())
 		g_printerr("Failed to initialize mesh configuration client\n");
 
@@ -2291,18 +2024,11 @@ int main(int argc, char *argv[])
 	if (!onoff_client_init(PRIMARY_ELEMENT_IDX))
 		g_printerr("Failed to initialize mesh generic On/Off client\n");
 
-	g_main_loop_run(main_loop);
+	bt_shell_run();
 
 	g_dbus_client_unref(client);
-	g_source_remove(signal);
-	if (input > 0)
-		g_source_remove(input);
-
-	rl_message("");
-	rl_callback_handler_remove();
 
 	dbus_connection_unref(dbus_conn);
-	g_main_loop_unref(main_loop);
 
 	node_cleanup();
 
@@ -2310,7 +2036,5 @@ int main(int argc, char *argv[])
 	g_list_free(service_list);
 	g_list_free_full(ctrl_list, proxy_leak);
 
-	rl_release_prompt("");
-
 	return 0;
 }
diff --git a/mesh/net.c b/mesh/net.c
index 96e82fe1c..421dc6955 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -33,7 +33,7 @@
 #include <glib.h>
 
 #include "src/shared/util.h"
-#include "client/display.h"
+#include "src/shared/shell.h"
 
 #include "mesh/crypto.h"
 #include "mesh/gatt.h"
@@ -958,7 +958,7 @@ static void beacon_update(bool first, bool iv_update, uint32_t iv_index)
 
 	/* Enforcement of 96 hour and 192 hour IVU time windows */
 	if (iv_update && !net.iv_update) {
-		rl_printf("iv_upd_state = IV_UPD_UPDATING\n");
+		bt_shell_printf("iv_upd_state = IV_UPD_UPDATING\n");
 		net.iv_upd_state = IV_UPD_UPDATING;
 		/* TODO: Start timer to enforce IV Update parameters */
 	} else if (first) {
@@ -967,11 +967,11 @@ static void beacon_update(bool first, bool iv_update, uint32_t iv_index)
 		else
 			net.iv_upd_state = IV_UPD_NORMAL;
 
-		rl_printf("iv_upd_state = IV_UPD_%s\n",
+		bt_shell_printf("iv_upd_state = IV_UPD_%s\n",
 				iv_update ? "UPDATING" : "NORMAL");
 
 	} else if (iv_update && iv_index != net.iv_index) {
-		rl_printf("IV Update too soon -- Rejecting\n");
+		bt_shell_printf("IV Update too soon -- Rejecting\n");
 		return;
 	}
 
@@ -1060,7 +1060,7 @@ static bool process_beacon(uint8_t *data, uint8_t size)
 
 	if ((net.iv_index + IV_IDX_DIFF_RANGE < iv_index) ||
 			(iv_index < net.iv_index)) {
-		rl_printf("iv index outside range\n");
+		bt_shell_printf("iv index outside range\n");
 		return false;
 	}
 
@@ -1076,7 +1076,7 @@ static bool process_beacon(uint8_t *data, uint8_t size)
 
 	if (iv_update && (net.iv_upd_state > IV_UPD_UPDATING)) {
 		if (iv_index != net.iv_index) {
-			rl_printf("Update too soon -- Rejecting\n");
+			bt_shell_printf("Update too soon -- Rejecting\n");
 		}
 		/* Silently ignore old beacons */
 		return true;
@@ -1198,7 +1198,7 @@ static void send_pkt_cmplt(DBusMessage *message, void *user_data)
 		g_free(pkt);
 	} else {
 		/* This is a serious error, and probable memory leak */
-		rl_printf("ERR: send_pkt_cmplt %p not head of queue\n", pkt);
+		bt_shell_printf("ERR: send_pkt_cmplt %p not head of queue\n", pkt);
 	}
 
 	l = g_list_first(net.pkt_out);
@@ -1381,7 +1381,7 @@ static bool proxy_ctl_rxed(uint16_t net_idx, uint32_t iv_index,
 				return false;
 
 			net.blacklist = !!(trans[1] == BLACKLIST_FILTER);
-			rl_printf("Proxy %slist filter length: %d\n",
+			bt_shell_printf("Proxy %slist filter length: %d\n",
 					net.blacklist ? "Black" : "White",
 					get_be16(trans + 2));
 
diff --git a/mesh/node.c b/mesh/node.c
index b906754ae..b682a35f7 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -34,12 +34,10 @@
 #include <wordexp.h>
 #include <inttypes.h>
 
-#include <readline/readline.h>
-#include <readline/history.h>
 #include <glib.h>
 
-#include "client/display.h"
 #include "src/shared/util.h"
+#include "src/shared/shell.h"
 #include "gdbus/gdbus.h"
 #include "monitor/uuid.h"
 #include "mesh/mesh-net.h"
@@ -450,7 +448,7 @@ bool node_parse_composition(struct mesh_node *node, uint8_t *data, uint16_t len)
 bool node_set_local_node(struct mesh_node *node)
 {
 	if (local_node) {
-		rl_printf("Local node already registered\n");
+		bt_shell_printf("Local node already registered\n");
 		return false;
 	}
 	net_register_unicast(node->primary, node->num_ele);
@@ -516,7 +514,7 @@ void node_local_data_handler(uint16_t src, uint32_t dst,
 
 	if (!remote) {
 		if (local_node->provisioner) {
-			rl_printf("Remote node unknown (%4.4x)\n", src);
+			bt_shell_printf("Remote node unknown (%4.4x)\n", src);
 			return;
 		}
 
@@ -538,7 +536,7 @@ void node_local_data_handler(uint16_t src, uint32_t dst,
 		iv_seq |= remote->seq_number;
 
 		if (iv_seq_remote >= iv_seq) {
-			rl_printf("Replayed message detected "
+			bt_shell_printf("Replayed message detected "
 					"(%016" PRIx64 " >= %016" PRIx64 ")\n",
 							iv_seq_remote, iv_seq);
 			return;
diff --git a/mesh/onoff-model.c b/mesh/onoff-model.c
index 676c14c78..9c8869414 100644
--- a/mesh/onoff-model.c
+++ b/mesh/onoff-model.c
@@ -38,7 +38,7 @@
 #include <readline/history.h>
 #include <glib.h>
 
-#include "client/display.h"
+#include "src/shared/shell.h"
 #include "src/shared/util.h"
 #include "mesh/mesh-net.h"
 #include "mesh/keys.h"
@@ -58,7 +58,7 @@ static int client_bind(uint16_t app_idx, int action)
 			return MESH_STATUS_INSUFF_RESOURCES;
 		} else {
 			onoff_app_idx = app_idx;
-			rl_printf("On/Off client model: new binding %4.4x\n",
+			bt_shell_printf("On/Off client model: new binding %4.4x\n",
 								app_idx);
 		}
 	} else {
@@ -101,7 +101,7 @@ static void print_remaining_time(uint8_t remaining_time)
 		break;
 	}
 
-	rl_printf("\n\t\tRemaining time: %d hrs %d mins %d secs %d msecs\n",
+	bt_shell_printf("\n\t\tRemaining time: %d hrs %d mins %d secs %d msecs\n",
 						hours, minutes, secs, msecs);
 
 }
@@ -118,7 +118,7 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 	} else
 		return false;
 
-	rl_printf("On Off Model Message received (%d) opcode %x\n",
+	bt_shell_printf("On Off Model Message received (%d) opcode %x\n",
 								len, opcode);
 	print_byte_array("\t",data, len);
 
@@ -130,14 +130,14 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 		if (len != 1 && len != 3)
 			break;
 
-		rl_printf("Node %4.4x: Off Status present = %s",
+		bt_shell_printf("Node %4.4x: Off Status present = %s",
 						src, data[0] ? "ON" : "OFF");
 
 		if (len == 3) {
-			rl_printf(", target = %s", data[1] ? "ON" : "OFF");
+			bt_shell_printf(", target = %s", data[1] ? "ON" : "OFF");
 			print_remaining_time(data[2]);
 		} else
-			rl_printf("\n");
+			bt_shell_printf("\n");
 		break;
 	}
 
@@ -148,44 +148,42 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
 static uint32_t target;
 static uint32_t parms[8];
 
-static uint32_t read_input_parameters(const char *args)
+static uint32_t read_input_parameters(int argc, char *argv[])
 {
 	uint32_t i;
 
-	if (!args)
+	--argc;
+	++argv;
+
+	if (!argc || argv[1][0] == '\0')
 		return 0;
 
 	memset(parms, 0xff, sizeof(parms));
 
-	for (i = 0; i < sizeof(parms)/sizeof(parms[0]); i++) {
-		int n;
-
-		sscanf(args, "%x", &parms[i]);
+	for (i = 0; i < sizeof(parms)/sizeof(parms[0]) && i < (unsigned) argc;
+									i++) {
+		sscanf(argv[i], "%x", &parms[i]);
 		if (parms[i] == 0xffffffff)
 			break;
-
-		n = strcspn(args, " \t");
-		args = args + n + strspn(args + n, " \t");
 	}
 
 	return i;
 }
 
-static void cmd_set_node(const char *args)
+static void cmd_set_node(int argc, char *argv[])
 {
 	uint32_t dst;
 	char *end;
 
-	dst = strtol(args, &end, 16);
-	if (end != (args + 4)) {
-		rl_printf("Bad unicast address %s: "
-						"expected format 4 digit hex\n",
-			args);
+	dst = strtol(argv[1], &end, 16);
+	if (end != (argv[1] + 4)) {
+		bt_shell_printf("Bad unicast address %s: "
+				"expected format 4 digit hex\n", argv[1]);
 		target = UNASSIGNED_ADDRESS;
 	} else {
-		rl_printf("Controlling ON/OFF for node %4.4x\n", dst);
+		bt_shell_printf("Controlling ON/OFF for node %4.4x\n", dst);
 		target = dst;
-		set_menu_prompt("on/off", args);
+		set_menu_prompt("on/off", argv[1]);
 	}
 }
 
@@ -203,14 +201,14 @@ static bool send_cmd(uint8_t *buf, uint16_t len)
 					target, onoff_app_idx, buf, len);
 }
 
-static void cmd_get_status(const char *args)
+static void cmd_get_status(int argc, char *argv[])
 {
 	uint16_t n;
 	uint8_t msg[32];
 	struct mesh_node *node;
 
 	if (IS_UNASSIGNED(target)) {
-		rl_printf("Destination not set\n");
+		bt_shell_printf("Destination not set\n");
 		return;
 	}
 
@@ -222,17 +220,17 @@ static void cmd_get_status(const char *args)
 	n = mesh_opcode_set(OP_GENERIC_ONOFF_GET, msg);
 
 	if (!send_cmd(msg, n))
-		rl_printf("Failed to send \"GENERIC ON/OFF GET\"\n");
+		bt_shell_printf("Failed to send \"GENERIC ON/OFF GET\"\n");
 }
 
-static void cmd_set(const char *args)
+static void cmd_set(int argc, char *argv[])
 {
 	uint16_t n;
 	uint8_t msg[32];
 	struct mesh_node *node;
 
 	if (IS_UNASSIGNED(target)) {
-		rl_printf("Destination not set\n");
+		bt_shell_printf("Destination not set\n");
 		return;
 	}
 
@@ -241,9 +239,9 @@ static void cmd_set(const char *args)
 	if (!node)
 		return;
 
-	if ((read_input_parameters(args) != 1) &&
+	if ((read_input_parameters(argc, argv) != 1) &&
 					parms[0] != 0 && parms[0] != 1) {
-		rl_printf("Bad arguments %s. Expecting \"0\" or \"1\"\n", args);
+		bt_shell_printf("Bad arguments: Expecting \"0\" or \"1\"\n");
 		return;
 	}
 
@@ -252,41 +250,22 @@ static void cmd_set(const char *args)
 	msg[n++] = trans_id++;
 
 	if (!send_cmd(msg, n))
-		rl_printf("Failed to send \"GENERIC ON/OFF SET\"\n");
+		bt_shell_printf("Failed to send \"GENERIC ON/OFF SET\"\n");
 
 }
 
-static void cmd_back(const char *args)
-{
-	cmd_menu_main(false);
-}
-
-static void cmd_help(const char *args);
-
-static const struct menu_entry cfg_menu[] = {
+static const struct bt_shell_menu onoff_menu = {
+	.name = "onoff",
+	.entries = {
 	{"target",		"<unicast>",			cmd_set_node,
 						"Set node to configure"},
 	{"get",			NULL,				cmd_get_status,
 						"Get ON/OFF status"},
 	{"onoff",		"<0/1>",			cmd_set,
 						"Send \"SET ON/OFF\" command"},
-	{"back",		NULL,				cmd_back,
-						"Back to main menu"},
-	{"help",		NULL,				cmd_help,
-						"Config Commands"},
-	{}
+	{} },
 };
 
-static void cmd_help(const char *args)
-{
-	rl_printf("Client Configuration Menu\n");
-	print_cmd_menu(cfg_menu);
-}
-
-void onoff_set_node(const char *args) {
-	cmd_set_node(args);
-}
-
 static struct mesh_model_ops client_cbs = {
 	client_msg_recvd,
 	client_bind,
@@ -300,7 +279,7 @@ bool onoff_client_init(uint8_t ele)
 					&client_cbs, NULL))
 		return false;
 
-	add_cmd_menu("onoff", cfg_menu);
+	bt_shell_add_submenu(&onoff_menu);
 
 	return true;
 }
diff --git a/mesh/prov-db.c b/mesh/prov-db.c
index 9add3f7c3..04803a5c8 100644
--- a/mesh/prov-db.c
+++ b/mesh/prov-db.c
@@ -37,11 +37,10 @@
 #include <json-c/json.h>
 #include <sys/stat.h>
 
-#include <readline/readline.h>
 #include <glib.h>
 
 #include "src/shared/util.h"
-#include "client/display.h"
+#include "src/shared/shell.h"
 
 #include "mesh/mesh-net.h"
 #include "mesh/crypto.h"
@@ -83,7 +82,7 @@ static char* prov_file_read(const char *filename)
 
 	sz = read(fd, str, st.st_size);
 	if (sz != st.st_size)
-		rl_printf("Incomplete read: %d vs %d\n", (int)sz,
+		bt_shell_printf("Incomplete read: %d vs %d\n", (int)sz,
 							(int)(st.st_size));
 
 	close(fd);
@@ -104,7 +103,7 @@ static void prov_file_write(json_object *jmain, bool local)
 
 	outfile = fopen(out_filename, "wr");
 	if (!outfile) {
-		rl_printf("Failed to open file %s for writing\n", out_filename);
+		bt_shell_printf("Failed to open file %s for writing\n", out_filename);
 		return;
 	}
 
@@ -577,10 +576,10 @@ void prov_db_print_node_composition(struct mesh_node *node)
 
 done:
 	if (res)
-		rl_printf("\tComposition data for node %4.4x %s\n",
+		bt_shell_printf("\tComposition data for node %4.4x %s\n",
 							primary, comp_str);
 	else
-		rl_printf("\tComposition data for node %4.4x not present\n",
+		bt_shell_printf("\tComposition data for node %4.4x not present\n",
 								primary);
 	g_free(in_str);
 
@@ -1380,7 +1379,7 @@ bool prov_db_show(const char *filename)
 	if (!str)
 		return false;
 
-	rl_printf("%s\n", str);
+	bt_shell_printf("%s\n", str);
 	g_free(str);
 	return true;
 }
@@ -1415,7 +1414,7 @@ static bool read_json_db(const char *filename, bool provisioner, bool local)
 
 		json_object_object_get_ex(jmain, "node", &jnode);
 		if (!jnode) {
-			rl_printf("Cannot find \"node\" object");
+			bt_shell_printf("Cannot find \"node\" object");
 			goto done;
 		} else
 			result = parse_node(jnode, true);
@@ -1451,7 +1450,7 @@ static bool read_json_db(const char *filename, bool provisioner, bool local)
 		goto done;
 
 	len = json_object_array_length(jarray);
-	rl_printf("# netkeys = %d\n", len);
+	bt_shell_printf("# netkeys = %d\n", len);
 
 	for (i = 0; i < len; ++i) {
 		uint32_t idx;
@@ -1489,7 +1488,7 @@ static bool read_json_db(const char *filename, bool provisioner, bool local)
 	json_object_object_get_ex(jmain, "appKeys", &jarray);
 	if (jarray) {
 		len = json_object_array_length(jarray);
-		rl_printf("# appkeys = %d\n", len);
+		bt_shell_printf("# appkeys = %d\n", len);
 
 		for (i = 0; i < len; ++i) {
 			int app_idx;
@@ -1536,7 +1535,7 @@ static bool read_json_db(const char *filename, bool provisioner, bool local)
 		goto done;
 
 	len = json_object_array_length(jarray);
-	rl_printf("# provisioners = %d\n", len);
+	bt_shell_printf("# provisioners = %d\n", len);
 
 	for (i = 0; i < len; ++i) {
 
@@ -1550,7 +1549,7 @@ static bool read_json_db(const char *filename, bool provisioner, bool local)
 		}
 
 		if (!parse_unicast_range(jtemp)) {
-			rl_printf("Doneed to parse unicast range\n");
+			bt_shell_printf("Doneed to parse unicast range\n");
 			goto done;
 		}
 	}
@@ -1563,7 +1562,7 @@ static bool read_json_db(const char *filename, bool provisioner, bool local)
 
 	len = json_object_array_length(jarray);
 
-	rl_printf("# provisioned nodes = %d\n", len);
+	bt_shell_printf("# provisioned nodes = %d\n", len);
 	for (i = 0; i < len; ++i) {
 		json_object *jnode;
 		jnode = json_object_array_get_idx(jarray, i);
diff --git a/mesh/prov.c b/mesh/prov.c
index a3333f7b6..1ff5cedbb 100644
--- a/mesh/prov.c
+++ b/mesh/prov.c
@@ -38,10 +38,10 @@
 
 #include "src/shared/util.h"
 #include "src/shared/ecc.h"
+#include "src/shared/shell.h"
 
 #include "gdbus/gdbus.h"
 #include "monitor/uuid.h"
-#include "client/display.h"
 #include "mesh/node.h"
 #include "mesh/gatt.h"
 #include "mesh/crypto.h"
@@ -178,9 +178,9 @@ bool prov_open(struct mesh_node *node, GDBusProxy *prov_in, uint16_t net_idx,
 	prov->conf_in.invite.attention = invite[2];
 	prov->state = PROV_INVITE;
 
-	rl_printf("Open-Node: %p\n", node);
-	rl_printf("Open-Prov: %p\n", prov);
-	rl_printf("Open-Prov: proxy %p\n", prov_in);
+	bt_shell_printf("Open-Node: %p\n", node);
+	bt_shell_printf("Open-Prov: %p\n", prov);
+	bt_shell_printf("Open-Prov: proxy %p\n", prov_in);
 
 	return mesh_gatt_write(prov_in, invite, sizeof(invite), NULL, node);
 }
@@ -380,7 +380,7 @@ static void prov_calc_ecdh(DBusMessage *message, void *node)
 						"Enter %s on device\n",
 						in_ascii);
 			}
-			rl_printf("Agent String: %s\n", in_oob_display);
+			bt_shell_printf("Agent String: %s\n", in_oob_display);
 			agent_output_request(in_oob_display);
 			break;
 	}
@@ -436,7 +436,7 @@ bool prov_data_ready(struct mesh_node *node, uint8_t *buf, uint8_t len)
 	buf++;
 	len--;
 
-	rl_printf("Got provisioning data (%d bytes)\n", len);
+	bt_shell_printf("Got provisioning data (%d bytes)\n", len);
 
 	if (buf[0] > PROV_FAILED || expected_pdu_size[buf[0]] != len)
 		return prov_complete(node, PROV_ERR_INVALID_PDU);
@@ -611,7 +611,7 @@ bool prov_data_ready(struct mesh_node *node, uint8_t *buf, uint8_t len)
 				return prov_complete(node,
 						PROV_ERR_INVALID_PDU);
 
-			rl_printf("Confirmation Validated\n");
+			bt_shell_printf("Confirmation Validated\n");
 
 			prov_send_prov_data(node);
 
@@ -630,7 +630,7 @@ bool prov_data_ready(struct mesh_node *node, uint8_t *buf, uint8_t len)
 	/* Compose appropriate reply for the prov state message */
 	/* Send reply via mesh_gatt_write() */
 	/* If done, call prov_done calllback and free prov housekeeping data */
-	rl_printf("Got provisioning data (%d bytes)\n", len);
+	bt_shell_printf("Got provisioning data (%d bytes)\n", len);
 	print_byte_array("\t", buf, len);
 
 	return true;
diff --git a/mesh/util.c b/mesh/util.c
index fac4bab1b..d38d87514 100644
--- a/mesh/util.c
+++ b/mesh/util.c
@@ -28,175 +28,23 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
-#include <readline/readline.h>
+
 #include <glib.h>
 
-#include "client/display.h"
+#include "src/shared/shell.h"
 #include "src/shared/util.h"
 #include "mesh/mesh-net.h"
 #include "mesh/node.h"
 #include "mesh/util.h"
 
-struct cmd_menu {
-	const char *name;
-	const struct menu_entry *table;
-};
-
-static struct menu_entry *main_cmd_table;
-static struct menu_entry *current_cmd_table;
-static GList *menu_list;
-
-static char *main_menu_prompt;
-static int main_menu_point;
-
-static int match_menu_name(const void *a, const void *b)
-{
-	const struct cmd_menu *menu = a;
-	const char *name = b;
-
-	return strcasecmp(menu->name, name);
-}
-
-bool cmd_menu_init(const struct menu_entry *cmd_table)
-{
-	struct cmd_menu *menu;
-
-	if (main_cmd_table) {
-		rl_printf("Main menu already registered\n");
-		return false;
-	}
-
-	menu = g_malloc(sizeof(struct cmd_menu));
-	if (!menu)
-		return false;
-
-	menu->name = "meshctl";
-	menu->table = cmd_table;
-	menu_list = g_list_append(menu_list, menu);
-	main_cmd_table = (struct menu_entry *) cmd_table;
-	current_cmd_table = (struct menu_entry *) main_cmd_table;
-
-	return true;
-}
-
-void cmd_menu_main(bool forced)
-{
-	current_cmd_table = main_cmd_table;
-
-	if (!forced) {
-		rl_set_prompt(main_menu_prompt);
-		rl_replace_line("", 0);
-		rl_point = main_menu_point;
-		rl_redisplay();
-	}
-
-	g_free(main_menu_prompt);
-	main_menu_prompt = NULL;
-}
-
-bool add_cmd_menu(const char *name, const struct menu_entry *cmd_table)
-{
-	struct cmd_menu *menu;
-	GList *l;
-
-	l = g_list_find_custom(menu_list, name, match_menu_name);
-	if (l) {
-		menu = l->data;
-		rl_printf("menu \"%s\" already registered\n", menu->name);
-		return false;
-	}
-
-	menu = g_malloc(sizeof(struct cmd_menu));
-	if (!menu)
-		return false;
-
-	menu->name = name;
-	menu->table = cmd_table;
-	menu_list = g_list_append(menu_list, menu);
-
-	return true;
-}
-
 void set_menu_prompt(const char *name, const char *id)
 {
 	char *prompt;
 
 	prompt = g_strdup_printf(COLOR_BLUE "[%s%s%s]" COLOR_OFF "# ", name,
 					id ? ": Target = " : "", id ? id : "");
-	rl_set_prompt(prompt);
+	bt_shell_set_prompt(prompt);
 	g_free(prompt);
-	rl_on_new_line();
-}
-
-bool switch_cmd_menu(const char *name)
-{
-	GList *l;
-	struct cmd_menu *menu;
-
-	l = g_list_find_custom(menu_list, name, match_menu_name);
-	if(!l)
-		return false;
-
-	menu = l->data;
-	current_cmd_table = (struct menu_entry *) menu->table;
-
-	main_menu_point = rl_point;
-	main_menu_prompt = g_strdup(rl_prompt);
-
-	return true;
-}
-
-void process_menu_cmd(const char *cmd, const char *arg)
-{
-	int i;
-	int len;
-	struct menu_entry *cmd_table = current_cmd_table;
-
-	if (!current_cmd_table)
-		return;
-
-	len = strlen(cmd);
-
-	for (i = 0; cmd_table[i].cmd; i++) {
-		if (strncmp(cmd, cmd_table[i].cmd, len))
-			continue;
-
-		if (cmd_table[i].func) {
-			cmd_table[i].func(arg);
-			return;
-		}
-	}
-
-	if (strncmp(cmd, "help", len)) {
-		rl_printf("Invalid command\n");
-		return;
-	}
-
-	print_cmd_menu(cmd_table);
-}
-
-void print_cmd_menu(const struct menu_entry *cmd_table)
-{
-	int i;
-
-	rl_printf("Available commands:\n");
-
-	for (i = 0; cmd_table[i].cmd; i++) {
-		if (cmd_table[i].desc)
-			rl_printf("  %s %-*s %s\n", cmd_table[i].cmd,
-					(int)(40 - strlen(cmd_table[i].cmd)),
-					cmd_table[i].arg ? : "",
-					cmd_table[i].desc ? : "");
-	}
-
-}
-
-void cmd_menu_cleanup(void)
-{
-	main_cmd_table = NULL;
-	current_cmd_table = NULL;
-
-	g_list_free_full(menu_list, g_free);
 }
 
 void print_byte_array(const char *prefix, const void *ptr, int len)
@@ -214,13 +62,13 @@ void print_byte_array(const char *prefix, const void *ptr, int len)
 		if ((i + 1) % 16) {
 			bytes += 3;
 		} else {
-			rl_printf("\r%s\n", line);
+			bt_shell_printf("\r%s\n", line);
 			bytes = line + strlen(prefix) + 1;
 		}
 	}
 
 	if (i % 16)
-		rl_printf("\r%s\n", line);
+		bt_shell_printf("\r%s\n", line);
 
 	g_free(line);
 }
@@ -272,7 +120,7 @@ uint16_t mesh_opcode_set(uint32_t opcode, uint8_t *buf)
 		put_be16(opcode, buf + 1);
 		return 3;
 	} else {
-		rl_printf("Illegal Opcode %x", opcode);
+		bt_shell_printf("Illegal Opcode %x", opcode);
 		return 0;
 	}
 }
@@ -310,7 +158,7 @@ bool mesh_opcode_get(const uint8_t *buf, uint16_t sz, uint32_t *opcode, int *n)
 		break;
 
 	default:
-		rl_printf("Bad Packet:\n");
+		bt_shell_printf("Bad Packet:\n");
 		print_byte_array("\t", (void *) buf, sz);
 		return false;
 	}
@@ -347,14 +195,15 @@ const char *mesh_status_str(uint8_t status)
 void print_model_pub(uint16_t ele_addr, uint32_t mod_id,
 						struct mesh_publication *pub)
 {
-	rl_printf("\tElement: %4.4x\n", ele_addr);
-	rl_printf("\tPub Addr: %4.4x", pub->u.addr16);
+	bt_shell_printf("\tElement: %4.4x\n", ele_addr);
+	bt_shell_printf("\tPub Addr: %4.4x", pub->u.addr16);
 	if (mod_id > 0xffff0000)
-		rl_printf("\tModel: %8.8x \n", mod_id);
+		bt_shell_printf("\tModel: %8.8x \n", mod_id);
 	else
-		rl_printf("\tModel: %4.4x \n", (uint16_t) (mod_id & 0xffff));
-	rl_printf("\tApp Key Idx: %4.4x", pub->app_idx);
-	rl_printf("\tTTL: %2.2x", pub->ttl);
+		bt_shell_printf("\tModel: %4.4x \n",
+				(uint16_t) (mod_id & 0xffff));
+	bt_shell_printf("\tApp Key Idx: %4.4x", pub->app_idx);
+	bt_shell_printf("\tTTL: %2.2x", pub->ttl);
 }
 
 void swap_u256_bytes(uint8_t *u256)
diff --git a/mesh/util.h b/mesh/util.h
index 7f729ab62..c3facfa73 100644
--- a/mesh/util.h
+++ b/mesh/util.h
@@ -27,21 +27,7 @@ struct mesh_publication;
 
 #define OP_UNRELIABLE			0x0100
 
-struct menu_entry {
-	const char *cmd;
-	const char *arg;
-	void (*func) (const char *arg);
-	const char *desc;
-};
-
-bool cmd_menu_init(const struct menu_entry *cmd_table);
-void cmd_menu_main(bool forced);
-bool add_cmd_menu(const char *name, const struct menu_entry *cmd_table);
-bool switch_cmd_menu(const char *name);
-void set_menu_prompt(const char *prefix, const char * node);
-void process_menu_cmd(const char *cmd, const char *arg);
-void print_cmd_menu(const struct menu_entry *cmd_table);
-void cmd_menu_cleanup(void);
+void set_menu_prompt(const char *name, const char *id);
 void print_byte_array(const char *prefix, const void *ptr, int len);
 bool str2hex(const char *str, uint16_t in_len, uint8_t *out_buf,
 		uint16_t out_len);
-- 
2.13.6

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux