make telnet interface use VTY code

diff --git a/src/Makefile.am b/src/Makefile.am
index 3847af3..b9e9427 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,14 +6,14 @@
 
 libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_04_08.c gsm_data.c \
 		gsm_subscriber.c msgb.c select.c chan_alloc.c timer.c debug.c db.c \
-		gsm_04_11.c telnet_interface.c telnet_parser.l subchan_demux.c \
+		gsm_04_11.c telnet_interface.c subchan_demux.c \
 		trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \
 		input/misdn.c input/ipaccess.c signal.c gsm_utils.c
 
 libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
 
-bsc_hack_SOURCES = bsc_hack.c
-bsc_hack_LDADD = libbsc.a -ldl -ldbi
+bsc_hack_SOURCES = bsc_hack.c vty_interface.c
+bsc_hack_LDADD = libbsc.a libvty.a -ldl -ldbi -lcrypt
 
 bs11_config_SOURCES = bs11_config.c abis_nm.c gsm_data.c msgb.c debug.c select.c timer.c rs232.c tlv_parser.c
 
diff --git a/src/telnet_interface.c b/src/telnet_interface.c
index 3d3ed76..422af3b 100644
--- a/src/telnet_interface.c
+++ b/src/telnet_interface.c
@@ -35,8 +35,6 @@
 #include <openbsc/paging.h>
 #include <openbsc/signal.h>
 
-extern void telnet_parse(struct telnet_connection *connection, char *line);
-
 #define WRITE_CONNECTION(fd, msg...) \
 	int ret; \
 	char buf[4096]; \
@@ -64,6 +62,8 @@
 	struct sockaddr_in sock_addr;
 	int fd, on = 1;
 
+	bsc_vty_init(network);
+
 	fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 
 	if (fd < 0) {
@@ -93,26 +93,10 @@
 	bsc_register_fd(&server_socket);
 
 	/* register callbacks */
+#if 0
 	register_signal_handler(SS_PAGING, telnet_paging_callback, network);
 	register_signal_handler(SS_SMS, telnet_sms_callback, network);
-}
-
-void telnet_write_help(int fd) {
-	int ret;
-	static char *msg =
-		"Help for the ad-hoc telnet command line interface\n"
-		"The generic pattern is CMD LEN DATA\\n or just CMD\n"
-		"where CMD is one of the following:\n"
-		"help\n"
-		"page IMSI (type)\n"
-		"call IMSI (number)\n"
-		"get_channel IMSI Add use count on an active channel\n"
-		"put_channel IMSI Remove use count on an active channel\n"
-		"show  This will show the channel allocation\n"
-		"48 IMSI 0xAB 0xEF...Send GSM 04.08. proto and msg byte then data\n"
-		"11 IMSI 0xAB 0xEF...Send GSM 04.11\n";
-
-	ret = write(fd, msg, strlen(msg));
+#endif
 }
 
 static void print_welcome(int fd) {
@@ -142,200 +126,10 @@
 	return 0;
 }
 
-void telnet_error_client(int fd) {
-	int ret;
-	static char *msg = "Something went wrong. Please try again.\n";
-
-	printf("Error\n");
-	ret = write(fd, msg, strlen(msg));
-}
-
-static struct gsm_lchan* find_channel(struct gsm_bts *bts, const char *imsi,
-			    const char **error, int fd) {
-	int ret;
-	struct gsm_lchan *lchan;
-	struct gsm_subscriber *subscr;
-
-	subscr = subscr_get_by_imsi(imsi);
-	if (!subscr) {
-		ret = write(fd, error[0], strlen(error[0]));
-		return NULL;
-	}
-
-	lchan = lchan_find(bts, subscr);
-	if (!lchan)
-		ret = write(fd, error[1], strlen(error[1]));
-
-	subscr_put(subscr);
-	return lchan;
-}
-
-void telnet_page(struct telnet_connection *connection, const char *imsi, int type) {
-	int ret;
-	static const char* error[] = {
-		"paging: IMSI not found\n",
-		"paging: No channel allocated for IMSI -> will allocate\n" };
-	struct gsm_bts *bts = &connection->network->bts[connection->bts];
-	struct gsm_lchan *lchan = find_channel(bts, imsi, error, connection->fd.fd);
-
-	if (lchan) {
-		static const char *msg = "paging: A Channel is already allocated.\n";
-		ret = write(connection->fd.fd, msg, strlen(msg));
-		return;
-	}
-
-	struct gsm_subscriber *subscr = subscr_get_by_imsi(imsi);
-	if (!subscr)
-		return;
-
-	paging_request(bts, subscr, type, NULL, NULL);	
-}
-
-void telnet_put_channel(struct telnet_connection *connection, const char *imsi) {
-	static const char* error[] = {
-		"put_channel: IMSI not found\n",
-		"put_channel: No channel allocated for IMSI\n" };
-	struct gsm_bts *bts = &connection->network->bts[connection->bts];
-	struct gsm_lchan *lchan = find_channel(bts, imsi, error, connection->fd.fd);
-
-	if (!lchan)
-		return;
-
-	put_lchan(lchan);
-}
-
-void telnet_get_channel(struct telnet_connection *connection, const char *imsi) {
-	static const char* error[] = {
-		"get_channel: IMSI not found\n",
-		"get_channel: No channel allocated for IMSI\n" };
-	struct gsm_bts *bts = &connection->network->bts[connection->bts];
-	struct gsm_lchan *lchan = find_channel(bts, imsi, error, connection->fd.fd);
-
-	if (!lchan)
-		return;
-
-	use_lchan(lchan);
-}
-
-void telnet_call(struct telnet_connection *connection, const char* imsi,
-		const char *origin) {
-	static const char* error[] = {
-		"call: IMSI not found\n",
-		"call: No channel allocated for IMSI\n" };
-	struct gsm_bts *bts = &connection->network->bts[connection->bts];
-	struct gsm_lchan *lchan = find_channel(bts, imsi, error, connection->fd.fd);
-
-	if (!lchan)
-		return;
-
-	/* TODO: add the origin */
-	gsm48_cc_tx_setup(lchan, NULL);
-}
-
-void telnet_send_gsm_48(struct telnet_connection *connection) {
-	static const char* error[] = {
-		"48: IMSI not found\n",
-		"48: No channel allocated for IMSI\n" };
-	int ret;
-	struct gsm_bts *bts = &connection->network->bts[connection->bts];
-	struct gsm_lchan *lchan = find_channel(bts, connection->imsi, error, connection->fd.fd);
-
-	if (!lchan)
-		return;
-
-	if (connection->read < 2) {
-		static const char *msg = "48: Need at least two bytes";
-		ret = write(connection->fd.fd, msg, strlen(msg));
-		return;
-	}
-
-	struct msgb *msg = gsm48_msgb_alloc();
-	struct gsm48_hdr *gh;
-	int i;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + connection->read-2);
-	msg->lchan = lchan;
-
-	gh->proto_discr = connection->commands[0];
-	gh->msg_type = connection->commands[1];
-	for (i = 2; i < connection->read; ++i)
-	    gh->data[i-2] = connection->commands[i];
-
-	gsm48_sendmsg(msg);
-}
-
-void telnet_send_gsm_11(struct telnet_connection *connection) {
-	printf("sending gsm04.11 message\n");
-}
-
-static void show_bts(int fd, struct gsm_bts *bts) {
-	WRITE_CONNECTION(fd,
-		 "BTS #%u on link %u  LOC: %u TRX: %d CCCH0: arfcn:%u,#%u\n",
-		 bts->nr, bts->bts_nr, bts->location_area_code,
-		 bts->num_trx, bts->c0->arfcn, bts->c0->nr)
-}
-
-static void show_trx(int fd, struct gsm_bts_trx *trx) {
-	WRITE_CONNECTION(fd,
-		 "  TRX: %u ARFCN: %u\n",
-		trx->nr, trx->arfcn)
-}
-
-static void show_ts(int fd, struct gsm_bts_trx_ts *ts) {
-	WRITE_CONNECTION(fd,
-		"     TS: #%u pchan: %12s flags: %u\n",
-		ts->nr, gsm_pchan_name(ts->pchan), ts->flags);
-}
-
-static void show_lchan(int fd, struct gsm_lchan *lchan) {
-	struct gsm_subscriber *subscr = lchan->subscr;
-	WRITE_CONNECTION(fd,
-		"       LCHAN: #%u type: %7s  count: %d subscriber: %s/%s/%s use: %d loc: %p\n",
-		lchan->nr, gsm_lchan_name(lchan->type),
-		lchan->use_count,
-		subscr ? subscr->imsi : "na",
-		subscr ? subscr->tmsi : "na",
-		subscr ? subscr->name : "na",
-		lchan->use_count, lchan->loc_operation);
-}
-
-void telnet_list_channels(struct telnet_connection *connection) {
-	int bts_no, trx, lchan_no, ts_no;
-	struct gsm_network *network = connection->network;
-
-	for (bts_no = 0; bts_no < network->num_bts; ++bts_no) {
-		struct gsm_bts *bts = &network->bts[bts_no];
-		show_bts(connection->fd.fd, bts);
-
-		for (trx = 0; trx < bts->num_trx; ++trx) {
-			show_trx(connection->fd.fd, &bts->trx[trx]);
-			for (ts_no = 0; ts_no < 8; ++ts_no) {
-				show_ts(connection->fd.fd, &bts->trx[trx].ts[ts_no]);
-				for (lchan_no = 0; lchan_no < TS_MAX_LCHAN; ++lchan_no) {
-					struct gsm_lchan *lchan =
-						&bts->trx[trx].ts[ts_no].lchan[lchan_no];
-					show_lchan(connection->fd.fd, lchan);
-				}
-			}
-		}
-	}
-}
-
-static int client_data(struct bsc_fd *fd, unsigned int what) {
-	char buf[4096];
-	int ret;
-
-	ret = read(fd->fd, buf, sizeof(buf)-1);
-	buf[ret] = '\0';
-
-	/* connection is gone */
-	if (ret <= 0)
-		return telnet_close_client(fd);
-
-	/* time to parse. This code assumes that the input is line based */
-	telnet_parse((struct telnet_connection*)fd->data, buf);
-
-	return 0;
+static int client_data(struct bsc_fd *fd, unsigned int what)
+{
+	struct telnet_connection *conn = fd->data;
+	return vty_read(conn->vty);
 }
 
 static int telnet_new_connection(struct bsc_fd *fd, unsigned int what) {
@@ -363,9 +157,14 @@
 
 	print_welcome(new_connection);
 
+	connection->vty = vty_create(new_connection);
+	if (!connection->vty)
+		return -1;
+
 	return 0;
 }
 
+#if 0
 static int telnet_paging_callback(unsigned int subsys, unsigned int singal,
 				  void *handler_data, void *signal_data)
 {
@@ -399,3 +198,4 @@
 
 	return 0;
 }
+#endif
diff --git a/src/telnet_parser.l b/src/telnet_parser.l
deleted file mode 100644
index e432719..0000000
--- a/src/telnet_parser.l
+++ /dev/null
@@ -1,190 +0,0 @@
-/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/*
- * I'm lazy and will not introduce lemon to this game. Our telnet
- * interface is matching line based so we can have a pattern that
- * is matching a line and everyone will be happy.
- */
-
-%option never-interactive
-%option noyywrap
-%option	reentrant
-
-%{
-#include <string.h>
-#include <openbsc/telnet_interface.h>
-
-extern char *strndup(const char *s, size_t n);
-extern void telnet_write_help(int);
-extern void telnet_close_client(struct bsc_fd*);
-extern void telnet_error_client(int fd);
-extern void telnet_page(struct telnet_connection *con, const char *imsi, int page);
-extern void telnet_call(struct telnet_connection *con, const char *imsi,
-			const char* origin);
-extern void telnet_put_channel(struct telnet_connection*, const char *imsi);
-extern void telnet_get_channel(struct telnet_connection*, const char *imsi);
-extern void telnet_send_gsm_48(struct telnet_connection*);
-extern void telnet_send_gsm_11(struct telnet_connection*);
-extern void telnet_list_channels(struct telnet_connection*);
-
-static const int PAGE_LEN = 5; /* "page " */
-static const int CALL_LEN = 5; /* "call " */
-static const int PUT_LEN = 12; /* "put_channel " */
-static const int GET_LEN = 12; /* "get_channel " */
-static const int NET_LEN = 3;  /* "48 " "11 " */
-static const int SHOW_LEN = 5; /* "show " */
-
-#define YY_EXTRA_TYPE struct telnet_connection*
-
-/* the string is null terminated */
-static int parse_hex(char *hex)
-{
-	int byte;
-	sscanf(hex, "%x", &byte);
-	return byte;
-}
-
-#define PREPARE_STRING(len) \
-		yytext[yyleng-1] = '\0'; \
-                char *str = yytext + len; \
-		char *pag = strstr(str, "\r"); \
-		if (pag) pag[0] = '\0'; \
-		pag = strstr(str, "\n"); \
-		if (pag) pag[0] = '\0';
-
-%}
-
-CMD_HELP	"help"
-CMD_EXIT	"exit"
-CMD_CLOSE	"close"
-CMD_PAGE	"page"
-CMD_GET_CHANNEL	"get_channel"
-CMD_PUT_CHANNEL "put_channel"
-CMD_CALL	"call"
-CMD_48		"48"
-CMD_11		"11"
-CMD_SHOW	"show"
-
-LINE_END	\n|\r\n
-HEX		[0][x][0-9a-zA-Z][0-9a-zA-Z]
-
-%s  READ_HEX_BYTES
-
-%%
-{CMD_HELP}{LINE_END}		{telnet_write_help(yyextra->fd.fd); yyterminate();}
-{CMD_EXIT}{LINE_END}		{telnet_close_client(&yyextra->fd); yyterminate();}
-{CMD_CLOSE}{LINE_END}		{telnet_close_client(&yyextra->fd); yyterminate();}
-{CMD_SHOW}{LINE_END}		{telnet_list_channels(yyextra); yyterminate();}
-{CMD_PAGE}[ ][0-9]+{LINE_END} {
-				    PREPARE_STRING(PAGE_LEN)
-                                    telnet_page(yyextra, str, 0);
-				    yyterminate();
-				}
-{CMD_PAGE}[ ][0-9]+[ ][0-2]{LINE_END} {
-				    PREPARE_STRING(PAGE_LEN)
-				    char *sp = strstr(str, " ");
-				    sp[0] = '\0';
-                                    telnet_page(yyextra, str, atoi(sp+1));
-				    yyterminate();
-				}
-{CMD_PUT_CHANNEL}[ ][0-9]+{LINE_END} {
-				    PREPARE_STRING(PUT_LEN)
-                                    telnet_put_channel(yyextra, str);
-				    yyterminate();
-				}
-{CMD_GET_CHANNEL}[ ][0-9]+{LINE_END} {
-				    PREPARE_STRING(GET_LEN)
-                                    telnet_get_channel(yyextra, str);
-				    yyterminate();
-				}
-{CMD_CALL}[ ][0-9]+[ ][0-9]+{LINE_END} {
-				    PREPARE_STRING(CALL_LEN)
-				    char *sp = strstr(str, " ");
-				    sp[0] = '\0';
-                                    telnet_call(yyextra, str, sp+1);
-				    yyterminate();
-				}
-{CMD_CALL}[ ][0-9]+{LINE_END} {
-				    PREPARE_STRING(CALL_LEN)
-                                    telnet_call(yyextra, str, NULL);
-				    yyterminate();
-				}
-<READ_HEX_BYTES>{HEX}		{
-				    if (yyextra->read >= sizeof(yyextra->commands)) {
-					yyterminate();
-				    }
-				    yytext[yyleng] = '\0';
-				    yyextra->commands[yyextra->read++] = parse_hex(yytext+2);
-				}
-<READ_HEX_BYTES>{LINE_END}	{
-				    if (yyextra->command == TELNET_COMMAND_11) {
-					telnet_send_gsm_11(yyextra);
-				    } else if (yyextra->command == TELNET_COMMAND_48) {
-					telnet_send_gsm_48(yyextra);
-				    }
-
-				    if (yyextra->imsi) {
-					free(yyextra->imsi);
-					yyextra->imsi = NULL;
-				    }
-				    yyterminate();
-				}
-<INITIAL>{CMD_48}[ ][0-9]+	{
-				    BEGIN READ_HEX_BYTES;
-				    yyextra->read = 0;
-				    yyextra->command = TELNET_COMMAND_48;
-				    yytext[yyleng-1] = '\0';
-				    yyextra->imsi = strdup(yytext);
-				}
-
-<INITIAL>{CMD_11}[ ][0-9]+	{
-				    BEGIN READ_HEX_BYTES;
-				    yyextra->read = 0;
-				    yyextra->command = TELNET_COMMAND_11;
-				    yytext[yyleng-1] = '\0';
-				    yyextra->imsi = strdup(yytext);
-				}
-
-
-
-[ \t\r\n]			/* Ommit */
-.				{ telnet_error_client(yyextra->fd.fd); yyterminate(); }
-
-%%
-
-void telnet_parse(struct telnet_connection *conn, char *buf)
-{
-	yyscan_t scanner;
-	yylex_init(&scanner);
-	yyset_extra(conn, scanner);
-	yy_scan_string(buf, scanner);
-	yylex(scanner);
-	yylex_destroy(scanner);
-
-	if (conn->imsi) {
-		free(conn->imsi);
-		conn->imsi = NULL;
-	}
-}
-
-__attribute__((unused)) void telnet_unused(void)
-{
-	yyunput(0, 0, 0);
-	input(0);
-}