[layer23] Removed cloned VTY and replaced it by libosmovty.
authorAndreas.Eversberg <jolly@eversberg.eu>
Sat, 26 Jun 2010 14:00:29 +0000 (14:00 +0000)
committerAndreas.Eversberg <jolly@eversberg.eu>
Sat, 26 Jun 2010 14:00:29 +0000 (14:00 +0000)
19 files changed:
src/Makefile
src/host/layer23/configure.ac
src/host/layer23/include/osmocom/telnet_interface.h [deleted file]
src/host/layer23/include/vty/Makefile.am [deleted file]
src/host/layer23/include/vty/buffer.h [deleted file]
src/host/layer23/include/vty/command.h [deleted file]
src/host/layer23/include/vty/vector.h [deleted file]
src/host/layer23/include/vty/vty.h [deleted file]
src/host/layer23/src/Makefile.am
src/host/layer23/src/app_mobile.c
src/host/layer23/src/gsm322.c
src/host/layer23/src/main.c
src/host/layer23/src/mnccms.c
src/host/layer23/src/vty/buffer.c [deleted file]
src/host/layer23/src/vty/cardshell.h [deleted file]
src/host/layer23/src/vty/command.c [deleted file]
src/host/layer23/src/vty/vector.c [deleted file]
src/host/layer23/src/vty/vty.c [deleted file]
src/host/layer23/src/vty_interface.c

index e9cdb6c..5151bfb 100644 (file)
@@ -8,7 +8,9 @@ CROSS_TOOL_PREFIX=arm-elf-
 
 TOPDIR=$(shell pwd)
 OSMOCORE_CONFIGURE_ENV= LIBOSMOCORE_LIBS=$(TOPDIR)/shared/libosmocore/build-host/src/.libs/libosmocore.a \
-                       LIBOSMOCORE_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include
+                        LIBOSMOVTY_LIBS=$(TOPDIR)/shared/libosmocore/build-host/src/vty/.libs/libosmovty.a \
+                       LIBOSMOCORE_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include \
+                       LIBOSMOVTY_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include
 
 all: libosmocore-host libosmocore-target layer23 osmocon firmware
 
index 177d968..036161c 100644 (file)
@@ -14,6 +14,7 @@ AC_PROG_RANLIB
 
 dnl checks for libraries
 PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore)
+PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty)
 
 dnl checks for header files
 AC_HEADER_STDC
diff --git a/src/host/layer23/include/osmocom/telnet_interface.h b/src/host/layer23/include/osmocom/telnet_interface.h
deleted file mode 100644 (file)
index 68157b0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* minimalistic telnet/network interface it might turn into a wire interface */
-/* (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.
- *
- */
-
-#ifndef TELNET_INTERFACE_H
-#define TELNET_INTERFACE_H
-
-#include <osmocom/osmocom_data.h>
-#include <osmocore/select.h>
-
-#include <vty/vty.h>
-
-struct telnet_connection {
-       struct llist_head entry;
-       struct osmocom_ms *ms;
-       struct bsc_fd fd;
-       struct vty *vty;
-       struct debug_target *dbg;
-};
-
-
-extern int telnet_init(struct osmocom_ms *ms, int port);
-
-extern int ms_vty_init(struct osmocom_ms *ms);
-
-extern void vty_notify(struct osmocom_ms *ms, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
-
-#endif
diff --git a/src/host/layer23/include/vty/Makefile.am b/src/host/layer23/include/vty/Makefile.am
deleted file mode 100644 (file)
index 1674766..0000000
+++ /dev/null
@@ -1 +0,0 @@
-noinst_HEADERS = buffer.h command.h  vector.h vty.h
diff --git a/src/host/layer23/include/vty/buffer.h b/src/host/layer23/include/vty/buffer.h
deleted file mode 100644 (file)
index 3151940..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Buffering to output and input.
- * Copyright (C) 1998 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra 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, or (at your
- * option) any later version.
- *
- * GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _ZEBRA_BUFFER_H
-#define _ZEBRA_BUFFER_H
-
-#include <sys/types.h>
-
-/* Create a new buffer.  Memory will be allocated in chunks of the given
-   size.  If the argument is 0, the library will supply a reasonable
-   default size suitable for buffering socket I/O. */
-struct buffer *buffer_new(size_t);
-
-/* Free all data in the buffer. */
-void buffer_reset(struct buffer *);
-
-/* This function first calls buffer_reset to release all buffered data.
-   Then it frees the struct buffer itself. */
-void buffer_free(struct buffer *);
-
-/* Add the given data to the end of the buffer. */
-extern void buffer_put(struct buffer *, const void *, size_t);
-/* Add a single character to the end of the buffer. */
-extern void buffer_putc(struct buffer *, u_char);
-/* Add a NUL-terminated string to the end of the buffer. */
-extern void buffer_putstr(struct buffer *, const char *);
-
-/* Combine all accumulated (and unflushed) data inside the buffer into a
-   single NUL-terminated string allocated using XMALLOC(MTYPE_TMP).  Note
-   that this function does not alter the state of the buffer, so the data
-   is still inside waiting to be flushed. */
-char *buffer_getstr(struct buffer *);
-
-/* Returns 1 if there is no pending data in the buffer.  Otherwise returns 0. */
-int buffer_empty(struct buffer *);
-
-typedef enum {
-       /* An I/O error occurred.  The buffer should be destroyed and the
-          file descriptor should be closed. */
-       BUFFER_ERROR = -1,
-
-       /* The data was written successfully, and the buffer is now empty
-          (there is no pending data waiting to be flushed). */
-       BUFFER_EMPTY = 0,
-
-       /* There is pending data in the buffer waiting to be flushed.  Please
-          try flushing the buffer when select indicates that the file descriptor
-          is writeable. */
-       BUFFER_PENDING = 1
-} buffer_status_t;
-
-/* Try to write this data to the file descriptor.  Any data that cannot
-   be written immediately is added to the buffer queue. */
-extern buffer_status_t buffer_write(struct buffer *, int fd,
-                                   const void *, size_t);
-
-/* This function attempts to flush some (but perhaps not all) of
-   the queued data to the given file descriptor. */
-extern buffer_status_t buffer_flush_available(struct buffer *, int fd);
-
-/* The following 2 functions (buffer_flush_all and buffer_flush_window)
-   are for use in lib/vty.c only.  They should not be used elsewhere. */
-
-/* Call buffer_flush_available repeatedly until either all data has been
-   flushed, or an I/O error has been encountered, or the operation would
-   block. */
-extern buffer_status_t buffer_flush_all(struct buffer *, int fd);
-
-/* Attempt to write enough data to the given fd to fill a window of the
-   given width and height (and remove the data written from the buffer).
-
-   If !no_more, then a message saying " --More-- " is appended.
-   If erase is true, then first overwrite the previous " --More-- " message
-   with spaces.
-
-   Any write error (including EAGAIN or EINTR) will cause this function
-   to return -1 (because the logic for handling the erase and more features
-   is too complicated to retry the write later).
-*/
-extern buffer_status_t buffer_flush_window(struct buffer *, int fd, int width,
-                                          int height, int erase, int no_more);
-
-#endif                         /* _ZEBRA_BUFFER_H */
diff --git a/src/host/layer23/include/vty/command.h b/src/host/layer23/include/vty/command.h
deleted file mode 100644 (file)
index 88d000d..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Zebra configuration command interface routine
- * Copyright (C) 1997, 98 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra 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, or (at your
- * option) any later version.
- *
- * GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _ZEBRA_COMMAND_H
-#define _ZEBRA_COMMAND_H
-
-#include <stdio.h>
-#include <sys/types.h>
-#include "vector.h"
-#include "vty.h"
-
-/* Host configuration variable */
-struct host {
-       /* Host name of this router. */
-       char *name;
-
-       /* Password for vty interface. */
-       char *password;
-       char *password_encrypt;
-
-       /* Enable password */
-       char *enable;
-       char *enable_encrypt;
-
-       /* System wide terminal lines. */
-       int lines;
-
-       /* Log filename. */
-       char *logfile;
-
-       /* config file name of this host */
-       char *config;
-
-       /* Flags for services */
-       int advanced;
-       int encrypt;
-
-       /* Banner configuration. */
-       const char *motd;
-       char *motdfile;
-};
-
-/* There are some command levels which called from command node. */
-enum node_type {
-       AUTH_NODE,              /* Authentication mode of vty interface. */
-       VIEW_NODE,              /* View node. Default mode of vty interface. */
-       AUTH_ENABLE_NODE,       /* Authentication mode for change enable. */
-       ENABLE_NODE,            /* Enable node. */
-       CONFIG_NODE,            /* Config node. Default mode of config file. */
-       SERVICE_NODE,           /* Service node. */
-       DEBUG_NODE,             /* Debug node. */
-#if 0
-       AAA_NODE,               /* AAA node. */
-       KEYCHAIN_NODE,          /* Key-chain node. */
-       KEYCHAIN_KEY_NODE,      /* Key-chain key node. */
-       INTERFACE_NODE,         /* Interface mode node. */
-       ZEBRA_NODE,             /* zebra connection node. */
-       TABLE_NODE,             /* rtm_table selection node. */
-       RIP_NODE,               /* RIP protocol mode node. */
-       RIPNG_NODE,             /* RIPng protocol mode node. */
-       BGP_NODE,               /* BGP protocol mode which includes BGP4+ */
-       BGP_VPNV4_NODE,         /* BGP MPLS-VPN PE exchange. */
-       BGP_IPV4_NODE,          /* BGP IPv4 unicast address family.  */
-       BGP_IPV4M_NODE,         /* BGP IPv4 multicast address family.  */
-       BGP_IPV6_NODE,          /* BGP IPv6 address family */
-       OSPF_NODE,              /* OSPF protocol mode */
-       OSPF6_NODE,             /* OSPF protocol for IPv6 mode */
-       ISIS_NODE,              /* ISIS protocol mode */
-       MASC_NODE,              /* MASC for multicast.  */
-       IRDP_NODE,              /* ICMP Router Discovery Protocol mode. */
-       IP_NODE,                /* Static ip route node. */
-       ACCESS_NODE,            /* Access list node. */
-       PREFIX_NODE,            /* Prefix list node. */
-       ACCESS_IPV6_NODE,       /* Access list node. */
-       PREFIX_IPV6_NODE,       /* Prefix list node. */
-       AS_LIST_NODE,           /* AS list node. */
-       COMMUNITY_LIST_NODE,    /* Community list node. */
-       RMAP_NODE,              /* Route map node. */
-       SMUX_NODE,              /* SNMP configuration node. */
-       DUMP_NODE,              /* Packet dump node. */
-       FORWARDING_NODE,        /* IP forwarding node. */
-#endif
-       VTY_NODE,               /* Vty node. */
-
-       MS_NODE,
-       TESTSIM_NODE,
-#if 0
-       BTS_NODE,
-       TRX_NODE,
-       TS_NODE,
-       SUBSCR_NODE,
-       MGCP_NODE,
-#endif
-};
-
-/* Node which has some commands and prompt string and configuration
-   function pointer . */
-struct cmd_node {
-       /* Node index. */
-       enum node_type node;
-
-       /* Prompt character at vty interface. */
-       const char *prompt;
-
-       /* Is this node's configuration goes to vtysh ? */
-       int vtysh;
-
-       /* Node's configuration write function */
-       int (*func) (struct vty *);
-
-       /* Vector of this node's command list. */
-       vector cmd_vector;
-};
-
-enum {
-       CMD_ATTR_DEPRECATED = 1,
-       CMD_ATTR_HIDDEN,
-};
-
-/* Structure of command element. */
-struct cmd_element {
-       const char *string;     /* Command specification by string. */
-       int (*func) (struct cmd_element *, struct vty *, int, const char *[]);
-       const char *doc;        /* Documentation of this command. */
-       int daemon;             /* Daemon to which this command belong. */
-       vector strvec;          /* Pointing out each description vector. */
-       unsigned int cmdsize;   /* Command index count. */
-       char *config;           /* Configuration string */
-       vector subconfig;       /* Sub configuration string */
-       u_char attr;            /* Command attributes */
-};
-
-/* Command description structure. */
-struct desc {
-       const char *cmd;        /* Command string. */
-       const char *str;        /* Command's description. */
-};
-
-/* Return value of the commands. */
-#define CMD_SUCCESS              0
-#define CMD_WARNING              1
-#define CMD_ERR_NO_MATCH         2
-#define CMD_ERR_AMBIGUOUS        3
-#define CMD_ERR_INCOMPLETE       4
-#define CMD_ERR_EXEED_ARGC_MAX   5
-#define CMD_ERR_NOTHING_TODO     6
-#define CMD_COMPLETE_FULL_MATCH  7
-#define CMD_COMPLETE_MATCH       8
-#define CMD_COMPLETE_LIST_MATCH  9
-#define CMD_SUCCESS_DAEMON      10
-
-/* Argc max counts. */
-#define CMD_ARGC_MAX   25
-
-/* Turn off these macros when uisng cpp with extract.pl */
-#ifndef VTYSH_EXTRACT_PL
-
-/* helper defines for end-user DEFUN* macros */
-#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
-  struct cmd_element cmdname = \
-  { \
-    .string = cmdstr, \
-    .func = funcname, \
-    .doc = helpstr, \
-    .attr = attrs, \
-    .daemon = dnum, \
-  };
-
-#define DEFUN_CMD_FUNC_DECL(funcname) \
-  static int funcname (struct cmd_element *, struct vty *, int, const char *[]); \
-
-#define DEFUN_CMD_FUNC_TEXT(funcname) \
-  static int funcname \
-    (struct cmd_element *self, struct vty *vty, int argc, const char *argv[])
-
-/* DEFUN for vty command interafce. Little bit hacky ;-). */
-#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_FUNC_DECL(funcname) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
-  DEFUN_CMD_FUNC_TEXT(funcname)
-
-#define DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
-  DEFUN_CMD_FUNC_DECL(funcname) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \
-  DEFUN_CMD_FUNC_TEXT(funcname)
-
-#define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
-
-#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) \
-
-/* DEFUN_NOSH for commands that vtysh should ignore */
-#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \
-  DEFUN(funcname, cmdname, cmdstr, helpstr)
-
-/* DEFSH for vtysh. */
-#define DEFSH(daemon, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, 0, daemon) \
-
-/* DEFUN + DEFSH */
-#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_FUNC_DECL(funcname) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \
-  DEFUN_CMD_FUNC_TEXT(funcname)
-
-/* DEFUN + DEFSH with attributes */
-#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \
-  DEFUN_CMD_FUNC_DECL(funcname) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \
-  DEFUN_CMD_FUNC_TEXT(funcname)
-
-#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
-  DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
-
-#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
-  DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED)
-
-/* ALIAS macro which define existing command's alias. */
-#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
-
-#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0)
-
-#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0)
-
-#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0)
-
-#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon)
-
-#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon)
-
-#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
-  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon)
-
-#endif                         /* VTYSH_EXTRACT_PL */
-
-/* Some macroes */
-#define CMD_OPTION(S)   ((S[0]) == '[')
-#define CMD_VARIABLE(S) (((S[0]) >= 'A' && (S[0]) <= 'Z') || ((S[0]) == '<'))
-#define CMD_VARARG(S)   ((S[0]) == '.')
-#define CMD_RANGE(S)   ((S[0] == '<'))
-
-#define CMD_IPV4(S)       ((strcmp ((S), "A.B.C.D") == 0))
-#define CMD_IPV4_PREFIX(S) ((strcmp ((S), "A.B.C.D/M") == 0))
-#define CMD_IPV6(S)        ((strcmp ((S), "X:X::X:X") == 0))
-#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0))
-
-/* Common descriptions. */
-#define SHOW_STR "Show running system information\n"
-#define IP_STR "IP information\n"
-#define IPV6_STR "IPv6 information\n"
-#define NO_STR "Negate a command or set its defaults\n"
-#define CLEAR_STR "Reset functions\n"
-#define RIP_STR "RIP information\n"
-#define BGP_STR "BGP information\n"
-#define OSPF_STR "OSPF information\n"
-#define NEIGHBOR_STR "Specify neighbor router\n"
-#define DEBUG_STR "Debugging functions (see also 'undebug')\n"
-#define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"
-#define ROUTER_STR "Enable a routing process\n"
-#define AS_STR "AS number\n"
-#define MBGP_STR "MBGP information\n"
-#define MATCH_STR "Match values from routing table\n"
-#define SET_STR "Set values in destination routing protocol\n"
-#define OUT_STR "Filter outgoing routing updates\n"
-#define IN_STR  "Filter incoming routing updates\n"
-#define V4NOTATION_STR "specify by IPv4 address notation(e.g. 0.0.0.0)\n"
-#define OSPF6_NUMBER_STR "Specify by number\n"
-#define INTERFACE_STR "Interface infomation\n"
-#define IFNAME_STR "Interface name(e.g. ep0)\n"
-#define IP6_STR "IPv6 Information\n"
-#define OSPF6_STR "Open Shortest Path First (OSPF) for IPv6\n"
-#define OSPF6_ROUTER_STR "Enable a routing process\n"
-#define OSPF6_INSTANCE_STR "<1-65535> Instance ID\n"
-#define SECONDS_STR "<1-65535> Seconds\n"
-#define ROUTE_STR "Routing Table\n"
-#define PREFIX_LIST_STR "Build a prefix list\n"
-#define OSPF6_DUMP_TYPE_LIST \
-"(neighbor|interface|area|lsa|zebra|config|dbex|spf|route|lsdb|redistribute|hook|asbr|prefix|abr)"
-#define ISIS_STR "IS-IS information\n"
-#define AREA_TAG_STR "[area tag]\n"
-
-#define CONF_BACKUP_EXT ".sav"
-
-/* IPv4 only machine should not accept IPv6 address for peer's IP
-   address.  So we replace VTY command string like below. */
-#ifdef HAVE_IPV6
-#define NEIGHBOR_CMD       "neighbor (A.B.C.D|X:X::X:X) "
-#define NO_NEIGHBOR_CMD    "no neighbor (A.B.C.D|X:X::X:X) "
-#define NEIGHBOR_ADDR_STR  "Neighbor address\nIPv6 address\n"
-#define NEIGHBOR_CMD2      "neighbor (A.B.C.D|X:X::X:X|WORD) "
-#define NO_NEIGHBOR_CMD2   "no neighbor (A.B.C.D|X:X::X:X|WORD) "
-#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor IPv6 address\nNeighbor tag\n"
-#else
-#define NEIGHBOR_CMD       "neighbor A.B.C.D "
-#define NO_NEIGHBOR_CMD    "no neighbor A.B.C.D "
-#define NEIGHBOR_ADDR_STR  "Neighbor address\n"
-#define NEIGHBOR_CMD2      "neighbor (A.B.C.D|WORD) "
-#define NO_NEIGHBOR_CMD2   "no neighbor (A.B.C.D|WORD) "
-#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor tag\n"
-#endif                         /* HAVE_IPV6 */
-
-/* Prototypes. */
-void install_node(struct cmd_node *, int (*)(struct vty *));
-void install_default(enum node_type);
-void install_element(enum node_type, struct cmd_element *);
-void sort_node();
-
-/* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated
-   string with a space between each element (allocated using
-   XMALLOC(MTYPE_TMP)).  Returns NULL if shift >= argc. */
-char *argv_concat(const char **argv, int argc, int shift);
-
-vector cmd_make_strvec(const char *);
-void cmd_free_strvec(vector);
-vector cmd_describe_command();
-char **cmd_complete_command();
-const char *cmd_prompt(enum node_type);
-int config_from_file(struct vty *, FILE *);
-enum node_type node_parent(enum node_type);
-int cmd_execute_command(vector, struct vty *, struct cmd_element **, int);
-int cmd_execute_command_strict(vector, struct vty *, struct cmd_element **);
-void config_replace_string(struct cmd_element *, char *, ...);
-void cmd_init(int);
-
-/* Export typical functions. */
-extern struct cmd_element config_end_cmd;
-extern struct cmd_element config_exit_cmd;
-extern struct cmd_element config_quit_cmd;
-extern struct cmd_element config_help_cmd;
-extern struct cmd_element config_list_cmd;
-char *host_config_file();
-void host_config_set(const char *);
-
-void print_version(const char *);
-
-extern void *tall_vty_cmd_ctx;
-
-#endif                         /* _ZEBRA_COMMAND_H */
diff --git a/src/host/layer23/include/vty/vector.h b/src/host/layer23/include/vty/vector.h
deleted file mode 100644 (file)
index 22a184d..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Generic vector interface header.
- * Copyright (C) 1997, 98 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra 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, or (at your option) any
- * later version.
- *
- * GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#ifndef _ZEBRA_VECTOR_H
-#define _ZEBRA_VECTOR_H
-
-/* struct for vector */
-struct _vector {
-       unsigned int active;    /* number of active slots */
-       unsigned int alloced;   /* number of allocated slot */
-       void **index;           /* index to data */
-};
-typedef struct _vector *vector;
-
-#define VECTOR_MIN_SIZE 1
-
-/* (Sometimes) usefull macros.  This macro convert index expression to
- array expression. */
-/* Reference slot at given index, caller must ensure slot is active */
-#define vector_slot(V,I)  ((V)->index[(I)])
-/* Number of active slots.
- * Note that this differs from vector_count() as it the count returned
- * will include any empty slots
- */
-#define vector_active(V) ((V)->active)
-
-/* Prototypes. */
-vector vector_init(unsigned int size);
-void vector_ensure(vector v, unsigned int num);
-int vector_empty_slot(vector v);
-int vector_set(vector v, void *val);
-int vector_set_index(vector v, unsigned int i, void *val);
-void vector_unset(vector v, unsigned int i);
-unsigned int vector_count(vector v);
-void vector_only_wrapper_free(vector v);
-void vector_only_index_free(void *index);
-void vector_free(vector v);
-vector vector_copy(vector v);
-
-void *vector_lookup(vector, unsigned int);
-void *vector_lookup_ensure(vector, unsigned int);
-
-extern void *tall_vty_vec_ctx;
-
-#endif                         /* _ZEBRA_VECTOR_H */
diff --git a/src/host/layer23/include/vty/vty.h b/src/host/layer23/include/vty/vty.h
deleted file mode 100644 (file)
index 0441fc5..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-#ifndef _VTY_H
-#define _VTY_H
-
-#include <stdio.h>
-#include <stdarg.h>
-
-/* GCC have printf type attribute check.  */
-#ifdef __GNUC__
-#define VTY_PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
-#else
-#define VTY_PRINTF_ATTRIBUTE(a,b)
-#endif                         /* __GNUC__ */
-
-/* Does the I/O error indicate that the operation should be retried later? */
-#define ERRNO_IO_RETRY(EN) \
-       (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
-
-/* Vty read buffer size. */
-#define VTY_READ_BUFSIZ 512
-
-#define VTY_BUFSIZ 512
-#define VTY_MAXHIST 20
-
-/* Vty events */
-enum event {
-       VTY_SERV,
-       VTY_READ,
-       VTY_WRITE,
-       VTY_CLOSED,
-       VTY_TIMEOUT_RESET,
-#ifdef VTYSH
-       VTYSH_SERV,
-       VTYSH_READ,
-       VTYSH_WRITE
-#endif                         /* VTYSH */
-};
-
-struct vty {
-       FILE *file;
-
-       /* private data, specified by creator */
-       void *priv;
-
-       /* File descripter of this vty. */
-       int fd;
-
-       /* Is this vty connect to file or not */
-       enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type;
-
-       /* Node status of this vty */
-       int node;
-
-       /* Failure count */
-       int fail;
-
-       /* Output buffer. */
-       struct buffer *obuf;
-
-       /* Command input buffer */
-       char *buf;
-
-       /* Command cursor point */
-       int cp;
-
-       /* Command length */
-       int length;
-
-       /* Command max length. */
-       int max;
-
-       /* Histry of command */
-       char *hist[VTY_MAXHIST];
-
-       /* History lookup current point */
-       int hp;
-
-       /* History insert end point */
-       int hindex;
-
-       /* For current referencing point of interface, route-map,
-          access-list etc... */
-       void *index;
-
-       /* For multiple level index treatment such as key chain and key. */
-       void *index_sub;
-
-       /* For escape character. */
-       unsigned char escape;
-
-       /* Current vty status. */
-       enum { VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE } status;
-
-       /* IAC handling: was the last character received the IAC
-        * (interpret-as-command) escape character (and therefore the next
-        * character will be the command code)?  Refer to Telnet RFC 854. */
-       unsigned char iac;
-
-       /* IAC SB (option subnegotiation) handling */
-       unsigned char iac_sb_in_progress;
-       /* At the moment, we care only about the NAWS (window size) negotiation,
-        * and that requires just a 5-character buffer (RFC 1073):
-        * <NAWS char> <16-bit width> <16-bit height> */
-#define TELNET_NAWS_SB_LEN 5
-       unsigned char sb_buf[TELNET_NAWS_SB_LEN];
-       /* How many subnegotiation characters have we received?  We just drop
-        * those that do not fit in the buffer. */
-       size_t sb_len;
-
-       /* Window width/height. */
-       int width;
-       int height;
-
-       /* Configure lines. */
-       int lines;
-
-       int monitor;
-
-       /* In configure mode. */
-       int config;
-};
-
-/* Small macro to determine newline is newline only or linefeed needed. */
-#define VTY_NEWLINE  ((vty->type == VTY_TERM) ? "\r\n" : "\n")
-
-static inline char *vty_newline(struct vty *vty)
-{
-       return VTY_NEWLINE;
-}
-
-/* Prototypes. */
-void vty_init (void);
-int vty_read_config_file(const char *file_name);
-void vty_init_vtysh (void);
-void vty_reset (void);
-struct vty *vty_new (void);
-struct vty *vty_create (int vty_sock, void *priv);
-int vty_out (struct vty *, const char *, ...) VTY_PRINTF_ATTRIBUTE(2, 3);
-int vty_out_newline(struct vty *);
-int vty_read(struct vty *vty);
-//void vty_time_print (struct vty *, int);
-void vty_close (struct vty *);
-char *vty_get_cwd (void);
-void vty_log (const char *level, const char *proto, const char *fmt, va_list);
-int vty_config_lock (struct vty *);
-int vty_config_unlock (struct vty *);
-int vty_shell (struct vty *);
-int vty_shell_serv (struct vty *);
-void vty_hello (struct vty *);
-
-void *tall_vty_ctx;
-#endif
index dda3438..6b25352 100644 (file)
@@ -2,12 +2,12 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include
 AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS)
 #AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
 
-noinst_LIBRARIES = liblayer23.a libvty.a
+noinst_LIBRARIES = liblayer23.a
 liblayer23_a_SOURCES = l1l2_interface.c l1ctl.c gsmtap_util.c lapdm.c rslms.c \
                        layer3.c logging.c bcch_scan.c settings.c \
                        gsm48_cc.c transaction.c gsm48_mm.c gsm48_rr.c \
                        gsm322.c support.c subscriber.c sysinfo.c networks.c \
-                       mnccms.c telnet_interface.c vty_interface.c
+                       mnccms.c vty_interface.c
 
 bin_PROGRAMS = bcch_scan layer23 echo_test mobile
 
@@ -21,7 +21,6 @@ echo_test_SOURCES = main.c app_echo_test.c
 echo_test_LDADD = liblayer23.a $(LIBOSMOCORE_LIBS)
 
 mobile_SOURCES = main.c app_mobile.c
-mobile_LDADD = liblayer23.a libvty.a $(LIBOSMOCORE_LIBS)
+mobile_LDADD = liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS)
 
-libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
 
index a7a1215..a40d382 100644 (file)
@@ -34,7 +34,8 @@
 #include <osmocom/lapdm.h>
 #include <osmocom/gsmtap_util.h>
 #include <osmocom/logging.h>
-#include <osmocom/telnet_interface.h>
+#include <osmocom/vty.h>
+#include <osmocom/vty/telnet_interface.h>
 #include <osmocom/file.h>
 
 #include <osmocore/msgb.h>
@@ -43,7 +44,8 @@
 #include <osmocore/signal.h>
 
 extern struct log_target *stderr_target;
-static const char *config_file = "osmocom.cfg";
+static const char *config_file = "/etc/osmocom/osmocom.cfg";
+extern void *l23_ctx;
 
 static int started = 0;
 
@@ -134,9 +136,16 @@ int mobile_exit(struct osmocom_ms *ms)
        return 0;
 }
 
+static struct vty_app_info vty_info = {
+       .name = "OsmocomBB",
+       .version = PACKAGE_VERSION,
+       .go_parent_cb = ms_vty_go_parent,
+};
+
 int l23_app_init(struct osmocom_ms *ms)
 {
        int rc;
+       struct telnet_connection dummy_conn;
 
 //     log_parse_category_mask(stderr_target, "DRSL:DLAPDM:DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG:DSUM");
        log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG:DSUM");
@@ -157,8 +166,10 @@ int l23_app_init(struct osmocom_ms *ms)
        register_signal_handler(SS_L1CTL, &signal_cb, NULL);
        l23_app_exit = mobile_exit;
 
-       telnet_init(ms, 4247);
-       rc = vty_read_config_file(config_file);
+       vty_init(&vty_info);
+       ms_vty_init();
+       dummy_conn.priv = NULL;
+       rc = vty_read_config_file(config_file, &dummy_conn);
        if (rc < 0) {
                fprintf(stderr, "Failed to parse the config file: '%s'\n",
                        config_file);
@@ -166,6 +177,9 @@ int l23_app_init(struct osmocom_ms *ms)
                        "'touch %s%s'\n", OSMOCOM_CONFDIR, config_file);
                return rc;
        }
+       telnet_init(l23_ctx, NULL, 4247);
+       if (rc < 0)
+               return rc;
 
        gsm_random_imei(&ms->settings);
 
index 672f77e..b59763a 100644 (file)
@@ -36,7 +36,7 @@
 #include <osmocom/file.h>
 #include <osmocom/osmocom_data.h>
 #include <osmocom/networks.h>
-#include <osmocom/telnet_interface.h>
+#include <osmocom/vty.h>
 
 extern void *l23_ctx;
 
index e9f243d..4aa9bf1 100644 (file)
@@ -56,6 +56,13 @@ int (*l23_app_work) (struct osmocom_ms *ms) = NULL;
 int (*l23_app_exit) (struct osmocom_ms *ms) = NULL;
 int quit = 0;
 
+const char *openbsc_copyright =
+       "Copyright (C) 2008-2010 ...\n"
+       "Contributions by ...\n\n"
+       "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
+       "This is free software: you are free to change and redistribute it.\n"
+       "There is NO WARRANTY, to the extent permitted by law.\n";
+
 static void print_usage(const char *app)
 {
        printf("Usage: %s\n", app);
@@ -91,6 +98,7 @@ static void handle_options(int argc, char **argv)
 
                switch (c) {
                case 'h':
+                       printf("%s\n", openbsc_copyright);
                        print_usage(argv[0]);
                        print_help();
                        exit(0);
index 3f6f866..dd08b7c 100644 (file)
@@ -30,7 +30,7 @@
 #include <osmocom/logging.h>
 #include <osmocom/osmocom_data.h>
 #include <osmocom/mncc.h>
-#include <osmocom/telnet_interface.h>
+#include <osmocom/vty.h>
 
 void *l23_ctx;
 static int new_callref = 1;
diff --git a/src/host/layer23/src/vty/buffer.c b/src/host/layer23/src/vty/buffer.c
deleted file mode 100644 (file)
index 195d062..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Buffering of output and input.
- * Copyright (C) 1998 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra 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, or (at your
- * option) any later version.
- *
- * GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <stddef.h>
-#include <sys/uio.h>
-
-#include <osmocore/talloc.h>
-#include <vty/buffer.h>
-#include <vty/vty.h>
-
-/* Buffer master. */
-struct buffer {
-       /* Data list. */
-       struct buffer_data *head;
-       struct buffer_data *tail;
-
-       /* Size of each buffer_data chunk. */
-       size_t size;
-};
-
-/* Data container. */
-struct buffer_data {
-       struct buffer_data *next;
-
-       /* Location to add new data. */
-       size_t cp;
-
-       /* Pointer to data not yet flushed. */
-       size_t sp;
-
-       /* Actual data stream (variable length). */
-       unsigned char data[0];  /* real dimension is buffer->size */
-};
-
-/* It should always be true that: 0 <= sp <= cp <= size */
-
-/* Default buffer size (used if none specified).  It is rounded up to the
-   next page boundery. */
-#define BUFFER_SIZE_DEFAULT            4096
-
-#define BUFFER_DATA_FREE(D) talloc_free((D))
-
-/* Make new buffer. */
-struct buffer *buffer_new(size_t size)
-{
-       struct buffer *b;
-
-       b = talloc_zero(tall_vty_ctx, struct buffer);
-
-       if (size)
-               b->size = size;
-       else {
-               static size_t default_size;
-               if (!default_size) {
-                       long pgsz = sysconf(_SC_PAGESIZE);
-                       default_size =
-                           ((((BUFFER_SIZE_DEFAULT - 1) / pgsz) + 1) * pgsz);
-               }
-               b->size = default_size;
-       }
-
-       return b;
-}
-
-/* Free buffer. */
-void buffer_free(struct buffer *b)
-{
-       buffer_reset(b);
-       talloc_free(b);
-}
-
-/* Make string clone. */
-char *buffer_getstr(struct buffer *b)
-{
-       size_t totlen = 0;
-       struct buffer_data *data;
-       char *s;
-       char *p;
-
-       for (data = b->head; data; data = data->next)
-               totlen += data->cp - data->sp;
-       if (!(s = _talloc_zero(tall_vty_ctx, (totlen + 1), "buffer_getstr")))
-               return NULL;
-       p = s;
-       for (data = b->head; data; data = data->next) {
-               memcpy(p, data->data + data->sp, data->cp - data->sp);
-               p += data->cp - data->sp;
-       }
-       *p = '\0';
-       return s;
-}
-
-/* Return 1 if buffer is empty. */
-int buffer_empty(struct buffer *b)
-{
-       return (b->head == NULL);
-}
-
-/* Clear and free all allocated data. */
-void buffer_reset(struct buffer *b)
-{
-       struct buffer_data *data;
-       struct buffer_data *next;
-
-       for (data = b->head; data; data = next) {
-               next = data->next;
-               BUFFER_DATA_FREE(data);
-       }
-       b->head = b->tail = NULL;
-}
-
-/* Add buffer_data to the end of buffer. */
-static struct buffer_data *buffer_add(struct buffer *b)
-{
-       struct buffer_data *d;
-
-       d = _talloc_zero(tall_vty_ctx,
-                        offsetof(struct buffer_data, data[b->size]),
-                        "buffer_add");
-       if (!d)
-               return NULL;
-       d->cp = d->sp = 0;
-       d->next = NULL;
-
-       if (b->tail)
-               b->tail->next = d;
-       else
-               b->head = d;
-       b->tail = d;
-
-       return d;
-}
-
-/* Write data to buffer. */
-void buffer_put(struct buffer *b, const void *p, size_t size)
-{
-       struct buffer_data *data = b->tail;
-       const char *ptr = p;
-
-       /* We use even last one byte of data buffer. */
-       while (size) {
-               size_t chunk;
-
-               /* If there is no data buffer add it. */
-               if (data == NULL || data->cp == b->size)
-                       data = buffer_add(b);
-
-               chunk =
-                   ((size <=
-                     (b->size - data->cp)) ? size : (b->size - data->cp));
-               memcpy((data->data + data->cp), ptr, chunk);
-               size -= chunk;
-               ptr += chunk;
-               data->cp += chunk;
-       }
-}
-
-/* Insert character into the buffer. */
-void buffer_putc(struct buffer *b, u_char c)
-{
-       buffer_put(b, &c, 1);
-}
-
-/* Put string to the buffer. */
-void buffer_putstr(struct buffer *b, const char *c)
-{
-       buffer_put(b, c, strlen(c));
-}
-
-/* Keep flushing data to the fd until the buffer is empty or an error is
-   encountered or the operation would block. */
-buffer_status_t buffer_flush_all(struct buffer *b, int fd)
-{
-       buffer_status_t ret;
-       struct buffer_data *head;
-       size_t head_sp;
-
-       if (!b->head)
-               return BUFFER_EMPTY;
-       head_sp = (head = b->head)->sp;
-       /* Flush all data. */
-       while ((ret = buffer_flush_available(b, fd)) == BUFFER_PENDING) {
-               if ((b->head == head) && (head_sp == head->sp)
-                   && (errno != EINTR))
-                       /* No data was flushed, so kernel buffer must be full. */
-                       return ret;
-               head_sp = (head = b->head)->sp;
-       }
-
-       return ret;
-}
-
-#if 0
-/* Flush enough data to fill a terminal window of the given scene (used only
-   by vty telnet interface). */
-buffer_status_t
-buffer_flush_window(struct buffer * b, int fd, int width, int height,
-                   int erase_flag, int no_more_flag)
-{
-       int nbytes;
-       int iov_alloc;
-       int iov_index;
-       struct iovec *iov;
-       struct iovec small_iov[3];
-       char more[] = " --More-- ";
-       char erase[] =
-           { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-               ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
-               0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
-       };
-       struct buffer_data *data;
-       int column;
-
-       if (!b->head)
-               return BUFFER_EMPTY;
-
-       if (height < 1) {
-               zlog_warn
-                   ("%s called with non-positive window height %d, forcing to 1",
-                    __func__, height);
-               height = 1;
-       } else if (height >= 2)
-               height--;
-       if (width < 1) {
-               zlog_warn
-                   ("%s called with non-positive window width %d, forcing to 1",
-                    __func__, width);
-               width = 1;
-       }
-
-       /* For erase and more data add two to b's buffer_data count. */
-       if (b->head->next == NULL) {
-               iov_alloc = sizeof(small_iov) / sizeof(small_iov[0]);
-               iov = small_iov;
-       } else {
-               iov_alloc = ((height * (width + 2)) / b->size) + 10;
-               iov = XMALLOC(MTYPE_TMP, iov_alloc * sizeof(*iov));
-       }
-       iov_index = 0;
-
-       /* Previously print out is performed. */
-       if (erase_flag) {
-               iov[iov_index].iov_base = erase;
-               iov[iov_index].iov_len = sizeof erase;
-               iov_index++;
-       }
-
-       /* Output data. */
-       column = 1;             /* Column position of next character displayed. */
-       for (data = b->head; data && (height > 0); data = data->next) {
-               size_t cp;
-
-               cp = data->sp;
-               while ((cp < data->cp) && (height > 0)) {
-                       /* Calculate lines remaining and column position after displaying
-                          this character. */
-                       if (data->data[cp] == '\r')
-                               column = 1;
-                       else if ((data->data[cp] == '\n') || (column == width)) {
-                               column = 1;
-                               height--;
-                       } else
-                               column++;
-                       cp++;
-               }
-               iov[iov_index].iov_base = (char *)(data->data + data->sp);
-               iov[iov_index++].iov_len = cp - data->sp;
-               data->sp = cp;
-
-               if (iov_index == iov_alloc)
-                       /* This should not ordinarily happen. */
-               {
-                       iov_alloc *= 2;
-                       if (iov != small_iov) {
-                               zlog_warn("%s: growing iov array to %d; "
-                                         "width %d, height %d, size %lu",
-                                         __func__, iov_alloc, width, height,
-                                         (u_long) b->size);
-                               iov =
-                                   XREALLOC(MTYPE_TMP, iov,
-                                            iov_alloc * sizeof(*iov));
-                       } else {
-                               /* This should absolutely never occur. */
-                               zlog_err
-                                   ("%s: corruption detected: iov_small overflowed; "
-                                    "head %p, tail %p, head->next %p",
-                                    __func__, b->head, b->tail, b->head->next);
-                               iov =
-                                   XMALLOC(MTYPE_TMP,
-                                           iov_alloc * sizeof(*iov));
-                               memcpy(iov, small_iov, sizeof(small_iov));
-                       }
-               }
-       }
-
-       /* In case of `more' display need. */
-       if (b->tail && (b->tail->sp < b->tail->cp) && !no_more_flag) {
-               iov[iov_index].iov_base = more;
-               iov[iov_index].iov_len = sizeof more;
-               iov_index++;
-       }
-#ifdef IOV_MAX
-       /* IOV_MAX are normally defined in <sys/uio.h> , Posix.1g.
-          example: Solaris2.6 are defined IOV_MAX size at 16.     */
-       {
-               struct iovec *c_iov = iov;
-               nbytes = 0;     /* Make sure it's initialized. */
-
-               while (iov_index > 0) {
-                       int iov_size;
-
-                       iov_size =
-                           ((iov_index > IOV_MAX) ? IOV_MAX : iov_index);
-                       if ((nbytes = writev(fd, c_iov, iov_size)) < 0) {
-                               zlog_warn("%s: writev to fd %d failed: %s",
-                                         __func__, fd, safe_strerror(errno));
-                               break;
-                       }
-
-                       /* move pointer io-vector */
-                       c_iov += iov_size;
-                       iov_index -= iov_size;
-               }
-       }
-#else                          /* IOV_MAX */
-       if ((nbytes = writev(fd, iov, iov_index)) < 0)
-               zlog_warn("%s: writev to fd %d failed: %s",
-                         __func__, fd, safe_strerror(errno));
-#endif                         /* IOV_MAX */
-
-       /* Free printed buffer data. */
-       while (b->head && (b->head->sp == b->head->cp)) {
-               struct buffer_data *del;
-               if (!(b->head = (del = b->head)->next))
-                       b->tail = NULL;
-               BUFFER_DATA_FREE(del);
-       }
-
-       if (iov != small_iov)
-               XFREE(MTYPE_TMP, iov);
-
-       return (nbytes < 0) ? BUFFER_ERROR :
-           (b->head ? BUFFER_PENDING : BUFFER_EMPTY);
-}
-#endif
-
-/* This function (unlike other buffer_flush* functions above) is designed
-to work with non-blocking sockets.  It does not attempt to write out
-all of the queued data, just a "big" chunk.  It returns 0 if it was
-able to empty out the buffers completely, 1 if more flushing is
-required later, or -1 on a fatal write error. */
-buffer_status_t buffer_flush_available(struct buffer * b, int fd)
-{
-
-/* These are just reasonable values to make sure a significant amount of
-data is written.  There's no need to go crazy and try to write it all
-in one shot. */
-#ifdef IOV_MAX
-#define MAX_CHUNKS ((IOV_MAX >= 16) ? 16 : IOV_MAX)
-#else
-#define MAX_CHUNKS 16
-#endif
-#define MAX_FLUSH 131072
-
-       struct buffer_data *d;
-       size_t written;
-       struct iovec iov[MAX_CHUNKS];
-       size_t iovcnt = 0;
-       size_t nbyte = 0;
-
-       for (d = b->head; d && (iovcnt < MAX_CHUNKS) && (nbyte < MAX_FLUSH);
-            d = d->next, iovcnt++) {
-               iov[iovcnt].iov_base = d->data + d->sp;
-               nbyte += (iov[iovcnt].iov_len = d->cp - d->sp);
-       }
-
-       if (!nbyte)
-               /* No data to flush: should we issue a warning message? */
-               return BUFFER_EMPTY;
-
-       /* only place where written should be sign compared */
-       if ((ssize_t) (written = writev(fd, iov, iovcnt)) < 0) {
-               if (ERRNO_IO_RETRY(errno))
-                       /* Calling code should try again later. */
-                       return BUFFER_PENDING;
-               return BUFFER_ERROR;
-       }
-
-       /* Free printed buffer data. */
-       while (written > 0) {
-               struct buffer_data *d;
-               if (!(d = b->head))
-                       break;
-               if (written < d->cp - d->sp) {
-                       d->sp += written;
-                       return BUFFER_PENDING;
-               }
-
-               written -= (d->cp - d->sp);
-               if (!(b->head = d->next))
-                       b->tail = NULL;
-               BUFFER_DATA_FREE(d);
-       }
-
-       return b->head ? BUFFER_PENDING : BUFFER_EMPTY;
-
-#undef MAX_CHUNKS
-#undef MAX_FLUSH
-}
-
-buffer_status_t
-buffer_write(struct buffer * b, int fd, const void *p, size_t size)
-{
-       ssize_t nbytes;
-
-#if 0
-       /* Should we attempt to drain any previously buffered data?  This could help reduce latency in pushing out the data if we are stuck in a long-running thread that is preventing the main select loop from calling the flush thread... */
-
-       if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR))
-               return BUFFER_ERROR;
-#endif
-       if (b->head)
-               /* Buffer is not empty, so do not attempt to write the new data. */
-               nbytes = 0;
-       else if ((nbytes = write(fd, p, size)) < 0) {
-               if (ERRNO_IO_RETRY(errno))
-                       nbytes = 0;
-               else
-                       return BUFFER_ERROR;
-       }
-       /* Add any remaining data to the buffer. */
-       {
-               size_t written = nbytes;
-               if (written < size)
-                       buffer_put(b, ((const char *)p) + written,
-                                  size - written);
-       }
-       return b->head ? BUFFER_PENDING : BUFFER_EMPTY;
-}
diff --git a/src/host/layer23/src/vty/cardshell.h b/src/host/layer23/src/vty/cardshell.h
deleted file mode 100644 (file)
index 439196a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#define QUAGGA_PROGNAME        "Osmocom BB"
-#define QUAGGA_VERSION "0.01"
-#define QUAGGA_COPYRIGHT ""
-#define CONFIGFILE_MASK 022
-#define SYSCONFDIR "/usr/local/etc"
diff --git a/src/host/layer23/src/vty/command.c b/src/host/layer23/src/vty/command.c
deleted file mode 100644 (file)
index 7ee3f34..0000000
+++ /dev/null
@@ -1,3417 +0,0 @@
-/*
-   $Id: command.c,v 1.47 2005/04/25 16:26:42 paul Exp $
-
-   Command interpreter routine for virtual terminal [aka TeletYpe]
-   Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra 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, or (at your
-option) any later version.
-
-GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#include "cardshell.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <errno.h>
-#define _XOPEN_SOURCE
-#include <unistd.h>
-#include <assert.h>
-#include <ctype.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-
-#include <vty/vector.h>
-#include <vty/vty.h>
-#include <vty/command.h>
-
-#include <osmocom/file.h>
-#include <osmocore/talloc.h>
-
-void *tall_vty_cmd_ctx;
-
-/* Command vector which includes some level of command lists. Normally
-   each daemon maintains each own cmdvec. */
-vector cmdvec;
-
-/* Host information structure. */
-struct host host;
-
-/* Standard command node structures. */
-struct cmd_node auth_node = {
-       AUTH_NODE,
-       "Password: ",
-};
-
-struct cmd_node view_node = {
-       VIEW_NODE,
-       "%s> ",
-};
-
-struct cmd_node auth_enable_node = {
-       AUTH_ENABLE_NODE,
-       "Password: ",
-};
-
-struct cmd_node enable_node = {
-       ENABLE_NODE,
-       "%s# ",
-};
-
-struct cmd_node config_node = {
-       CONFIG_NODE,
-       "%s(config)# ",
-       1
-};
-
-/* Default motd string. */
-const char *default_motd = "\r\n\
-Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
-" QUAGGA_COPYRIGHT "\r\n\
-\r\n";
-
-#if 0
-static struct facility_map {
-       int facility;
-       const char *name;
-       size_t match;
-} syslog_facilities[] = {
-       {
-       LOG_KERN, "kern", 1}, {
-       LOG_USER, "user", 2}, {
-       LOG_MAIL, "mail", 1}, {
-       LOG_DAEMON, "daemon", 1}, {
-       LOG_AUTH, "auth", 1}, {
-       LOG_SYSLOG, "syslog", 1}, {
-       LOG_LPR, "lpr", 2}, {
-       LOG_NEWS, "news", 1}, {
-       LOG_UUCP, "uucp", 2}, {
-       LOG_CRON, "cron", 1},
-#ifdef LOG_FTP
-       {
-       LOG_FTP, "ftp", 1},
-#endif
-       {
-       LOG_LOCAL0, "local0", 6}, {
-       LOG_LOCAL1, "local1", 6}, {
-       LOG_LOCAL2, "local2", 6}, {
-       LOG_LOCAL3, "local3", 6}, {
-       LOG_LOCAL4, "local4", 6}, {
-       LOG_LOCAL5, "local5", 6}, {
-       LOG_LOCAL6, "local6", 6}, {
-       LOG_LOCAL7, "local7", 6}, {
-0, NULL, 0},};
-
-static const char *facility_name(int facility)
-{
-       struct facility_map *fm;
-
-       for (fm = syslog_facilities; fm->name; fm++)
-               if (fm->facility == facility)
-                       return fm->name;
-       return "";
-}
-
-static int facility_match(const char *str)
-{
-       struct facility_map *fm;
-
-       for (fm = syslog_facilities; fm->name; fm++)
-               if (!strncmp(str, fm->name, fm->match))
-                       return fm->facility;
-       return -1;
-}
-
-static int level_match(const char *s)
-{
-       int level;
-
-       for (level = 0; zlog_priority[level] != NULL; level++)
-               if (!strncmp(s, zlog_priority[level], 2))
-                       return level;
-       return ZLOG_DISABLED;
-}
-#endif
-
-/* This is called from main when a daemon is invoked with -v or --version. */
-void print_version(const char *progname)
-{
-       printf("%s version %s\n", progname, QUAGGA_VERSION);
-       printf("%s\n", QUAGGA_COPYRIGHT);
-}
-\f
-/* Utility function to concatenate argv argument into a single string
-   with inserting ' ' character between each argument.  */
-char *argv_concat(const char **argv, int argc, int shift)
-{
-       int i;
-       size_t len;
-       char *str;
-       char *p;
-
-       len = 0;
-       for (i = shift; i < argc; i++)
-               len += strlen(argv[i]) + 1;
-       if (!len)
-               return NULL;
-       p = str = _talloc_zero(tall_vty_cmd_ctx, len, "arvg_concat");
-       for (i = shift; i < argc; i++) {
-               size_t arglen;
-               memcpy(p, argv[i], (arglen = strlen(argv[i])));
-               p += arglen;
-               *p++ = ' ';
-       }
-       *(p - 1) = '\0';
-       return str;
-}
-
-/* Install top node of command vector. */
-void install_node(struct cmd_node *node, int (*func) (struct vty *))
-{
-       vector_set_index(cmdvec, node->node, node);
-       node->func = func;
-       node->cmd_vector = vector_init(VECTOR_MIN_SIZE);
-}
-
-/* Compare two command's string.  Used in sort_node (). */
-static int cmp_node(const void *p, const void *q)
-{
-       struct cmd_element *a = *(struct cmd_element **)p;
-       struct cmd_element *b = *(struct cmd_element **)q;
-
-       return strcmp(a->string, b->string);
-}
-
-static int cmp_desc(const void *p, const void *q)
-{
-       struct desc *a = *(struct desc **)p;
-       struct desc *b = *(struct desc **)q;
-
-       return strcmp(a->cmd, b->cmd);
-}
-
-/* Sort each node's command element according to command string. */
-void sort_node()
-{
-       unsigned int i, j;
-       struct cmd_node *cnode;
-       vector descvec;
-       struct cmd_element *cmd_element;
-
-       for (i = 0; i < vector_active(cmdvec); i++)
-               if ((cnode = vector_slot(cmdvec, i)) != NULL) {
-                       vector cmd_vector = cnode->cmd_vector;
-                       qsort(cmd_vector->index, vector_active(cmd_vector),
-                             sizeof(void *), cmp_node);
-
-                       for (j = 0; j < vector_active(cmd_vector); j++)
-                               if ((cmd_element =
-                                    vector_slot(cmd_vector, j)) != NULL
-                                   && vector_active(cmd_element->strvec)) {
-                                       descvec =
-                                           vector_slot(cmd_element->strvec,
-                                                       vector_active
-                                                       (cmd_element->strvec) -
-                                                       1);
-                                       qsort(descvec->index,
-                                             vector_active(descvec),
-                                             sizeof(void *), cmp_desc);
-                               }
-               }
-}
-
-/* Breaking up string into each command piece. I assume given
-   character is separated by a space character. Return value is a
-   vector which includes char ** data element. */
-vector cmd_make_strvec(const char *string)
-{
-       const char *cp, *start;
-       char *token;
-       int strlen;
-       vector strvec;
-
-       if (string == NULL)
-               return NULL;
-
-       cp = string;
-
-       /* Skip white spaces. */
-       while (isspace((int)*cp) && *cp != '\0')
-               cp++;
-
-       /* Return if there is only white spaces */
-       if (*cp == '\0')
-               return NULL;
-
-       if (*cp == '!' || *cp == '#')
-               return NULL;
-
-       /* Prepare return vector. */
-       strvec = vector_init(VECTOR_MIN_SIZE);
-
-       /* Copy each command piece and set into vector. */
-       while (1) {
-               start = cp;
-               while (!(isspace((int)*cp) || *cp == '\r' || *cp == '\n') &&
-                      *cp != '\0')
-                       cp++;
-               strlen = cp - start;
-               token = _talloc_zero(tall_vty_cmd_ctx, strlen + 1, "make_strvec");
-               memcpy(token, start, strlen);
-               *(token + strlen) = '\0';
-               vector_set(strvec, token);
-
-               while ((isspace((int)*cp) || *cp == '\n' || *cp == '\r') &&
-                      *cp != '\0')
-                       cp++;
-
-               if (*cp == '\0')
-                       return strvec;
-       }
-}
-
-/* Free allocated string vector. */
-void cmd_free_strvec(vector v)
-{
-       unsigned int i;
-       char *cp;
-
-       if (!v)
-               return;
-
-       for (i = 0; i < vector_active(v); i++)
-               if ((cp = vector_slot(v, i)) != NULL)
-                       talloc_free(cp);
-
-       vector_free(v);
-}
-
-/* Fetch next description.  Used in cmd_make_descvec(). */
-static char *cmd_desc_str(const char **string)
-{
-       const char *cp, *start;
-       char *token;
-       int strlen;
-
-       cp = *string;
-
-       if (cp == NULL)
-               return NULL;
-
-       /* Skip white spaces. */
-       while (isspace((int)*cp) && *cp != '\0')
-               cp++;
-
-       /* Return if there is only white spaces */
-       if (*cp == '\0')
-               return NULL;
-
-       start = cp;
-
-       while (!(*cp == '\r' || *cp == '\n') && *cp != '\0')
-               cp++;
-
-       strlen = cp - start;
-       token = _talloc_zero(tall_vty_cmd_ctx, strlen + 1, "cmd_desc_str");
-       memcpy(token, start, strlen);
-       *(token + strlen) = '\0';
-
-       *string = cp;
-
-       return token;
-}
-
-/* New string vector. */
-static vector cmd_make_descvec(const char *string, const char *descstr)
-{
-       int multiple = 0;
-       const char *sp;
-       char *token;
-       int len;
-       const char *cp;
-       const char *dp;
-       vector allvec;
-       vector strvec = NULL;
-       struct desc *desc;
-
-       cp = string;
-       dp = descstr;
-
-       if (cp == NULL)
-               return NULL;
-
-       allvec = vector_init(VECTOR_MIN_SIZE);
-
-       while (1) {
-               while (isspace((int)*cp) && *cp != '\0')
-                       cp++;
-
-               if (*cp == '(') {
-                       multiple = 1;
-                       cp++;
-               }
-               if (*cp == ')') {
-                       multiple = 0;
-                       cp++;
-               }
-               if (*cp == '|') {
-                       if (!multiple) {
-                               fprintf(stderr, "Command parse error!: %s\n",
-                                       string);
-                               exit(1);
-                       }
-                       cp++;
-               }
-
-               while (isspace((int)*cp) && *cp != '\0')
-                       cp++;
-
-               if (*cp == '(') {
-                       multiple = 1;
-                       cp++;
-               }
-
-               if (*cp == '\0')
-                       return allvec;
-
-               sp = cp;
-
-               while (!
-                      (isspace((int)*cp) || *cp == '\r' || *cp == '\n'
-                       || *cp == ')' || *cp == '|') && *cp != '\0')
-                       cp++;
-
-               len = cp - sp;
-
-               token = _talloc_zero(tall_vty_cmd_ctx, len + 1, "cmd_make_descvec");
-               memcpy(token, sp, len);
-               *(token + len) = '\0';
-
-               desc = talloc_zero(tall_vty_cmd_ctx, struct desc);
-               desc->cmd = token;
-               desc->str = cmd_desc_str(&dp);
-
-               if (multiple) {
-                       if (multiple == 1) {
-                               strvec = vector_init(VECTOR_MIN_SIZE);
-                               vector_set(allvec, strvec);
-                       }
-                       multiple++;
-               } else {
-                       strvec = vector_init(VECTOR_MIN_SIZE);
-                       vector_set(allvec, strvec);
-               }
-               vector_set(strvec, desc);
-       }
-}
-
-/* Count mandantory string vector size.  This is to determine inputed
-   command has enough command length. */
-static int cmd_cmdsize(vector strvec)
-{
-       unsigned int i;
-       int size = 0;
-       vector descvec;
-       struct desc *desc;
-
-       for (i = 0; i < vector_active(strvec); i++)
-               if ((descvec = vector_slot(strvec, i)) != NULL) {
-                       if ((vector_active(descvec)) == 1
-                           && (desc = vector_slot(descvec, 0)) != NULL) {
-                               if (desc->cmd == NULL || CMD_OPTION(desc->cmd))
-                                       return size;
-                               else
-                                       size++;
-                       } else
-                               size++;
-               }
-       return size;
-}
-
-/* Return prompt character of specified node. */
-const char *cmd_prompt(enum node_type node)
-{
-       struct cmd_node *cnode;
-
-       cnode = vector_slot(cmdvec, node);
-       return cnode->prompt;
-}
-
-/* Install a command into a node. */
-void install_element(enum node_type ntype, struct cmd_element *cmd)
-{
-       struct cmd_node *cnode;
-
-       cnode = vector_slot(cmdvec, ntype);
-
-       if (cnode == NULL) {
-               fprintf(stderr,
-                       "Command node %d doesn't exist, please check it\n",
-                       ntype);
-               exit(1);
-       }
-
-       vector_set(cnode->cmd_vector, cmd);
-
-       cmd->strvec = cmd_make_descvec(cmd->string, cmd->doc);
-       cmd->cmdsize = cmd_cmdsize(cmd->strvec);
-}
-
-#ifdef VTY_CRYPT_PW
-static unsigned char itoa64[] =
-    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-static void to64(char *s, long v, int n)
-{
-       while (--n >= 0) {
-               *s++ = itoa64[v & 0x3f];
-               v >>= 6;
-       }
-}
-
-static char *zencrypt(const char *passwd)
-{
-       char salt[6];
-       struct timeval tv;
-       char *crypt(const char *, const char *);
-
-       gettimeofday(&tv, 0);
-
-       to64(&salt[0], random(), 3);
-       to64(&salt[3], tv.tv_usec, 3);
-       salt[5] = '\0';
-
-       return crypt(passwd, salt);
-}
-#endif
-
-/* This function write configuration of this host. */
-static int config_write_host(struct vty *vty)
-{
-       if (host.name)
-               vty_out(vty, "hostname %s%s", host.name, VTY_NEWLINE);
-
-       if (host.encrypt) {
-               if (host.password_encrypt)
-                       vty_out(vty, "password 8 %s%s", host.password_encrypt,
-                               VTY_NEWLINE);
-               if (host.enable_encrypt)
-                       vty_out(vty, "enable password 8 %s%s",
-                               host.enable_encrypt, VTY_NEWLINE);
-       } else {
-               if (host.password)
-                       vty_out(vty, "password %s%s", host.password,
-                               VTY_NEWLINE);
-               if (host.enable)
-                       vty_out(vty, "enable password %s%s", host.enable,
-                               VTY_NEWLINE);
-       }
-
-#if 0
-       if (zlog_default->default_lvl != LOG_DEBUG) {
-               vty_out(vty, "! N.B. The 'log trap' command is deprecated.%s",
-                       VTY_NEWLINE);
-               vty_out(vty, "log trap %s%s",
-                       zlog_priority[zlog_default->default_lvl], VTY_NEWLINE);
-       }
-
-       if (host.logfile
-           && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) {
-               vty_out(vty, "log file %s", host.logfile);
-               if (zlog_default->maxlvl[ZLOG_DEST_FILE] !=
-                   zlog_default->default_lvl)
-                       vty_out(vty, " %s",
-                               zlog_priority[zlog_default->
-                                             maxlvl[ZLOG_DEST_FILE]]);
-               vty_out(vty, "%s", VTY_NEWLINE);
-       }
-
-       if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) {
-               vty_out(vty, "log stdout");
-               if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] !=
-                   zlog_default->default_lvl)
-                       vty_out(vty, " %s",
-                               zlog_priority[zlog_default->
-                                             maxlvl[ZLOG_DEST_STDOUT]]);
-               vty_out(vty, "%s", VTY_NEWLINE);
-       }
-
-       if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
-               vty_out(vty, "no log monitor%s", VTY_NEWLINE);
-       else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] !=
-                zlog_default->default_lvl)
-               vty_out(vty, "log monitor %s%s",
-                       zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],
-                       VTY_NEWLINE);
-
-       if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) {
-               vty_out(vty, "log syslog");
-               if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] !=
-                   zlog_default->default_lvl)
-                       vty_out(vty, " %s",
-                               zlog_priority[zlog_default->
-                                             maxlvl[ZLOG_DEST_SYSLOG]]);
-               vty_out(vty, "%s", VTY_NEWLINE);
-       }
-
-       if (zlog_default->facility != LOG_DAEMON)
-               vty_out(vty, "log facility %s%s",
-                       facility_name(zlog_default->facility), VTY_NEWLINE);
-
-       if (zlog_default->record_priority == 1)
-               vty_out(vty, "log record-priority%s", VTY_NEWLINE);
-#endif
-       if (host.advanced)
-               vty_out(vty, "service advanced-vty%s", VTY_NEWLINE);
-
-       if (host.encrypt)
-               vty_out(vty, "service password-encryption%s", VTY_NEWLINE);
-
-       if (host.lines >= 0)
-               vty_out(vty, "service terminal-length %d%s", host.lines,
-                       VTY_NEWLINE);
-
-       if (host.motdfile)
-               vty_out(vty, "banner motd file %s%s", host.motdfile,
-                       VTY_NEWLINE);
-       else if (!host.motd)
-               vty_out(vty, "no banner motd%s", VTY_NEWLINE);
-
-       return 1;
-}
-
-/* Utility function for getting command vector. */
-static vector cmd_node_vector(vector v, enum node_type ntype)
-{
-       struct cmd_node *cnode = vector_slot(v, ntype);
-       return cnode->cmd_vector;
-}
-
-#if 0
-/* Filter command vector by symbol.  This function is not actually used;
- * should it be deleted? */
-static int cmd_filter_by_symbol(char *command, char *symbol)
-{
-       int i, lim;
-
-       if (strcmp(symbol, "IPV4_ADDRESS") == 0) {
-               i = 0;
-               lim = strlen(command);
-               while (i < lim) {
-                       if (!
-                           (isdigit((int)command[i]) || command[i] == '.'
-                            || command[i] == '/'))
-                               return 1;
-                       i++;
-               }
-               return 0;
-       }
-       if (strcmp(symbol, "STRING") == 0) {
-               i = 0;
-               lim = strlen(command);
-               while (i < lim) {
-                       if (!
-                           (isalpha((int)command[i]) || command[i] == '_'
-                            || command[i] == '-'))
-                               return 1;
-                       i++;
-               }
-               return 0;
-       }
-       if (strcmp(symbol, "IFNAME") == 0) {
-               i = 0;
-               lim = strlen(command);
-               while (i < lim) {
-                       if (!isalnum((int)command[i]))
-                               return 1;
-                       i++;
-               }
-               return 0;
-       }
-       return 0;
-}
-#endif
-
-/* Completion match types. */
-enum match_type {
-       no_match,
-       extend_match,
-       ipv4_prefix_match,
-       ipv4_match,
-       ipv6_prefix_match,
-       ipv6_match,
-       range_match,
-       vararg_match,
-       partly_match,
-       exact_match
-};
-
-static enum match_type cmd_ipv4_match(const char *str)
-{
-       const char *sp;
-       int dots = 0, nums = 0;
-       char buf[4];
-
-       if (str == NULL)
-               return partly_match;
-
-       for (;;) {
-               memset(buf, 0, sizeof(buf));
-               sp = str;
-               while (*str != '\0') {
-                       if (*str == '.') {
-                               if (dots >= 3)
-                                       return no_match;
-
-                               if (*(str + 1) == '.')
-                                       return no_match;
-
-                               if (*(str + 1) == '\0')
-                                       return partly_match;
-
-                               dots++;
-                               break;
-                       }
-                       if (!isdigit((int)*str))
-                               return no_match;
-
-                       str++;
-               }
-
-               if (str - sp > 3)
-                       return no_match;
-
-               strncpy(buf, sp, str - sp);
-               if (atoi(buf) > 255)
-                       return no_match;
-
-               nums++;
-
-               if (*str == '\0')
-                       break;
-
-               str++;
-       }
-
-       if (nums < 4)
-               return partly_match;
-
-       return exact_match;
-}
-
-static enum match_type cmd_ipv4_prefix_match(const char *str)
-{
-       const char *sp;
-       int dots = 0;
-       char buf[4];
-
-       if (str == NULL)
-               return partly_match;
-
-       for (;;) {
-               memset(buf, 0, sizeof(buf));
-               sp = str;
-               while (*str != '\0' && *str != '/') {
-                       if (*str == '.') {
-                               if (dots == 3)
-                                       return no_match;
-
-                               if (*(str + 1) == '.' || *(str + 1) == '/')
-                                       return no_match;
-
-                               if (*(str + 1) == '\0')
-                                       return partly_match;
-
-                               dots++;
-                               break;
-                       }
-
-                       if (!isdigit((int)*str))
-                               return no_match;
-
-                       str++;
-               }
-
-               if (str - sp > 3)
-                       return no_match;
-
-               strncpy(buf, sp, str - sp);
-               if (atoi(buf) > 255)
-                       return no_match;
-
-               if (dots == 3) {
-                       if (*str == '/') {
-                               if (*(str + 1) == '\0')
-                                       return partly_match;
-
-                               str++;
-                               break;
-                       } else if (*str == '\0')
-                               return partly_match;
-               }
-
-               if (*str == '\0')
-                       return partly_match;
-
-               str++;
-       }
-
-       sp = str;
-       while (*str != '\0') {
-               if (!isdigit((int)*str))
-                       return no_match;
-
-               str++;
-       }
-
-       if (atoi(sp) > 32)
-               return no_match;
-
-       return exact_match;
-}
-
-#define IPV6_ADDR_STR          "0123456789abcdefABCDEF:.%"
-#define IPV6_PREFIX_STR                "0123456789abcdefABCDEF:.%/"
-#define STATE_START            1
-#define STATE_COLON            2
-#define STATE_DOUBLE           3
-#define STATE_ADDR             4
-#define STATE_DOT               5
-#define STATE_SLASH            6
-#define STATE_MASK             7
-
-#ifdef HAVE_IPV6
-
-static enum match_type cmd_ipv6_match(const char *str)
-{
-       int state = STATE_START;
-       int colons = 0, nums = 0, double_colon = 0;
-       const char *sp = NULL;
-       struct sockaddr_in6 sin6_dummy;
-       int ret;
-
-       if (str == NULL)
-               return partly_match;
-
-       if (strspn(str, IPV6_ADDR_STR) != strlen(str))
-               return no_match;
-
-       /* use inet_pton that has a better support,
-        * for example inet_pton can support the automatic addresses:
-        *  ::1.2.3.4
-        */
-       ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
-
-       if (ret == 1)
-               return exact_match;
-
-       while (*str != '\0') {
-               switch (state) {
-               case STATE_START:
-                       if (*str == ':') {
-                               if (*(str + 1) != ':' && *(str + 1) != '\0')
-                                       return no_match;
-                               colons--;
-                               state = STATE_COLON;
-                       } else {
-                               sp = str;
-                               state = STATE_ADDR;
-                       }
-
-                       continue;
-               case STATE_COLON:
-                       colons++;
-                       if (*(str + 1) == ':')
-                               state = STATE_DOUBLE;
-                       else {
-                               sp = str + 1;
-                               state = STATE_ADDR;
-                       }
-                       break;
-               case STATE_DOUBLE:
-                       if (double_colon)
-                               return no_match;
-
-                       if (*(str + 1) == ':')
-                               return no_match;
-                       else {
-                               if (*(str + 1) != '\0')
-                                       colons++;
-                               sp = str + 1;
-                               state = STATE_ADDR;
-                       }
-
-                       double_colon++;
-                       nums++;
-                       break;
-               case STATE_ADDR:
-                       if (*(str + 1) == ':' || *(str + 1) == '\0') {
-                               if (str - sp > 3)
-                                       return no_match;
-
-                               nums++;
-                               state = STATE_COLON;
-                       }
-                       if (*(str + 1) == '.')
-                               state = STATE_DOT;
-                       break;
-               case STATE_DOT:
-                       state = STATE_ADDR;
-                       break;
-               default:
-                       break;
-               }
-
-               if (nums > 8)
-                       return no_match;
-
-               if (colons > 7)
-                       return no_match;
-
-               str++;
-       }
-
-#if 0
-       if (nums < 11)
-               return partly_match;
-#endif                         /* 0 */
-
-       return exact_match;
-}
-
-static enum match_type cmd_ipv6_prefix_match(const char *str)
-{
-       int state = STATE_START;
-       int colons = 0, nums = 0, double_colon = 0;
-       int mask;
-       const char *sp = NULL;
-       char *endptr = NULL;
-
-       if (str == NULL)
-               return partly_match;
-
-       if (strspn(str, IPV6_PREFIX_STR) != strlen(str))
-               return no_match;
-
-       while (*str != '\0' && state != STATE_MASK) {
-               switch (state) {
-               case STATE_START:
-                       if (*str == ':') {
-                               if (*(str + 1) != ':' && *(str + 1) != '\0')
-                                       return no_match;
-                               colons--;
-                               state = STATE_COLON;
-                       } else {
-                               sp = str;
-                               state = STATE_ADDR;
-                       }
-
-                       continue;
-               case STATE_COLON:
-                       colons++;
-                       if (*(str + 1) == '/')
-                               return no_match;
-                       else if (*(str + 1) == ':')
-                               state = STATE_DOUBLE;
-                       else {
-                               sp = str + 1;
-                               state = STATE_ADDR;
-                       }
-                       break;
-               case STATE_DOUBLE:
-                       if (double_colon)
-                               return no_match;
-
-                       if (*(str + 1) == ':')
-                               return no_match;
-                       else {
-                               if (*(str + 1) != '\0' && *(str + 1) != '/')
-                                       colons++;
-                               sp = str + 1;
-
-                               if (*(str + 1) == '/')
-                                       state = STATE_SLASH;
-                               else
-                                       state = STATE_ADDR;
-                       }
-
-                       double_colon++;
-                       nums += 1;
-                       break;
-               case STATE_ADDR:
-                       if (*(str + 1) == ':' || *(str + 1) == '.'
-                           || *(str + 1) == '\0' || *(str + 1) == '/') {
-                               if (str - sp > 3)
-                                       return no_match;
-
-                               for (; sp <= str; sp++)
-                                       if (*sp == '/')
-                                               return no_match;
-
-                               nums++;
-
-                               if (*(str + 1) == ':')
-                                       state = STATE_COLON;
-                               else if (*(str + 1) == '.')
-                                       state = STATE_DOT;
-                               else if (*(str + 1) == '/')
-                                       state = STATE_SLASH;
-                       }
-                       break;
-               case STATE_DOT:
-                       state = STATE_ADDR;
-                       break;
-               case STATE_SLASH:
-                       if (*(str + 1) == '\0')
-                               return partly_match;
-
-                       state = STATE_MASK;
-                       break;
-               default:
-                       break;
-               }
-
-               if (nums > 11)
-                       return no_match;
-
-               if (colons > 7)
-                       return no_match;
-
-               str++;
-       }
-
-       if (state < STATE_MASK)
-               return partly_match;
-
-       mask = strtol(str, &endptr, 10);
-       if (*endptr != '\0')
-               return no_match;
-
-       if (mask < 0 || mask > 128)
-               return no_match;
-
-/* I don't know why mask < 13 makes command match partly.
-   Forgive me to make this comments. I Want to set static default route
-   because of lack of function to originate default in ospf6d; sorry
-       yasu
-  if (mask < 13)
-    return partly_match;
-*/
-
-       return exact_match;
-}
-
-#endif                         /* HAVE_IPV6  */
-
-#define DECIMAL_STRLEN_MAX 10
-
-static int cmd_range_match(const char *range, const char *str)
-{
-       char *p;
-       char buf[DECIMAL_STRLEN_MAX + 1];
-       char *endptr = NULL;
-       unsigned long min, max, val;
-
-       if (str == NULL)
-               return 1;
-
-       val = strtoul(str, &endptr, 10);
-       if (*endptr != '\0')
-               return 0;
-
-       range++;
-       p = strchr(range, '-');
-       if (p == NULL)
-               return 0;
-       if (p - range > DECIMAL_STRLEN_MAX)
-               return 0;
-       strncpy(buf, range, p - range);
-       buf[p - range] = '\0';
-       min = strtoul(buf, &endptr, 10);
-       if (*endptr != '\0')
-               return 0;
-
-       range = p + 1;
-       p = strchr(range, '>');
-       if (p == NULL)
-               return 0;
-       if (p - range > DECIMAL_STRLEN_MAX)
-               return 0;
-       strncpy(buf, range, p - range);
-       buf[p - range] = '\0';
-       max = strtoul(buf, &endptr, 10);
-       if (*endptr != '\0')
-               return 0;
-
-       if (val < min || val > max)
-               return 0;
-
-       return 1;
-}
-
-/* Make completion match and return match type flag. */
-static enum match_type
-cmd_filter_by_completion(char *command, vector v, unsigned int index)
-{
-       unsigned int i;
-       const char *str;
-       struct cmd_element *cmd_element;
-       enum match_type match_type;
-       vector descvec;
-       struct desc *desc;
-
-       match_type = no_match;
-
-       /* If command and cmd_element string does not match set NULL to vector */
-       for (i = 0; i < vector_active(v); i++)
-               if ((cmd_element = vector_slot(v, i)) != NULL) {
-                       if (index >= vector_active(cmd_element->strvec))
-                               vector_slot(v, i) = NULL;
-                       else {
-                               unsigned int j;
-                               int matched = 0;
-
-                               descvec =
-                                   vector_slot(cmd_element->strvec, index);
-
-                               for (j = 0; j < vector_active(descvec); j++)
-                                       if ((desc = vector_slot(descvec, j))) {
-                                               str = desc->cmd;
-
-                                               if (CMD_VARARG(str)) {
-                                                       if (match_type <
-                                                           vararg_match)
-                                                               match_type =
-                                                                   vararg_match;
-                                                       matched++;
-                                               } else if (CMD_RANGE(str)) {
-                                                       if (cmd_range_match
-                                                           (str, command)) {
-                                                               if (match_type <
-                                                                   range_match)
-                                                                       match_type
-                                                                           =
-                                                                           range_match;
-
-                                                               matched++;
-                                                       }
-                                               }
-#ifdef HAVE_IPV6
-                                               else if (CMD_IPV6(str)) {
-                                                       if (cmd_ipv6_match
-                                                           (command)) {
-                                                               if (match_type <
-                                                                   ipv6_match)
-                                                                       match_type
-                                                                           =
-                                                                           ipv6_match;
-
-                                                               matched++;
-                                                       }
-                                               } else if (CMD_IPV6_PREFIX(str)) {
-                                                       if (cmd_ipv6_prefix_match(command)) {
-                                                               if (match_type <
-                                                                   ipv6_prefix_match)
-                                                                       match_type
-                                                                           =
-                                                                           ipv6_prefix_match;
-
-                                                               matched++;
-                                                       }
-                                               }
-#endif                         /* HAVE_IPV6  */
-                                               else if (CMD_IPV4(str)) {
-                                                       if (cmd_ipv4_match
-                                                           (command)) {
-                                                               if (match_type <
-                                                                   ipv4_match)
-                                                                       match_type
-                                                                           =
-                                                                           ipv4_match;
-
-                                                               matched++;
-                                                       }
-                                               } else if (CMD_IPV4_PREFIX(str)) {
-                                                       if (cmd_ipv4_prefix_match(command)) {
-                                                               if (match_type <
-                                                                   ipv4_prefix_match)
-                                                                       match_type
-                                                                           =
-                                                                           ipv4_prefix_match;
-                                                               matched++;
-                                                       }
-                                               } else
-                                                       /* Check is this point's argument optional ? */
-                                               if (CMD_OPTION(str)
-                                                           ||
-                                                           CMD_VARIABLE(str)) {
-                                                       if (match_type <
-                                                           extend_match)
-                                                               match_type =
-                                                                   extend_match;
-                                                       matched++;
-                                               } else
-                                                   if (strncmp
-                                                       (command, str,
-                                                        strlen(command)) ==
-                                                       0) {
-                                                       if (strcmp(command, str)
-                                                           == 0)
-                                                               match_type =
-                                                                   exact_match;
-                                                       else {
-                                                               if (match_type <
-                                                                   partly_match)
-                                                                       match_type
-                                                                           =
-                                                                           partly_match;
-                                                       }
-                                                       matched++;
-                                               }
-                                       }
-                               if (!matched)
-                                       vector_slot(v, i) = NULL;
-                       }
-               }
-       return match_type;
-}
-
-/* Filter vector by command character with index. */
-static enum match_type
-cmd_filter_by_string(char *command, vector v, unsigned int index)
-{
-       unsigned int i;
-       const char *str;
-       struct cmd_element *cmd_element;
-       enum match_type match_type;
-       vector descvec;
-       struct desc *desc;
-
-       match_type = no_match;
-
-       /* If command and cmd_element string does not match set NULL to vector */
-       for (i = 0; i < vector_active(v); i++)
-               if ((cmd_element = vector_slot(v, i)) != NULL) {
-                       /* If given index is bigger than max string vector of command,
-                          set NULL */
-                       if (index >= vector_active(cmd_element->strvec))
-                               vector_slot(v, i) = NULL;
-                       else {
-                               unsigned int j;
-                               int matched = 0;
-
-                               descvec =
-                                   vector_slot(cmd_element->strvec, index);
-
-                               for (j = 0; j < vector_active(descvec); j++)
-                                       if ((desc = vector_slot(descvec, j))) {
-                                               str = desc->cmd;
-
-                                               if (CMD_VARARG(str)) {
-                                                       if (match_type <
-                                                           vararg_match)
-                                                               match_type =
-                                                                   vararg_match;
-                                                       matched++;
-                                               } else if (CMD_RANGE(str)) {
-                                                       if (cmd_range_match
-                                                           (str, command)) {
-                                                               if (match_type <
-                                                                   range_match)
-                                                                       match_type
-                                                                           =
-                                                                           range_match;
-                                                               matched++;
-                                                       }
-                                               }
-#ifdef HAVE_IPV6
-                                               else if (CMD_IPV6(str)) {
-                                                       if (cmd_ipv6_match
-                                                           (command) ==
-                                                           exact_match) {
-                                                               if (match_type <
-                                                                   ipv6_match)
-                                                                       match_type
-                                                                           =
-                                                                           ipv6_match;
-                                                               matched++;
-                                                       }
-                                               } else if (CMD_IPV6_PREFIX(str)) {
-                                                       if (cmd_ipv6_prefix_match(command) == exact_match) {
-                                                               if (match_type <
-                                                                   ipv6_prefix_match)
-                                                                       match_type
-                                                                           =
-                                                                           ipv6_prefix_match;
-                                                               matched++;
-                                                       }
-                                               }
-#endif                         /* HAVE_IPV6  */
-                                               else if (CMD_IPV4(str)) {
-                                                       if (cmd_ipv4_match
-                                                           (command) ==
-                                                           exact_match) {
-                                                               if (match_type <
-                                                                   ipv4_match)
-                                                                       match_type
-                                                                           =
-                                                                           ipv4_match;
-                                                               matched++;
-                                                       }
-                                               } else if (CMD_IPV4_PREFIX(str)) {
-                                                       if (cmd_ipv4_prefix_match(command) == exact_match) {
-                                                               if (match_type <
-                                                                   ipv4_prefix_match)
-                                                                       match_type
-                                                                           =
-                                                                           ipv4_prefix_match;
-                                                               matched++;
-                                                       }
-                                               } else if (CMD_OPTION(str)
-                                                          || CMD_VARIABLE(str))
-                                               {
-                                                       if (match_type <
-                                                           extend_match)
-                                                               match_type =
-                                                                   extend_match;
-                                                       matched++;
-                                               } else {
-                                                       if (strcmp(command, str)
-                                                           == 0) {
-                                                               match_type =
-                                                                   exact_match;
-                                                               matched++;
-                                                       }
-                                               }
-                                       }
-                               if (!matched)
-                                       vector_slot(v, i) = NULL;
-                       }
-               }
-       return match_type;
-}
-
-/* Check ambiguous match */
-static int
-is_cmd_ambiguous(char *command, vector v, int index, enum match_type type)
-{
-       unsigned int i;
-       unsigned int j;
-       const char *str = NULL;
-       struct cmd_element *cmd_element;
-       const char *matched = NULL;
-       vector descvec;
-       struct desc *desc;
-
-       for (i = 0; i < vector_active(v); i++)
-               if ((cmd_element = vector_slot(v, i)) != NULL) {
-                       int match = 0;
-
-                       descvec = vector_slot(cmd_element->strvec, index);
-
-                       for (j = 0; j < vector_active(descvec); j++)
-                               if ((desc = vector_slot(descvec, j))) {
-                                       enum match_type ret;
-
-                                       str = desc->cmd;
-
-                                       switch (type) {
-                                       case exact_match:
-                                               if (!
-                                                   (CMD_OPTION(str)
-                                                    || CMD_VARIABLE(str))
-&& strcmp(command, str) == 0)
-                                                       match++;
-                                               break;
-                                       case partly_match:
-                                               if (!
-                                                   (CMD_OPTION(str)
-                                                    || CMD_VARIABLE(str))
-&& strncmp(command, str, strlen(command)) == 0) {
-                                                       if (matched
-                                                           && strcmp(matched,
-                                                                     str) != 0)
-                                                               return 1;       /* There is ambiguous match. */
-                                                       else
-                                                               matched = str;
-                                                       match++;
-                                               }
-                                               break;
-                                       case range_match:
-                                               if (cmd_range_match
-                                                   (str, command)) {
-                                                       if (matched
-                                                           && strcmp(matched,
-                                                                     str) != 0)
-                                                               return 1;
-                                                       else
-                                                               matched = str;
-                                                       match++;
-                                               }
-                                               break;
-#ifdef HAVE_IPV6
-                                       case ipv6_match:
-                                               if (CMD_IPV6(str))
-                                                       match++;
-                                               break;
-                                       case ipv6_prefix_match:
-                                               if ((ret =
-                                                    cmd_ipv6_prefix_match
-                                                    (command)) != no_match) {
-                                                       if (ret == partly_match)
-                                                               return 2;       /* There is incomplete match. */
-
-                                                       match++;
-                                               }
-                                               break;
-#endif                         /* HAVE_IPV6 */
-                                       case ipv4_match:
-                                               if (CMD_IPV4(str))
-                                                       match++;
-                                               break;
-                                       case ipv4_prefix_match:
-                                               if ((ret =
-                                                    cmd_ipv4_prefix_match
-                                                    (command)) != no_match) {
-                                                       if (ret == partly_match)
-                                                               return 2;       /* There is incomplete match. */
-
-                                                       match++;
-                                               }
-                                               break;
-                                       case extend_match:
-                                               if (CMD_OPTION(str)
-                                                   || CMD_VARIABLE(str))
-                                                       match++;
-                                               break;
-                                       case no_match:
-                                       default:
-                                               break;
-                                       }
-                               }
-                       if (!match)
-                               vector_slot(v, i) = NULL;
-               }
-       return 0;
-}
-
-/* If src matches dst return dst string, otherwise return NULL */
-static const char *cmd_entry_function(const char *src, const char *dst)
-{
-       /* Skip variable arguments. */
-       if (CMD_OPTION(dst) || CMD_VARIABLE(dst) || CMD_VARARG(dst) ||
-           CMD_IPV4(dst) || CMD_IPV4_PREFIX(dst) || CMD_RANGE(dst))
-               return NULL;
-
-       /* In case of 'command \t', given src is NULL string. */
-       if (src == NULL)
-               return dst;
-
-       /* Matched with input string. */
-       if (strncmp(src, dst, strlen(src)) == 0)
-               return dst;
-
-       return NULL;
-}
-
-/* If src matches dst return dst string, otherwise return NULL */
-/* This version will return the dst string always if it is
-   CMD_VARIABLE for '?' key processing */
-static const char *cmd_entry_function_desc(const char *src, const char *dst)
-{
-       if (CMD_VARARG(dst))
-               return dst;
-
-       if (CMD_RANGE(dst)) {
-               if (cmd_range_match(dst, src))
-                       return dst;
-               else
-                       return NULL;
-       }
-#ifdef HAVE_IPV6
-       if (CMD_IPV6(dst)) {
-               if (cmd_ipv6_match(src))
-                       return dst;
-               else
-                       return NULL;
-       }
-
-       if (CMD_IPV6_PREFIX(dst)) {
-               if (cmd_ipv6_prefix_match(src))
-                       return dst;
-               else
-                       return NULL;
-       }
-#endif                         /* HAVE_IPV6 */
-
-       if (CMD_IPV4(dst)) {
-               if (cmd_ipv4_match(src))
-                       return dst;
-               else
-                       return NULL;
-       }
-
-       if (CMD_IPV4_PREFIX(dst)) {
-               if (cmd_ipv4_prefix_match(src))
-                       return dst;
-               else
-                       return NULL;
-       }
-
-       /* Optional or variable commands always match on '?' */
-       if (CMD_OPTION(dst) || CMD_VARIABLE(dst))
-               return dst;
-
-       /* In case of 'command \t', given src is NULL string. */
-       if (src == NULL)
-               return dst;
-
-       if (strncmp(src, dst, strlen(src)) == 0)
-               return dst;
-       else
-               return NULL;
-}
-
-/* Check same string element existence.  If it isn't there return
-    1. */
-static int cmd_unique_string(vector v, const char *str)
-{
-       unsigned int i;
-       char *match;
-
-       for (i = 0; i < vector_active(v); i++)
-               if ((match = vector_slot(v, i)) != NULL)
-                       if (strcmp(match, str) == 0)
-                               return 0;
-       return 1;
-}
-
-/* Compare string to description vector.  If there is same string
-   return 1 else return 0. */
-static int desc_unique_string(vector v, const char *str)
-{
-       unsigned int i;
-       struct desc *desc;
-
-       for (i = 0; i < vector_active(v); i++)
-               if ((desc = vector_slot(v, i)) != NULL)
-                       if (strcmp(desc->cmd, str) == 0)
-                               return 1;
-       return 0;
-}
-
-static int cmd_try_do_shortcut(enum node_type node, char *first_word)
-{
-       if (first_word != NULL &&
-           node != AUTH_NODE &&
-           node != VIEW_NODE &&
-           node != AUTH_ENABLE_NODE &&
-           node != ENABLE_NODE && 0 == strcmp("do", first_word))
-               return 1;
-       return 0;
-}
-
-/* '?' describe command support. */
-static vector
-cmd_describe_command_real(vector vline, struct vty *vty, int *status)
-{
-       unsigned int i;
-       vector cmd_vector;
-#define INIT_MATCHVEC_SIZE 10
-       vector matchvec;
-       struct cmd_element *cmd_element;
-       unsigned int index;
-       int ret;
-       enum match_type match;
-       char *command;
-       static struct desc desc_cr = { "<cr>", "" };
-
-       /* Set index. */
-       if (vector_active(vline) == 0) {
-               *status = CMD_ERR_NO_MATCH;
-               return NULL;
-       } else
-               index = vector_active(vline) - 1;
-
-       /* Make copy vector of current node's command vector. */
-       cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));
-
-       /* Prepare match vector */
-       matchvec = vector_init(INIT_MATCHVEC_SIZE);
-
-       /* Filter commands. */
-       /* Only words precedes current word will be checked in this loop. */
-       for (i = 0; i < index; i++)
-               if ((command = vector_slot(vline, i))) {
-                       match =
-                           cmd_filter_by_completion(command, cmd_vector, i);
-
-                       if (match == vararg_match) {
-                               struct cmd_element *cmd_element;
-                               vector descvec;
-                               unsigned int j, k;
-
-                               for (j = 0; j < vector_active(cmd_vector); j++)
-                                       if ((cmd_element =
-                                            vector_slot(cmd_vector, j)) != NULL
-                                           &&
-                                           (vector_active
-                                            (cmd_element->strvec))) {
-                                               descvec =
-                                                   vector_slot(cmd_element->
-                                                               strvec,
-                                                               vector_active
-                                                               (cmd_element->
-                                                                strvec) - 1);
-                                               for (k = 0;
-                                                    k < vector_active(descvec);
-                                                    k++) {
-                                                       struct desc *desc =
-                                                           vector_slot(descvec,
-                                                                       k);
-                                                       vector_set(matchvec,
-                                                                  desc);
-                                               }
-                                       }
-
-                               vector_set(matchvec, &desc_cr);
-                               vector_free(cmd_vector);
-
-                               return matchvec;
-                       }
-
-                       if ((ret =
-                            is_cmd_ambiguous(command, cmd_vector, i,
-                                             match)) == 1) {
-                               vector_free(cmd_vector);
-                               *status = CMD_ERR_AMBIGUOUS;
-                               return NULL;
-                       } else if (ret == 2) {
-                               vector_free(cmd_vector);
-                               *status = CMD_ERR_NO_MATCH;
-                               return NULL;
-                       }
-               }
-
-       /* Prepare match vector */
-       /*  matchvec = vector_init (INIT_MATCHVEC_SIZE); */
-
-       /* Make sure that cmd_vector is filtered based on current word */
-       command = vector_slot(vline, index);
-       if (command)
-               match = cmd_filter_by_completion(command, cmd_vector, index);
-
-       /* Make description vector. */
-       for (i = 0; i < vector_active(cmd_vector); i++)
-               if ((cmd_element = vector_slot(cmd_vector, i)) != NULL) {
-                       const char *string = NULL;
-                       vector strvec = cmd_element->strvec;
-
-                       /* if command is NULL, index may be equal to vector_active */
-                       if (command && index >= vector_active(strvec))
-                               vector_slot(cmd_vector, i) = NULL;
-                       else {
-                               /* Check if command is completed. */
-                               if (command == NULL
-                                   && index == vector_active(strvec)) {
-                                       string = "<cr>";
-                                       if (!desc_unique_string
-                                           (matchvec, string))
-                                               vector_set(matchvec, &desc_cr);
-                               } else {
-                                       unsigned int j;
-                                       vector descvec =
-                                           vector_slot(strvec, index);
-                                       struct desc *desc;
-
-                                       for (j = 0; j < vector_active(descvec);
-                                            j++)
-                                               if ((desc =
-                                                    vector_slot(descvec, j))) {
-                                                       string =
-                                                           cmd_entry_function_desc
-                                                           (command,
-                                                            desc->cmd);
-                                                       if (string) {
-                                                               /* Uniqueness check */
-                                                               if (!desc_unique_string(matchvec, string))
-                                                                       vector_set
-                                                                           (matchvec,
-                                                                            desc);
-                                                       }
-                                               }
-                               }
-                       }
-               }
-       vector_free(cmd_vector);
-
-       if (vector_slot(matchvec, 0) == NULL) {
-               vector_free(matchvec);
-               *status = CMD_ERR_NO_MATCH;
-       } else
-               *status = CMD_SUCCESS;
-
-       return matchvec;
-}
-
-vector cmd_describe_command(vector vline, struct vty * vty, int *status)
-{
-       vector ret;
-
-       if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
-               enum node_type onode;
-               vector shifted_vline;
-               unsigned int index;
-
-               onode = vty->node;
-               vty->node = ENABLE_NODE;
-               /* We can try it on enable node, cos' the vty is authenticated */
-
-               shifted_vline = vector_init(vector_count(vline));
-               /* use memcpy? */
-               for (index = 1; index < vector_active(vline); index++) {
-                       vector_set_index(shifted_vline, index - 1,
-                                        vector_lookup(vline, index));
-               }
-
-               ret = cmd_describe_command_real(shifted_vline, vty, status);
-
-               vector_free(shifted_vline);
-               vty->node = onode;
-               return ret;
-       }
-
-       return cmd_describe_command_real(vline, vty, status);
-}
-
-/* Check LCD of matched command. */
-static int cmd_lcd(char **matched)
-{
-       int i;
-       int j;
-       int lcd = -1;
-       char *s1, *s2;
-       char c1, c2;
-
-       if (matched[0] == NULL || matched[1] == NULL)
-               return 0;
-
-       for (i = 1; matched[i] != NULL; i++) {
-               s1 = matched[i - 1];
-               s2 = matched[i];
-
-               for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++)
-                       if (c1 != c2)
-                               break;
-
-               if (lcd < 0)
-                       lcd = j;
-               else {
-                       if (lcd > j)
-                               lcd = j;
-               }
-       }
-       return lcd;
-}
-
-/* Command line completion support. */
-static char **cmd_complete_command_real(vector vline, struct vty *vty,
-                                       int *status)
-{
-       unsigned int i;
-       vector cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));
-#define INIT_MATCHVEC_SIZE 10
-       vector matchvec;
-       struct cmd_element *cmd_element;
-       unsigned int index;
-       char **match_str;
-       struct desc *desc;
-       vector descvec;
-       char *command;
-       int lcd;
-
-       if (vector_active(vline) == 0) {
-               *status = CMD_ERR_NO_MATCH;
-               return NULL;
-       } else
-               index = vector_active(vline) - 1;
-
-       /* First, filter by preceeding command string */
-       for (i = 0; i < index; i++)
-               if ((command = vector_slot(vline, i))) {
-                       enum match_type match;
-                       int ret;
-
-                       /* First try completion match, if there is exactly match return 1 */
-                       match =
-                           cmd_filter_by_completion(command, cmd_vector, i);
-
-                       /* If there is exact match then filter ambiguous match else check
-                          ambiguousness. */
-                       if ((ret =
-                            is_cmd_ambiguous(command, cmd_vector, i,
-                                             match)) == 1) {
-                               vector_free(cmd_vector);
-                               *status = CMD_ERR_AMBIGUOUS;
-                               return NULL;
-                       }
-                       /*
-                          else if (ret == 2)
-                          {
-                          vector_free (cmd_vector);
-                          *status = CMD_ERR_NO_MATCH;
-                          return NULL;
-                          }
-                        */
-               }
-
-       /* Prepare match vector. */
-       matchvec = vector_init(INIT_MATCHVEC_SIZE);
-
-       /* Now we got into completion */
-       for (i = 0; i < vector_active(cmd_vector); i++)
-               if ((cmd_element = vector_slot(cmd_vector, i))) {
-                       const char *string;
-                       vector strvec = cmd_element->strvec;
-
-                       /* Check field length */
-                       if (index >= vector_active(strvec))
-                               vector_slot(cmd_vector, i) = NULL;
-                       else {
-                               unsigned int j;
-
-                               descvec = vector_slot(strvec, index);
-                               for (j = 0; j < vector_active(descvec); j++)
-                                       if ((desc = vector_slot(descvec, j))) {
-                                               if ((string = cmd_entry_function(vector_slot(vline, index), desc->cmd)))
-                                                       if (cmd_unique_string (matchvec, string))
-                                                               vector_set (matchvec, talloc_strdup(tall_vty_cmd_ctx, string));
-                                       }
-                       }
-               }
-
-       /* We don't need cmd_vector any more. */
-       vector_free(cmd_vector);
-
-       /* No matched command */
-       if (vector_slot(matchvec, 0) == NULL) {
-               vector_free(matchvec);
-
-               /* In case of 'command \t' pattern.  Do you need '?' command at
-                  the end of the line. */
-               if (vector_slot(vline, index) == '\0')
-                       *status = CMD_ERR_NOTHING_TODO;
-               else
-                       *status = CMD_ERR_NO_MATCH;
-               return NULL;
-       }
-
-       /* Only one matched */
-       if (vector_slot(matchvec, 1) == NULL) {
-               match_str = (char **)matchvec->index;
-               vector_only_wrapper_free(matchvec);
-               *status = CMD_COMPLETE_FULL_MATCH;
-               return match_str;
-       }
-       /* Make it sure last element is NULL. */
-       vector_set(matchvec, NULL);
-
-       /* Check LCD of matched strings. */
-       if (vector_slot(vline, index) != NULL) {
-               lcd = cmd_lcd((char **)matchvec->index);
-
-               if (lcd) {
-                       int len = strlen(vector_slot(vline, index));
-
-                       if (len < lcd) {
-                               char *lcdstr;
-
-                               lcdstr = _talloc_zero(tall_vty_cmd_ctx, lcd + 1,
-                                                     "complete-lcdstr");
-                               memcpy(lcdstr, matchvec->index[0], lcd);
-                               lcdstr[lcd] = '\0';
-
-                               /* match_str = (char **) &lcdstr; */
-
-                               /* Free matchvec. */
-                               for (i = 0; i < vector_active(matchvec); i++) {
-                                       if (vector_slot(matchvec, i))
-                                               talloc_free(vector_slot(matchvec, i));
-                               }
-                               vector_free(matchvec);
-
-                               /* Make new matchvec. */
-                               matchvec = vector_init(INIT_MATCHVEC_SIZE);
-                               vector_set(matchvec, lcdstr);
-                               match_str = (char **)matchvec->index;
-                               vector_only_wrapper_free(matchvec);
-
-                               *status = CMD_COMPLETE_MATCH;
-                               return match_str;
-                       }
-               }
-       }
-
-       match_str = (char **)matchvec->index;
-       vector_only_wrapper_free(matchvec);
-       *status = CMD_COMPLETE_LIST_MATCH;
-       return match_str;
-}
-
-char **cmd_complete_command(vector vline, struct vty *vty, int *status)
-{
-       char **ret;
-
-       if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
-               enum node_type onode;
-               vector shifted_vline;
-               unsigned int index;
-
-               onode = vty->node;
-               vty->node = ENABLE_NODE;
-               /* We can try it on enable node, cos' the vty is authenticated */
-
-               shifted_vline = vector_init(vector_count(vline));
-               /* use memcpy? */
-               for (index = 1; index < vector_active(vline); index++) {
-                       vector_set_index(shifted_vline, index - 1,
-                                        vector_lookup(vline, index));
-               }
-
-               ret = cmd_complete_command_real(shifted_vline, vty, status);
-
-               vector_free(shifted_vline);
-               vty->node = onode;
-               return ret;
-       }
-
-       return cmd_complete_command_real(vline, vty, status);
-}
-
-/* return parent node */
-/* MUST eventually converge on CONFIG_NODE */
-enum node_type vty_go_parent(struct vty *vty)
-{
-       assert(vty->node > CONFIG_NODE);
-
-       switch (vty->node) {
-       case MS_NODE:
-               vty->node = CONFIG_NODE;
-               vty->index = NULL;
-               break;
-       case TESTSIM_NODE:
-               vty->node = MS_NODE;
-               break;
-#if 0
-       case BTS_NODE:
-               vty->node = GSMNET_NODE;
-               {
-                       /* set vty->index correctly ! */
-                       struct gsm_bts *bts = vty->index;
-                       vty->index = bts->network;
-               }
-               break;
-       case TRX_NODE:
-               vty->node = BTS_NODE;
-               {
-                       /* set vty->index correctly ! */
-                       struct gsm_bts_trx *trx = vty->index;
-                       vty->index = trx->bts;
-               }
-               break;
-       case TS_NODE:
-               vty->node = TRX_NODE;
-               {
-                       /* set vty->index correctly ! */
-                       struct gsm_bts_trx_ts *ts = vty->index;
-                       vty->index = ts->trx;
-               }
-               break;
-       case SUBSCR_NODE:
-               vty->node = VIEW_NODE;
-               subscr_put(vty->index);
-               vty->index = NULL;
-               break;
-#endif
-       default:
-               vty->node = CONFIG_NODE;
-       }
-
-       return vty->node;
-}
-
-/* Execute command by argument vline vector. */
-static int
-cmd_execute_command_real(vector vline, struct vty *vty,
-                        struct cmd_element **cmd)
-{
-       unsigned int i;
-       unsigned int index;
-       vector cmd_vector;
-       struct cmd_element *cmd_element;
-       struct cmd_element *matched_element;
-       unsigned int matched_count, incomplete_count;
-       int argc;
-       const char *argv[CMD_ARGC_MAX];
-       enum match_type match = 0;
-       int varflag;
-       char *command;
-
-       /* Make copy of command elements. */
-       cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));
-
-       for (index = 0; index < vector_active(vline); index++)
-               if ((command = vector_slot(vline, index))) {
-                       int ret;
-
-                       match =
-                           cmd_filter_by_completion(command, cmd_vector,
-                                                    index);
-
-                       if (match == vararg_match)
-                               break;
-
-                       ret =
-                           is_cmd_ambiguous(command, cmd_vector, index, match);
-
-                       if (ret == 1) {
-                               vector_free(cmd_vector);
-                               return CMD_ERR_AMBIGUOUS;
-                       } else if (ret == 2) {
-                               vector_free(cmd_vector);
-                               return CMD_ERR_NO_MATCH;
-                       }
-               }
-
-       /* Check matched count. */
-       matched_element = NULL;
-       matched_count = 0;
-       incomplete_count = 0;
-
-       for (i = 0; i < vector_active(cmd_vector); i++)
-               if ((cmd_element = vector_slot(cmd_vector, i))) {
-                       if (match == vararg_match
-                           || index >= cmd_element->cmdsize) {
-                               matched_element = cmd_element;
-#if 0
-                               printf("DEBUG: %s\n", cmd_element->string);
-#endif
-                               matched_count++;
-                       } else {
-                               incomplete_count++;
-                       }
-               }
-
-       /* Finish of using cmd_vector. */
-       vector_free(cmd_vector);
-
-       /* To execute command, matched_count must be 1. */
-       if (matched_count == 0) {
-               if (incomplete_count)
-                       return CMD_ERR_INCOMPLETE;
-               else
-                       return CMD_ERR_NO_MATCH;
-       }
-
-       if (matched_count > 1)
-               return CMD_ERR_AMBIGUOUS;
-
-       /* Argument treatment */
-       varflag = 0;
-       argc = 0;
-
-       for (i = 0; i < vector_active(vline); i++) {
-               if (varflag)
-                       argv[argc++] = vector_slot(vline, i);
-               else {
-                       vector descvec =
-                           vector_slot(matched_element->strvec, i);
-
-                       if (vector_active(descvec) == 1) {
-                               struct desc *desc = vector_slot(descvec, 0);
-
-                               if (CMD_VARARG(desc->cmd))
-                                       varflag = 1;
-
-                               if (varflag || CMD_VARIABLE(desc->cmd)
-                                   || CMD_OPTION(desc->cmd))
-                                       argv[argc++] = vector_slot(vline, i);
-                       } else
-                               argv[argc++] = vector_slot(vline, i);
-               }
-
-               if (argc >= CMD_ARGC_MAX)
-                       return CMD_ERR_EXEED_ARGC_MAX;
-       }
-
-       /* For vtysh execution. */
-       if (cmd)
-               *cmd = matched_element;
-
-       if (matched_element->daemon)
-               return CMD_SUCCESS_DAEMON;
-
-       /* Execute matched command. */
-       return (*matched_element->func) (matched_element, vty, argc, argv);
-}
-
-int
-cmd_execute_command(vector vline, struct vty *vty, struct cmd_element **cmd,
-                   int vtysh)
-{
-       int ret, saved_ret, tried = 0;
-       enum node_type onode;
-       void *oindex;
-
-       onode = vty->node;
-       oindex = vty->index;
-
-       if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
-               vector shifted_vline;
-               unsigned int index;
-
-               vty->node = ENABLE_NODE;
-               /* We can try it on enable node, cos' the vty is authenticated */
-
-               shifted_vline = vector_init(vector_count(vline));
-               /* use memcpy? */
-               for (index = 1; index < vector_active(vline); index++) {
-                       vector_set_index(shifted_vline, index - 1,
-                                        vector_lookup(vline, index));
-               }
-
-               ret = cmd_execute_command_real(shifted_vline, vty, cmd);
-
-               vector_free(shifted_vline);
-               vty->node = onode;
-               return ret;
-       }
-
-       saved_ret = ret = cmd_execute_command_real(vline, vty, cmd);
-
-       if (vtysh)
-               return saved_ret;
-
-       /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
-       while (ret != CMD_SUCCESS && ret != CMD_WARNING
-              && vty->node > CONFIG_NODE) {
-               vty_go_parent(vty);
-               ret = cmd_execute_command_real(vline, vty, cmd);
-               tried = 1;
-               if (ret == CMD_SUCCESS || ret == CMD_WARNING) {
-                       /* succesfull command, leave the node as is */
-                       return ret;
-               }
-       }
-       /* no command succeeded, reset the vty to the original node and
-          return the error for this node */
-       if (tried) {
-               vty->node = onode;
-               vty->index = oindex;
-       }
-       return saved_ret;
-}
-
-/* Execute command by argument readline. */
-int
-cmd_execute_command_strict(vector vline, struct vty *vty,
-                          struct cmd_element **cmd)
-{
-       unsigned int i;
-       unsigned int index;
-       vector cmd_vector;
-       struct cmd_element *cmd_element;
-       struct cmd_element *matched_element;
-       unsigned int matched_count, incomplete_count;
-       int argc;
-       const char *argv[CMD_ARGC_MAX];
-       int varflag;
-       enum match_type match = 0;
-       char *command;
-
-       /* Make copy of command element */
-       cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));
-
-       for (index = 0; index < vector_active(vline); index++)
-               if ((command = vector_slot(vline, index))) {
-                       int ret;
-
-                       match = cmd_filter_by_string(vector_slot(vline, index),
-                                                    cmd_vector, index);
-
-                       /* If command meets '.VARARG' then finish matching. */
-                       if (match == vararg_match)
-                               break;
-
-                       ret =
-                           is_cmd_ambiguous(command, cmd_vector, index, match);
-                       if (ret == 1) {
-                               vector_free(cmd_vector);
-                               return CMD_ERR_AMBIGUOUS;
-                       }
-                       if (ret == 2) {
-                               vector_free(cmd_vector);
-                               return CMD_ERR_NO_MATCH;
-                       }
-               }
-
-       /* Check matched count. */
-       matched_element = NULL;
-       matched_count = 0;
-       incomplete_count = 0;
-       for (i = 0; i < vector_active(cmd_vector); i++)
-               if (vector_slot(cmd_vector, i) != NULL) {
-                       cmd_element = vector_slot(cmd_vector, i);
-
-                       if (match == vararg_match
-                           || index >= cmd_element->cmdsize) {
-                               matched_element = cmd_element;
-                               matched_count++;
-                       } else
-                               incomplete_count++;
-               }
-
-       /* Finish of using cmd_vector. */
-       vector_free(cmd_vector);
-
-       /* To execute command, matched_count must be 1. */
-       if (matched_count == 0) {
-               if (incomplete_count)
-                       return CMD_ERR_INCOMPLETE;
-               else
-                       return CMD_ERR_NO_MATCH;
-       }
-
-       if (matched_count > 1)
-               return CMD_ERR_AMBIGUOUS;
-
-       /* Argument treatment */
-       varflag = 0;
-       argc = 0;
-
-       for (i = 0; i < vector_active(vline); i++) {
-               if (varflag)
-                       argv[argc++] = vector_slot(vline, i);
-               else {
-                       vector descvec =
-                           vector_slot(matched_element->strvec, i);
-
-                       if (vector_active(descvec) == 1) {
-                               struct desc *desc = vector_slot(descvec, 0);
-
-                               if (CMD_VARARG(desc->cmd))
-                                       varflag = 1;
-
-                               if (varflag || CMD_VARIABLE(desc->cmd)
-                                   || CMD_OPTION(desc->cmd))
-                                       argv[argc++] = vector_slot(vline, i);
-                       } else
-                               argv[argc++] = vector_slot(vline, i);
-               }
-
-               if (argc >= CMD_ARGC_MAX)
-                       return CMD_ERR_EXEED_ARGC_MAX;
-       }
-
-       /* For vtysh execution. */
-       if (cmd)
-               *cmd = matched_element;
-
-       if (matched_element->daemon)
-               return CMD_SUCCESS_DAEMON;
-
-       /* Now execute matched command */
-       return (*matched_element->func) (matched_element, vty, argc, argv);
-}
-
-/* Configration make from file. */
-int config_from_file(struct vty *vty, OSMOCOM_FILE * fp)
-{
-       int ret;
-       vector vline;
-
-       while (osmocom_fgets(vty->buf, VTY_BUFSIZ, fp)) {
-               vline = cmd_make_strvec(vty->buf);
-
-               /* In case of comment line */
-               if (vline == NULL)
-                       continue;
-               /* Execute configuration command : this is strict match */
-               ret = cmd_execute_command_strict(vline, vty, NULL);
-
-               /* Try again with setting node to CONFIG_NODE */
-               while (ret != CMD_SUCCESS && ret != CMD_WARNING
-                      && ret != CMD_ERR_NOTHING_TODO
-                      && vty->node != CONFIG_NODE) {
-                       vty_go_parent(vty);
-                       ret = cmd_execute_command_strict(vline, vty, NULL);
-               }
-
-               cmd_free_strvec(vline);
-
-               if (ret != CMD_SUCCESS && ret != CMD_WARNING
-                   && ret != CMD_ERR_NOTHING_TODO)
-                       return ret;
-       }
-       return CMD_SUCCESS;
-}
-
-/* Configration from terminal */
-DEFUN(config_terminal,
-      config_terminal_cmd,
-      "configure terminal",
-      "Configuration from vty interface\n" "Configuration terminal\n")
-{
-       if (vty_config_lock(vty))
-               vty->node = CONFIG_NODE;
-       else {
-               vty_out(vty, "VTY configuration is locked by other VTY%s",
-                       VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-       return CMD_SUCCESS;
-}
-
-/* Enable command */
-DEFUN(enable, config_enable_cmd, "enable", "Turn on privileged mode command\n")
-{
-       /* If enable password is NULL, change to ENABLE_NODE */
-       if ((host.enable == NULL && host.enable_encrypt == NULL) ||
-           vty->type == VTY_SHELL_SERV)
-               vty->node = ENABLE_NODE;
-       else
-               vty->node = AUTH_ENABLE_NODE;
-
-       return CMD_SUCCESS;
-}
-
-/* Disable command */
-DEFUN(disable,
-      config_disable_cmd, "disable", "Turn off privileged mode command\n")
-{
-       if (vty->node == ENABLE_NODE)
-               vty->node = VIEW_NODE;
-       return CMD_SUCCESS;
-}
-
-/* Down vty node level. */
-DEFUN(config_exit,
-      config_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
-{
-       switch (vty->node) {
-       case MS_NODE:
-               vty->node = CONFIG_NODE;
-               vty->index = NULL;
-               break;
-       case TESTSIM_NODE:
-               vty->node = MS_NODE;
-               break;
-#if 0
-       case BTS_NODE:
-               vty->node = GSMNET_NODE;
-               {
-                       /* set vty->index correctly ! */
-                       struct gsm_bts *bts = vty->index;
-                       vty->index = bts->network;
-               }
-               break;
-       case TRX_NODE:
-               vty->node = BTS_NODE;
-               {
-                       /* set vty->index correctly ! */
-                       struct gsm_bts_trx *trx = vty->index;
-                       vty->index = trx->bts;
-               }
-               break;
-       case TS_NODE:
-               vty->node = TRX_NODE;
-               {
-                       /* set vty->index correctly ! */
-                       struct gsm_bts_trx_ts *ts = vty->index;
-                       vty->index = ts->trx;
-               }
-               break;
-       case SUBSCR_NODE:
-               vty->node = VIEW_NODE;
-               subscr_put(vty->index);
-               vty->index = NULL;
-               break;
-#endif
-       case VIEW_NODE:
-       case ENABLE_NODE:
-               if (0)          //vty_shell (vty))
-                       exit(0);
-               else
-                       vty->status = VTY_CLOSE;
-               break;
-       case CONFIG_NODE:
-               vty->node = ENABLE_NODE;
-               vty_config_unlock(vty);
-               break;
-       case VTY_NODE:
-               vty->node = CONFIG_NODE;
-               break;
-       default:
-               break;
-       }
-       return CMD_SUCCESS;
-}
-
-/* quit is alias of exit. */
-ALIAS(config_exit,
-      config_quit_cmd, "quit", "Exit current mode and down to previous mode\n")
-
-/* End of configuration. */
-    DEFUN(config_end,
-      config_end_cmd, "end", "End current mode and change to enable mode.")
-{
-       switch (vty->node) {
-       case VIEW_NODE:
-       case ENABLE_NODE:
-               /* Nothing to do. */
-               break;
-       case CONFIG_NODE:
-       case VTY_NODE:
-       case MS_NODE:
-       case TESTSIM_NODE:
-               vty_config_unlock(vty);
-               vty->node = ENABLE_NODE;
-               break;
-       default:
-               break;
-       }
-       return CMD_SUCCESS;
-}
-
-/* Show version. */
-DEFUN(show_version,
-      show_version_cmd, "show version", SHOW_STR "Displays program version\n")
-{
-       vty_out(vty, "%s %s (%s).%s", QUAGGA_PROGNAME, QUAGGA_VERSION,
-               host.name ? host.name : "", VTY_NEWLINE);
-       vty_out(vty, "%s%s", QUAGGA_COPYRIGHT, VTY_NEWLINE);
-
-       return CMD_SUCCESS;
-}
-
-/* Help display function for all node. */
-DEFUN(config_help,
-      config_help_cmd, "help", "Description of the interactive help system\n")
-{
-       vty_out(vty,
-               "This VTY provides advanced help features.  When you need help,%s\
-anytime at the command line please press '?'.%s\
-%s\
-If nothing matches, the help list will be empty and you must backup%s\
- until entering a '?' shows the available options.%s\
-Two styles of help are provided:%s\
-1. Full help is available when you are ready to enter a%s\
-command argument (e.g. 'show ?') and describes each possible%s\
-argument.%s\
-2. Partial help is provided when an abbreviated argument is entered%s\
-   and you want to know what arguments match the input%s\
-   (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
-               VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
-       return CMD_SUCCESS;
-}
-
-/* Help display function for all node. */
-DEFUN(config_list, config_list_cmd, "list", "Print command list\n")
-{
-       unsigned int i;
-       struct cmd_node *cnode = vector_slot(cmdvec, vty->node);
-       struct cmd_element *cmd;
-
-       for (i = 0; i < vector_active(cnode->cmd_vector); i++)
-               if ((cmd = vector_slot(cnode->cmd_vector, i)) != NULL
-                   && !(cmd->attr == CMD_ATTR_DEPRECATED
-                        || cmd->attr == CMD_ATTR_HIDDEN))
-                       vty_out(vty, "  %s%s", cmd->string, VTY_NEWLINE);
-       return CMD_SUCCESS;
-}
-
-/* Write current configuration into file. */
-DEFUN(config_write_file,
-      config_write_file_cmd,
-      "write file",
-      "Write running configuration to memory, network, or terminal\n"
-      "Write to configuration file\n")
-{
-       unsigned int i;
-       int fd;
-       struct cmd_node *node;
-       char *config_file;
-       char *config_file_tmp = NULL;
-       char *config_file_sav = NULL;
-       struct vty *file_vty;
-
-       /* Check and see if we are operating under vtysh configuration */
-       if (host.config == NULL) {
-               vty_out(vty, "Can't save to configuration file, using vtysh.%s",
-                       VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       /* Get filename. */
-       config_file = host.config;
-
-       config_file_sav =
-           _talloc_zero(tall_vty_cmd_ctx,
-                        strlen(config_file) + strlen(CONF_BACKUP_EXT) + 1,
-                        "config_file_sav");
-       strcpy(config_file_sav, config_file);
-       strcat(config_file_sav, CONF_BACKUP_EXT);
-
-       config_file_tmp = _talloc_zero(tall_vty_cmd_ctx, strlen(config_file) + 8,
-                                       "config_file_tmp");
-       sprintf(config_file_tmp, "%s.XXXXXX", config_file);
-
-       /* Open file to configuration write. */
-       fd = OSMOCOM_MKSTEMP(config_file_tmp);
-       if (fd < 0) {
-               vty_out(vty, "Can't open configuration file %s.%s",
-                       config_file_tmp, VTY_NEWLINE);
-               talloc_free(config_file_tmp);
-               talloc_free(config_file_sav);
-               return CMD_WARNING;
-       }
-
-       /* Make vty for configuration file. */
-       file_vty = vty_new();
-       file_vty->fd = fd;
-       file_vty->type = VTY_FILE;
-
-       /* Config file header print. */
-       vty_out(file_vty, "!\n! Osmocom configuration saved from vty\n!   ");
-       //vty_time_print (file_vty, 1);
-       vty_out(file_vty, "!\n");
-
-       for (i = 0; i < vector_active(cmdvec); i++)
-               if ((node = vector_slot(cmdvec, i)) && node->func) {
-                       if ((*node->func) (file_vty))
-                               vty_out(file_vty, "!\n");
-               }
-       vty_close(file_vty);
-
-       if (OSMOCOM_UNLINK(config_file_sav) != 0)
-               if (errno != ENOENT) {
-                       vty_out(vty,
-                               "Can't unlink backup configuration file %s.%s",
-                               config_file_sav, VTY_NEWLINE);
-                       talloc_free(config_file_sav);
-                       talloc_free(config_file_tmp);
-                       OSMOCOM_UNLINK(config_file_tmp);
-                       return CMD_WARNING;
-               }
-       if (OSMOCOM_LINK(config_file, config_file_sav) != 0) {
-               vty_out(vty, "Can't backup old configuration file %s.%s",
-                       config_file_sav, VTY_NEWLINE);
-               talloc_free(config_file_sav);
-               talloc_free(config_file_tmp);
-               OSMOCOM_UNLINK(config_file_tmp);
-               return CMD_WARNING;
-       }
-       sync();
-       if (OSMOCOM_UNLINK(config_file) != 0) {
-               vty_out(vty, "Can't unlink configuration file %s.%s",
-                       config_file, VTY_NEWLINE);
-               talloc_free(config_file_sav);
-               talloc_free(config_file_tmp);
-               OSMOCOM_UNLINK(config_file_tmp);
-               return CMD_WARNING;
-       }
-       if (OSMOCOM_LINK(config_file_tmp, config_file) != 0) {
-               vty_out(vty, "Can't save configuration file %s.%s", config_file,
-                       VTY_NEWLINE);
-               talloc_free(config_file_sav);
-               talloc_free(config_file_tmp);
-               OSMOCOM_UNLINK(config_file_tmp);
-               return CMD_WARNING;
-       }
-       OSMOCOM_UNLINK(config_file_tmp);
-       sync();
-
-       talloc_free(config_file_sav);
-       talloc_free(config_file_tmp);
-
-       if (OSMOCOM_CHMOD(config_file, 0666 & ~CONFIGFILE_MASK) != 0) {
-               vty_out(vty, "Can't chmod configuration file %s: %s (%d).%s",
-                       config_file, strerror(errno), errno, VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       vty_out(vty, "Configuration saved to %s%s", config_file, VTY_NEWLINE);
-       return CMD_SUCCESS;
-}
-
-ALIAS(config_write_file,
-      config_write_cmd,
-      "write", "Write running configuration to memory, network, or terminal\n")
-
-    ALIAS(config_write_file,
-      config_write_memory_cmd,
-      "write memory",
-      "Write running configuration to memory, network, or terminal\n"
-      "Write configuration to the file (same as write file)\n")
-
-    ALIAS(config_write_file,
-      copy_runningconfig_startupconfig_cmd,
-      "copy running-config startup-config",
-      "Copy configuration\n"
-      "Copy running config to... \n"
-      "Copy running config to startup config (same as write file)\n")
-
-/* Write current configuration into the terminal. */
-    DEFUN(config_write_terminal,
-      config_write_terminal_cmd,
-      "write terminal",
-      "Write running configuration to memory, network, or terminal\n"
-      "Write to terminal\n")
-{
-       unsigned int i;
-       struct cmd_node *node;
-
-       if (vty->type == VTY_SHELL_SERV) {
-               for (i = 0; i < vector_active(cmdvec); i++)
-                       if ((node = vector_slot(cmdvec, i)) && node->func
-                           && node->vtysh) {
-                               if ((*node->func) (vty))
-                                       vty_out(vty, "!%s", VTY_NEWLINE);
-                       }
-       } else {
-               vty_out(vty, "%sCurrent configuration:%s", VTY_NEWLINE,
-                       VTY_NEWLINE);
-               vty_out(vty, "!%s", VTY_NEWLINE);
-
-               for (i = 0; i < vector_active(cmdvec); i++)
-                       if ((node = vector_slot(cmdvec, i)) && node->func) {
-                               if ((*node->func) (vty))
-                                       vty_out(vty, "!%s", VTY_NEWLINE);
-                       }
-               vty_out(vty, "end%s", VTY_NEWLINE);
-       }
-       return CMD_SUCCESS;
-}
-
-/* Write current configuration into the terminal. */
-ALIAS(config_write_terminal,
-      show_running_config_cmd,
-      "show running-config", SHOW_STR "running configuration\n")
-
-/* Write startup configuration into the terminal. */
-    DEFUN(show_startup_config,
-      show_startup_config_cmd,
-      "show startup-config", SHOW_STR "Contentes of startup configuration\n")
-{
-       char buf[BUFSIZ];
-       OSMOCOM_FILE *confp;
-
-       confp = osmocom_fopen(host.config, "r");
-       if (confp == NULL) {
-               vty_out(vty, "Can't open configuration file [%s]%s",
-                       host.config, VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       while (osmocom_fgets(buf, BUFSIZ, confp)) {
-               char *cp = buf;
-
-               while (*cp != '\r' && *cp != '\n' && *cp != '\0')
-                       cp++;
-               *cp = '\0';
-
-               vty_out(vty, "%s%s", buf, VTY_NEWLINE);
-       }
-
-       osmocom_fclose(confp);
-
-       return CMD_SUCCESS;
-}
-
-/* Hostname configuration */
-DEFUN(config_hostname,
-      hostname_cmd,
-      "hostname WORD",
-      "Set system's network name\n" "This system's network name\n")
-{
-       if (!isalpha((int)*argv[0])) {
-               vty_out(vty, "Please specify string starting with alphabet%s",
-                       VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       if (host.name)
-               talloc_free(host.name);
-
-       host.name = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_no_hostname,
-      no_hostname_cmd,
-      "no hostname [HOSTNAME]",
-      NO_STR "Reset system's network name\n" "Host name of this router\n")
-{
-       if (host.name)
-               talloc_free(host.name);
-       host.name = NULL;
-       return CMD_SUCCESS;
-}
-
-/* VTY interface password set. */
-DEFUN(config_password, password_cmd,
-      "password (8|) WORD",
-      "Assign the terminal connection password\n"
-      "Specifies a HIDDEN password will follow\n"
-      "dummy string \n" "The HIDDEN line password string\n")
-{
-       /* Argument check. */
-       if (argc == 0) {
-               vty_out(vty, "Please specify password.%s", VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       if (argc == 2) {
-               if (*argv[0] == '8') {
-                       if (host.password)
-                               talloc_free(host.password);
-                       host.password = NULL;
-                       if (host.password_encrypt)
-                               talloc_free(host.password_encrypt);
-                       host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, argv[1]);
-                       return CMD_SUCCESS;
-               } else {
-                       vty_out(vty, "Unknown encryption type.%s", VTY_NEWLINE);
-                       return CMD_WARNING;
-               }
-       }
-
-       if (!isalnum((int)*argv[0])) {
-               vty_out(vty,
-                       "Please specify string starting with alphanumeric%s",
-                       VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       if (host.password)
-               talloc_free(host.password);
-       host.password = NULL;
-
-#ifdef VTY_CRYPT_PW
-       if (host.encrypt) {
-               if (host.password_encrypt)
-                       talloc_free(host.password_encrypt);
-               host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(argv[0]));
-       } else
-#endif
-               host.password = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
-
-       return CMD_SUCCESS;
-}
-
-ALIAS(config_password, password_text_cmd,
-      "password LINE",
-      "Assign the terminal connection password\n"
-      "The UNENCRYPTED (cleartext) line password\n")
-
-/* VTY enable password set. */
-    DEFUN(config_enable_password, enable_password_cmd,
-      "enable password (8|) WORD",
-      "Modify enable password parameters\n"
-      "Assign the privileged level password\n"
-      "Specifies a HIDDEN password will follow\n"
-      "dummy string \n" "The HIDDEN 'enable' password string\n")
-{
-       /* Argument check. */
-       if (argc == 0) {
-               vty_out(vty, "Please specify password.%s", VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       /* Crypt type is specified. */
-       if (argc == 2) {
-               if (*argv[0] == '8') {
-                       if (host.enable)
-                               talloc_free(host.enable);
-                       host.enable = NULL;
-
-                       if (host.enable_encrypt)
-                               talloc_free(host.enable_encrypt);
-                       host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, argv[1]);
-
-                       return CMD_SUCCESS;
-               } else {
-                       vty_out(vty, "Unknown encryption type.%s", VTY_NEWLINE);
-                       return CMD_WARNING;
-               }
-       }
-
-       if (!isalnum((int)*argv[0])) {
-               vty_out(vty,
-                       "Please specify string starting with alphanumeric%s",
-                       VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       if (host.enable)
-               talloc_free(host.enable);
-       host.enable = NULL;
-
-       /* Plain password input. */
-#ifdef VTY_CRYPT_PW
-       if (host.encrypt) {
-               if (host.enable_encrypt)
-                       talloc_free(host.enable_encrypt);
-               host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(argv[0]));
-       } else
-#endif
-               host.enable = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
-
-       return CMD_SUCCESS;
-}
-
-ALIAS(config_enable_password,
-      enable_password_text_cmd,
-      "enable password LINE",
-      "Modify enable password parameters\n"
-      "Assign the privileged level password\n"
-      "The UNENCRYPTED (cleartext) 'enable' password\n")
-
-/* VTY enable password delete. */
-    DEFUN(no_config_enable_password, no_enable_password_cmd,
-      "no enable password",
-      NO_STR
-      "Modify enable password parameters\n"
-      "Assign the privileged level password\n")
-{
-       if (host.enable)
-               talloc_free(host.enable);
-       host.enable = NULL;
-
-       if (host.enable_encrypt)
-               talloc_free(host.enable_encrypt);
-       host.enable_encrypt = NULL;
-
-       return CMD_SUCCESS;
-}
-
-#ifdef VTY_CRYPT_PW
-DEFUN(service_password_encrypt,
-      service_password_encrypt_cmd,
-      "service password-encryption",
-      "Set up miscellaneous service\n" "Enable encrypted passwords\n")
-{
-       if (host.encrypt)
-               return CMD_SUCCESS;
-
-       host.encrypt = 1;
-
-       if (host.password) {
-               if (host.password_encrypt)
-                       talloc_free(host.password_encrypt);
-               host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(host.password));
-       }
-       if (host.enable) {
-               if (host.enable_encrypt)
-                       talloc_free(host.enable_encrypt);
-               host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(host.enable));
-       }
-
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_service_password_encrypt,
-      no_service_password_encrypt_cmd,
-      "no service password-encryption",
-      NO_STR "Set up miscellaneous service\n" "Enable encrypted passwords\n")
-{
-       if (!host.encrypt)
-               return CMD_SUCCESS;
-
-       host.encrypt = 0;
-
-       if (host.password_encrypt)
-               talloc_free(host.password_encrypt);
-       host.password_encrypt = NULL;
-
-       if (host.enable_encrypt)
-               talloc_free(host.enable_encrypt);
-       host.enable_encrypt = NULL;
-
-       return CMD_SUCCESS;
-}
-#endif
-
-DEFUN(config_terminal_length, config_terminal_length_cmd,
-      "terminal length <0-512>",
-      "Set terminal line parameters\n"
-      "Set number of lines on a screen\n"
-      "Number of lines on screen (0 for no pausing)\n")
-{
-       int lines;
-       char *endptr = NULL;
-
-       lines = strtol(argv[0], &endptr, 10);
-       if (lines < 0 || lines > 512 || *endptr != '\0') {
-               vty_out(vty, "length is malformed%s", VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-       vty->lines = lines;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_terminal_no_length, config_terminal_no_length_cmd,
-      "terminal no length",
-      "Set terminal line parameters\n"
-      NO_STR "Set number of lines on a screen\n")
-{
-       vty->lines = -1;
-       return CMD_SUCCESS;
-}
-
-DEFUN(service_terminal_length, service_terminal_length_cmd,
-      "service terminal-length <0-512>",
-      "Set up miscellaneous service\n"
-      "System wide terminal length configuration\n"
-      "Number of lines of VTY (0 means no line control)\n")
-{
-       int lines;
-       char *endptr = NULL;
-
-       lines = strtol(argv[0], &endptr, 10);
-       if (lines < 0 || lines > 512 || *endptr != '\0') {
-               vty_out(vty, "length is malformed%s", VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-       host.lines = lines;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_service_terminal_length, no_service_terminal_length_cmd,
-      "no service terminal-length [<0-512>]",
-      NO_STR
-      "Set up miscellaneous service\n"
-      "System wide terminal length configuration\n"
-      "Number of lines of VTY (0 means no line control)\n")
-{
-       host.lines = -1;
-       return CMD_SUCCESS;
-}
-
-DEFUN_HIDDEN(do_echo,
-            echo_cmd,
-            "echo .MESSAGE",
-            "Echo a message back to the vty\n" "The message to echo\n")
-{
-       char *message;
-
-       vty_out(vty, "%s%s",
-               ((message =
-                 argv_concat(argv, argc, 0)) ? message : ""), VTY_NEWLINE);
-       if (message)
-               talloc_free(message);
-       return CMD_SUCCESS;
-}
-
-#if 0
-DEFUN(config_logmsg,
-      config_logmsg_cmd,
-      "logmsg " LOG_LEVELS " .MESSAGE",
-      "Send a message to enabled logging destinations\n"
-      LOG_LEVEL_DESC "The message to send\n")
-{
-       int level;
-       char *message;
-
-       if ((level = level_match(argv[0])) == ZLOG_DISABLED)
-               return CMD_ERR_NO_MATCH;
-
-       zlog(NULL, level,
-            ((message = argv_concat(argv, argc, 1)) ? message : ""));
-       if (message)
-               talloc_free(message);
-       return CMD_SUCCESS;
-}
-
-DEFUN(show_logging,
-      show_logging_cmd,
-      "show logging", SHOW_STR "Show current logging configuration\n")
-{
-       struct zlog *zl = zlog_default;
-
-       vty_out(vty, "Syslog logging: ");
-       if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED)
-               vty_out(vty, "disabled");
-       else
-               vty_out(vty, "level %s, facility %s, ident %s",
-                       zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]],
-                       facility_name(zl->facility), zl->ident);
-       vty_out(vty, "%s", VTY_NEWLINE);
-
-       vty_out(vty, "Stdout logging: ");
-       if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED)
-               vty_out(vty, "disabled");
-       else
-               vty_out(vty, "level %s",
-                       zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]);
-       vty_out(vty, "%s", VTY_NEWLINE);
-
-       vty_out(vty, "Monitor logging: ");
-       if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
-               vty_out(vty, "disabled");
-       else
-               vty_out(vty, "level %s",
-                       zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]);
-       vty_out(vty, "%s", VTY_NEWLINE);
-
-       vty_out(vty, "File logging: ");
-       if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || !zl->fp)
-               vty_out(vty, "disabled");
-       else
-               vty_out(vty, "level %s, filename %s",
-                       zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]],
-                       zl->filename);
-       vty_out(vty, "%s", VTY_NEWLINE);
-
-       vty_out(vty, "Protocol name: %s%s",
-               zlog_proto_names[zl->protocol], VTY_NEWLINE);
-       vty_out(vty, "Record priority: %s%s",
-               (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE);
-
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_log_stdout,
-      config_log_stdout_cmd,
-      "log stdout", "Logging control\n" "Set stdout logging level\n")
-{
-       zlog_set_level(NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl);
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_log_stdout_level,
-      config_log_stdout_level_cmd,
-      "log stdout " LOG_LEVELS,
-      "Logging control\n" "Set stdout logging level\n" LOG_LEVEL_DESC)
-{
-       int level;
-
-       if ((level = level_match(argv[0])) == ZLOG_DISABLED)
-               return CMD_ERR_NO_MATCH;
-       zlog_set_level(NULL, ZLOG_DEST_STDOUT, level);
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_stdout,
-      no_config_log_stdout_cmd,
-      "no log stdout [LEVEL]",
-      NO_STR "Logging control\n" "Cancel logging to stdout\n" "Logging level\n")
-{
-       zlog_set_level(NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_log_monitor,
-      config_log_monitor_cmd,
-      "log monitor",
-      "Logging control\n" "Set terminal line (monitor) logging level\n")
-{
-       zlog_set_level(NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl);
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_log_monitor_level,
-      config_log_monitor_level_cmd,
-      "log monitor " LOG_LEVELS,
-      "Logging control\n"
-      "Set terminal line (monitor) logging level\n" LOG_LEVEL_DESC)
-{
-       int level;
-
-       if ((level = level_match(argv[0])) == ZLOG_DISABLED)
-               return CMD_ERR_NO_MATCH;
-       zlog_set_level(NULL, ZLOG_DEST_MONITOR, level);
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_monitor,
-      no_config_log_monitor_cmd,
-      "no log monitor [LEVEL]",
-      NO_STR
-      "Logging control\n"
-      "Disable terminal line (monitor) logging\n" "Logging level\n")
-{
-       zlog_set_level(NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
-       return CMD_SUCCESS;
-}
-
-static int set_log_file(struct vty *vty, const char *fname, int loglevel)
-{
-       int ret;
-       char *p = NULL;
-       const char *fullpath;
-
-       /* Path detection. */
-       if (!IS_DIRECTORY_SEP(*fname)) {
-               char cwd[MAXPATHLEN + 1];
-               cwd[MAXPATHLEN] = '\0';
-
-               if (getcwd(cwd, MAXPATHLEN) == NULL) {
-                       zlog_err("config_log_file: Unable to alloc mem!");
-                       return CMD_WARNING;
-               }
-
-               if ((p = _talloc_zero(tall_vcmd_ctx,
-                                     strlen(cwd) + strlen(fname) + 2),
-                                     "set_log_file")
-                   == NULL) {
-                       zlog_err("config_log_file: Unable to alloc mem!");
-                       return CMD_WARNING;
-               }
-               sprintf(p, "%s/%s", cwd, fname);
-               fullpath = p;
-       } else
-               fullpath = fname;
-
-       ret = zlog_set_file(NULL, fullpath, loglevel);
-
-       if (p)
-               talloc_free(p);
-
-       if (!ret) {
-               vty_out(vty, "can't open logfile %s\n", fname);
-               return CMD_WARNING;
-       }
-
-       if (host.logfile)
-               talloc_free(host.logfile);
-
-       host.logfile = talloc_strdup(tall_vty_cmd_ctx, fname);
-
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_log_file,
-      config_log_file_cmd,
-      "log file FILENAME",
-      "Logging control\n" "Logging to file\n" "Logging filename\n")
-{
-       return set_log_file(vty, argv[0], zlog_default->default_lvl);
-}
-
-DEFUN(config_log_file_level,
-      config_log_file_level_cmd,
-      "log file FILENAME " LOG_LEVELS,
-      "Logging control\n"
-      "Logging to file\n" "Logging filename\n" LOG_LEVEL_DESC)
-{
-       int level;
-
-       if ((level = level_match(argv[1])) == ZLOG_DISABLED)
-               return CMD_ERR_NO_MATCH;
-       return set_log_file(vty, argv[0], level);
-}
-
-DEFUN(no_config_log_file,
-      no_config_log_file_cmd,
-      "no log file [FILENAME]",
-      NO_STR
-      "Logging control\n" "Cancel logging to file\n" "Logging file name\n")
-{
-       zlog_reset_file(NULL);
-
-       if (host.logfile)
-               talloc_free(host.logfile);
-
-       host.logfile = NULL;
-
-       return CMD_SUCCESS;
-}
-
-ALIAS(no_config_log_file,
-      no_config_log_file_level_cmd,
-      "no log file FILENAME LEVEL",
-      NO_STR
-      "Logging control\n"
-      "Cancel logging to file\n" "Logging file name\n" "Logging level\n")
-
-    DEFUN(config_log_syslog,
-      config_log_syslog_cmd,
-      "log syslog", "Logging control\n" "Set syslog logging level\n")
-{
-       zlog_set_level(NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_log_syslog_level,
-      config_log_syslog_level_cmd,
-      "log syslog " LOG_LEVELS,
-      "Logging control\n" "Set syslog logging level\n" LOG_LEVEL_DESC)
-{
-       int level;
-
-       if ((level = level_match(argv[0])) == ZLOG_DISABLED)
-               return CMD_ERR_NO_MATCH;
-       zlog_set_level(NULL, ZLOG_DEST_SYSLOG, level);
-       return CMD_SUCCESS;
-}
-
-DEFUN_DEPRECATED(config_log_syslog_facility,
-                config_log_syslog_facility_cmd,
-                "log syslog facility " LOG_FACILITIES,
-                "Logging control\n"
-                "Logging goes to syslog\n"
-                "(Deprecated) Facility parameter for syslog messages\n"
-                LOG_FACILITY_DESC)
-{
-       int facility;
-
-       if ((facility = facility_match(argv[0])) < 0)
-               return CMD_ERR_NO_MATCH;
-
-       zlog_set_level(NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
-       zlog_default->facility = facility;
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_syslog,
-      no_config_log_syslog_cmd,
-      "no log syslog [LEVEL]",
-      NO_STR "Logging control\n" "Cancel logging to syslog\n" "Logging level\n")
-{
-       zlog_set_level(NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
-       return CMD_SUCCESS;
-}
-
-ALIAS(no_config_log_syslog,
-      no_config_log_syslog_facility_cmd,
-      "no log syslog facility " LOG_FACILITIES,
-      NO_STR
-      "Logging control\n"
-      "Logging goes to syslog\n"
-      "Facility parameter for syslog messages\n" LOG_FACILITY_DESC)
-
-    DEFUN(config_log_facility,
-      config_log_facility_cmd,
-      "log facility " LOG_FACILITIES,
-      "Logging control\n"
-      "Facility parameter for syslog messages\n" LOG_FACILITY_DESC)
-{
-       int facility;
-
-       if ((facility = facility_match(argv[0])) < 0)
-               return CMD_ERR_NO_MATCH;
-       zlog_default->facility = facility;
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_facility,
-      no_config_log_facility_cmd,
-      "no log facility [FACILITY]",
-      NO_STR
-      "Logging control\n"
-      "Reset syslog facility to default (daemon)\n" "Syslog facility\n")
-{
-       zlog_default->facility = LOG_DAEMON;
-       return CMD_SUCCESS;
-}
-
-DEFUN_DEPRECATED(config_log_trap,
-                config_log_trap_cmd,
-                "log trap " LOG_LEVELS,
-                "Logging control\n"
-                "(Deprecated) Set logging level and default for all destinations\n"
-                LOG_LEVEL_DESC)
-{
-       int new_level;
-       int i;
-
-       if ((new_level = level_match(argv[0])) == ZLOG_DISABLED)
-               return CMD_ERR_NO_MATCH;
-
-       zlog_default->default_lvl = new_level;
-       for (i = 0; i < ZLOG_NUM_DESTS; i++)
-               if (zlog_default->maxlvl[i] != ZLOG_DISABLED)
-                       zlog_default->maxlvl[i] = new_level;
-       return CMD_SUCCESS;
-}
-
-DEFUN_DEPRECATED(no_config_log_trap,
-                no_config_log_trap_cmd,
-                "no log trap [LEVEL]",
-                NO_STR
-                "Logging control\n"
-                "Permit all logging information\n" "Logging level\n")
-{
-       zlog_default->default_lvl = LOG_DEBUG;
-       return CMD_SUCCESS;
-}
-
-DEFUN(config_log_record_priority,
-      config_log_record_priority_cmd,
-      "log record-priority",
-      "Logging control\n"
-      "Log the priority of the message within the message\n")
-{
-       zlog_default->record_priority = 1;
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_record_priority,
-      no_config_log_record_priority_cmd,
-      "no log record-priority",
-      NO_STR
-      "Logging control\n"
-      "Do not log the priority of the message within the message\n")
-{
-       zlog_default->record_priority = 0;
-       return CMD_SUCCESS;
-}
-#endif
-
-DEFUN(banner_motd_file,
-      banner_motd_file_cmd,
-      "banner motd file [FILE]",
-      "Set banner\n" "Banner for motd\n" "Banner from a file\n" "Filename\n")
-{
-       if (host.motdfile)
-               talloc_free(host.motdfile);
-       host.motdfile = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
-
-       return CMD_SUCCESS;
-}
-
-DEFUN(banner_motd_default,
-      banner_motd_default_cmd,
-      "banner motd default",
-      "Set banner string\n" "Strings for motd\n" "Default string\n")
-{
-       host.motd = default_motd;
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_banner_motd,
-      no_banner_motd_cmd,
-      "no banner motd", NO_STR "Set banner string\n" "Strings for motd\n")
-{
-       host.motd = NULL;
-       if (host.motdfile)
-               talloc_free(host.motdfile);
-       host.motdfile = NULL;
-       return CMD_SUCCESS;
-}
-
-/* Set config filename.  Called from vty.c */
-void host_config_set(const char *filename)
-{
-       host.config = talloc_strdup(tall_vty_cmd_ctx, filename);
-}
-
-void install_default(enum node_type node)
-{
-       install_element(node, &config_exit_cmd);
-       install_element(node, &config_quit_cmd);
-       install_element(node, &config_end_cmd);
-       install_element(node, &config_help_cmd);
-       install_element(node, &config_list_cmd);
-
-       install_element(node, &config_write_terminal_cmd);
-       install_element(node, &config_write_file_cmd);
-       install_element(node, &config_write_memory_cmd);
-       install_element(node, &config_write_cmd);
-       install_element(node, &show_running_config_cmd);
-}
-
-/* Initialize command interface. Install basic nodes and commands. */
-void cmd_init(int terminal)
-{
-       /* Allocate initial top vector of commands. */
-       cmdvec = vector_init(VECTOR_MIN_SIZE);
-
-       /* Default host value settings. */
-       host.name = NULL;
-       host.password = NULL;
-       host.enable = NULL;
-       host.logfile = NULL;
-       host.config = NULL;
-       host.lines = -1;
-       host.motd = default_motd;
-       host.motdfile = NULL;
-
-       /* Install top nodes. */
-       install_node(&view_node, NULL);
-       install_node(&enable_node, NULL);
-       install_node(&auth_node, NULL);
-       install_node(&auth_enable_node, NULL);
-       install_node(&config_node, config_write_host);
-
-       /* Each node's basic commands. */
-       install_element(VIEW_NODE, &show_version_cmd);
-       if (terminal) {
-               install_element(VIEW_NODE, &config_list_cmd);
-               install_element(VIEW_NODE, &config_exit_cmd);
-               install_element(VIEW_NODE, &config_quit_cmd);
-               install_element(VIEW_NODE, &config_help_cmd);
-               install_element(VIEW_NODE, &config_enable_cmd);
-               install_element(VIEW_NODE, &config_terminal_length_cmd);
-               install_element(VIEW_NODE, &config_terminal_no_length_cmd);
-               install_element(VIEW_NODE, &echo_cmd);
-       }
-
-       if (terminal) {
-               install_default(ENABLE_NODE);
-               install_element(ENABLE_NODE, &config_disable_cmd);
-               install_element(ENABLE_NODE, &config_terminal_cmd);
-               install_element (ENABLE_NODE, &copy_runningconfig_startupconfig_cmd);
-       }
-       install_element (ENABLE_NODE, &show_startup_config_cmd);
-       install_element(ENABLE_NODE, &show_version_cmd);
-
-       if (terminal) {
-               install_element(ENABLE_NODE, &config_terminal_length_cmd);
-               install_element(ENABLE_NODE, &config_terminal_no_length_cmd);
-               install_element(ENABLE_NODE, &echo_cmd);
-
-               install_default(CONFIG_NODE);
-       }
-
-       install_element(CONFIG_NODE, &hostname_cmd);
-       install_element(CONFIG_NODE, &no_hostname_cmd);
-
-       if (terminal) {
-               install_element(CONFIG_NODE, &password_cmd);
-               install_element(CONFIG_NODE, &password_text_cmd);
-               install_element(CONFIG_NODE, &enable_password_cmd);
-               install_element(CONFIG_NODE, &enable_password_text_cmd);
-               install_element(CONFIG_NODE, &no_enable_password_cmd);
-
-#ifdef VTY_CRYPT_PW
-               install_element(CONFIG_NODE, &service_password_encrypt_cmd);
-               install_element(CONFIG_NODE, &no_service_password_encrypt_cmd);
-#endif
-               install_element(CONFIG_NODE, &banner_motd_default_cmd);
-               install_element(CONFIG_NODE, &banner_motd_file_cmd);
-               install_element(CONFIG_NODE, &no_banner_motd_cmd);
-               install_element(CONFIG_NODE, &service_terminal_length_cmd);
-               install_element(CONFIG_NODE, &no_service_terminal_length_cmd);
-
-       }
-//???  srand(time(NULL));
-}
diff --git a/src/host/layer23/src/vty/vector.c b/src/host/layer23/src/vty/vector.c
deleted file mode 100644 (file)
index db47ae5..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Generic vector interface routine
- * Copyright (C) 1997 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra 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, or (at your option) any
- * later version.
- *
- * GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <vty/vector.h>
-#include <vty/vty.h>
-#include <osmocore/talloc.h>
-#include <memory.h>
-
-void *tall_vty_vec_ctx;
-
-/* Initialize vector : allocate memory and return vector. */
-vector vector_init(unsigned int size)
-{
-       vector v = talloc_zero(tall_vty_vec_ctx, struct _vector);
-       if (!v)
-               return NULL;
-
-       /* allocate at least one slot */
-       if (size == 0)
-               size = 1;
-
-       v->alloced = size;
-       v->active = 0;
-       v->index = _talloc_zero(tall_vty_vec_ctx, sizeof(void *) * size,
-                               "vector_init:index");
-       if (!v->index) {
-               talloc_free(v);
-               return NULL;
-       }
-       return v;
-}
-
-void vector_only_wrapper_free(vector v)
-{
-       talloc_free(v);
-}
-
-void vector_only_index_free(void *index)
-{
-       talloc_free(index);
-}
-
-void vector_free(vector v)
-{
-       talloc_free(v->index);
-       talloc_free(v);
-}
-
-vector vector_copy(vector v)
-{
-       unsigned int size;
-       vector new = talloc_zero(tall_vty_vec_ctx, struct _vector);
-       if (!new)
-               return NULL;
-
-       new->active = v->active;
-       new->alloced = v->alloced;
-
-       size = sizeof(void *) * (v->alloced);
-       new->index = _talloc_zero(tall_vty_vec_ctx, size, "vector_copy:index");
-       if (!new->index) {
-               talloc_free(new);
-               return NULL;
-       }
-       memcpy(new->index, v->index, size);
-
-       return new;
-}
-
-/* Check assigned index, and if it runs short double index pointer */
-void vector_ensure(vector v, unsigned int num)
-{
-       if (v->alloced > num)
-               return;
-
-       v->index = talloc_realloc_size(tall_vty_vec_ctx, v->index,
-                                      sizeof(void *) * (v->alloced * 2));
-       memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced);
-       v->alloced *= 2;
-
-       if (v->alloced <= num)
-               vector_ensure(v, num);
-}
-
-/* This function only returns next empty slot index.  It dose not mean
-   the slot's index memory is assigned, please call vector_ensure()
-   after calling this function. */
-int vector_empty_slot(vector v)
-{
-       unsigned int i;
-
-       if (v->active == 0)
-               return 0;
-
-       for (i = 0; i < v->active; i++)
-               if (v->index[i] == 0)
-                       return i;
-
-       return i;
-}
-
-/* Set value to the smallest empty slot. */
-int vector_set(vector v, void *val)
-{
-       unsigned int i;
-
-       i = vector_empty_slot(v);
-       vector_ensure(v, i);
-
-       v->index[i] = val;
-
-       if (v->active <= i)
-               v->active = i + 1;
-
-       return i;
-}
-
-/* Set value to specified index slot. */
-int vector_set_index(vector v, unsigned int i, void *val)
-{
-       vector_ensure(v, i);
-
-       v->index[i] = val;
-
-       if (v->active <= i)
-               v->active = i + 1;
-
-       return i;
-}
-
-/* Look up vector.  */
-void *vector_lookup(vector v, unsigned int i)
-{
-       if (i >= v->active)
-               return NULL;
-       return v->index[i];
-}
-
-/* Lookup vector, ensure it. */
-void *vector_lookup_ensure(vector v, unsigned int i)
-{
-       vector_ensure(v, i);
-       return v->index[i];
-}
-
-/* Unset value at specified index slot. */
-void vector_unset(vector v, unsigned int i)
-{
-       if (i >= v->alloced)
-               return;
-
-       v->index[i] = NULL;
-
-       if (i + 1 == v->active) {
-               v->active--;
-               while (i && v->index[--i] == NULL && v->active--) ;     /* Is this ugly ? */
-       }
-}
-
-/* Count the number of not emplty slot. */
-unsigned int vector_count(vector v)
-{
-       unsigned int i;
-       unsigned count = 0;
-
-       for (i = 0; i < v->active; i++)
-               if (v->index[i] != NULL)
-                       count++;
-
-       return count;
-}
diff --git a/src/host/layer23/src/vty/vty.c b/src/host/layer23/src/vty/vty.c
deleted file mode 100644 (file)
index 1884cf2..0000000
+++ /dev/null
@@ -1,1679 +0,0 @@
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <termios.h>
-
-#include <sys/utsname.h>
-#include <sys/param.h>
-
-#include <arpa/telnet.h>
-
-#include "cardshell.h"
-#include <vty/vty.h>
-#include <vty/command.h>
-#include <vty/buffer.h>
-#include <osmocore/talloc.h>
-#include <osmocom/file.h>
-
-/* our callback, located in telnet_interface.c */
-void vty_event(enum event event, int sock, struct vty *vty);
-
-extern struct host host;
-
-/* Vector which store each vty structure. */
-static vector vtyvec;
-
-vector Vvty_serv_thread;
-
-char *vty_cwd = NULL;
-
-/* Configure lock. */
-static int vty_config;
-
-static int no_password_check = 1;
-
-void *tall_vty_ctx;
-
-static void vty_clear_buf(struct vty *vty)
-{
-       memset(vty->buf, 0, vty->max);
-}
-
-/* Allocate new vty struct. */
-struct vty *vty_new()
-{
-       struct vty *new = talloc_zero(tall_vty_ctx, struct vty);
-
-       if (!new)
-               goto out;
-
-       new->obuf = buffer_new(0);      /* Use default buffer size. */
-       if (!new->obuf)
-               goto out_new;
-       new->buf = _talloc_zero(tall_vty_ctx, VTY_BUFSIZ, "vty_new->buf");
-       if (!new->buf)
-               goto out_obuf;
-
-       new->max = VTY_BUFSIZ;
-
-       return new;
-
-out_obuf:
-       buffer_free(new->obuf);
-out_new:
-       talloc_free(new);
-       new = NULL;
-out:
-       return new;
-}
-
-/* Authentication of vty */
-static void vty_auth(struct vty *vty, char *buf)
-{
-       char *passwd = NULL;
-       enum node_type next_node = 0;
-       int fail;
-       char *crypt(const char *, const char *);
-
-       switch (vty->node) {
-       case AUTH_NODE:
-#ifdef VTY_CRYPT_PW
-               if (host.encrypt)
-                       passwd = host.password_encrypt;
-               else
-#endif
-                       passwd = host.password;
-               if (host.advanced)
-                       next_node = host.enable ? VIEW_NODE : ENABLE_NODE;
-               else
-                       next_node = VIEW_NODE;
-               break;
-       case AUTH_ENABLE_NODE:
-#ifdef VTY_CRYPT_PW
-               if (host.encrypt)
-                       passwd = host.enable_encrypt;
-               else
-#endif
-                       passwd = host.enable;
-               next_node = ENABLE_NODE;
-               break;
-       }
-
-       if (passwd) {
-#ifdef VTY_CRYPT_PW
-               if (host.encrypt)
-                       fail = strcmp(crypt(buf, passwd), passwd);
-               else
-#endif
-                       fail = strcmp(buf, passwd);
-       } else
-               fail = 1;
-
-       if (!fail) {
-               vty->fail = 0;
-               vty->node = next_node;  /* Success ! */
-       } else {
-               vty->fail++;
-               if (vty->fail >= 3) {
-                       if (vty->node == AUTH_NODE) {
-                               vty_out(vty,
-                                       "%% Bad passwords, too many failures!%s",
-                                       VTY_NEWLINE);
-                               vty->status = VTY_CLOSE;
-                       } else {
-                               /* AUTH_ENABLE_NODE */
-                               vty->fail = 0;
-                               vty_out(vty,
-                                       "%% Bad enable passwords, too many failures!%s",
-                                       VTY_NEWLINE);
-                               vty->node = VIEW_NODE;
-                       }
-               }
-       }
-}
-
-/* Close vty interface. */
-void vty_close(struct vty *vty)
-{
-       int i;
-
-       if (vty->obuf)  {
-               /* Flush buffer. */
-               buffer_flush_all(vty->obuf, vty->fd);
-
-               /* Free input buffer. */
-               buffer_free(vty->obuf);
-               vty->obuf = NULL;
-       }
-
-       /* Free command history. */
-       for (i = 0; i < VTY_MAXHIST; i++)
-               if (vty->hist[i])
-                       talloc_free(vty->hist[i]);
-
-       /* Unset vector. */
-       vector_unset(vtyvec, vty->fd);
-
-       /* Close socket. */
-       if (vty->fd > 0)
-               close(vty->fd);
-
-       if (vty->buf) {
-               talloc_free(vty->buf);
-               vty->buf = NULL;
-       }
-
-       /* Check configure. */
-       vty_config_unlock(vty);
-
-       /* FIXME: memory leak. We need to call telnet_close_client() but don't
-        * have bfd */
-       vty_event(VTY_CLOSED, vty->fd, vty);
-
-       /* OK free vty. */
-       talloc_free(vty);
-}
-
-int vty_shell(struct vty *vty)
-{
-       return vty->type == VTY_SHELL ? 1 : 0;
-}
-
-
-/* VTY standard output function. */
-int vty_out(struct vty *vty, const char *format, ...)
-{
-       va_list args;
-       int len = 0;
-       int size = 1024;
-       char buf[1024];
-       char *p = NULL;
-
-       if (vty_shell(vty)) {
-               va_start(args, format);
-               vprintf(format, args);
-               va_end(args);
-       } else {
-               /* Try to write to initial buffer.  */
-               va_start(args, format);
-               len = vsnprintf(buf, sizeof buf, format, args);
-               va_end(args);
-
-               /* Initial buffer is not enough.  */
-               if (len < 0 || len >= size) {
-                       while (1) {
-                               if (len > -1)
-                                       size = len + 1;
-                               else
-                                       size = size * 2;
-
-                               p = talloc_realloc_size(tall_vty_ctx, p, size);
-                               if (!p)
-                                       return -1;
-
-                               va_start(args, format);
-                               len = vsnprintf(p, size, format, args);
-                               va_end(args);
-
-                               if (len > -1 && len < size)
-                                       break;
-                       }
-               }
-
-               /* When initial buffer is enough to store all output.  */
-               if (!p)
-                       p = buf;
-
-               /* Pointer p must point out buffer. */
-               buffer_put(vty->obuf, (u_char *) p, len);
-
-               /* If p is not different with buf, it is allocated buffer.  */
-               if (p != buf)
-                       talloc_free(p);
-       }
-
-       vty_event(VTY_WRITE, vty->fd, vty);
-
-       return len;
-}
-
-int vty_out_newline(struct vty *vty)
-{
-       char *p = vty_newline(vty);
-       buffer_put(vty->obuf, p, strlen(p));
-       return 0;
-}
-
-int vty_config_lock(struct vty *vty)
-{
-       if (vty_config == 0) {
-               vty->config = 1;
-               vty_config = 1;
-       }
-       return vty->config;
-}
-
-int vty_config_unlock(struct vty *vty)
-{
-       if (vty_config == 1 && vty->config == 1) {
-               vty->config = 0;
-               vty_config = 0;
-       }
-       return vty->config;
-}
-
-/* Say hello to vty interface. */
-void vty_hello(struct vty *vty)
-{
-       if (host.motdfile) {
-               FILE *f;
-               char buf[4096];
-
-               f = osmocom_fopen(host.motdfile, "r");
-               if (f) {
-                       while (osmocom_fgets(buf, sizeof(buf), f)) {
-                               char *s;
-                               /* work backwards to ignore trailling isspace() */
-                               for (s = buf + strlen(buf);
-                                    (s > buf) && isspace(*(s - 1)); s--) ;
-                               *s = '\0';
-                               vty_out(vty, "%s%s", buf, VTY_NEWLINE);
-                       }
-                       osmocom_fclose(f);
-               } else
-                       vty_out(vty, "MOTD file not found%s", VTY_NEWLINE);
-       } else if (host.motd)
-               vty_out(vty, "%s", host.motd);
-}
-
-/* Put out prompt and wait input from user. */
-static void vty_prompt(struct vty *vty)
-{
-       struct utsname names;
-       const char *hostname;
-
-       if (vty->type == VTY_TERM) {
-               hostname = host.name;
-               if (!hostname) {
-                       uname(&names);
-                       hostname = names.nodename;
-               }
-               vty_out(vty, cmd_prompt(vty->node), hostname);
-       }
-}
-
-/* Command execution over the vty interface. */
-static int vty_command(struct vty *vty, char *buf)
-{
-       int ret;
-       vector vline;
-
-       /* Split readline string up into the vector */
-       vline = cmd_make_strvec(buf);
-
-       if (vline == NULL)
-               return CMD_SUCCESS;
-
-       ret = cmd_execute_command(vline, vty, NULL, 0);
-       if (ret != CMD_SUCCESS)
-               switch (ret) {
-               case CMD_WARNING:
-                       if (vty->type == VTY_FILE)
-                               vty_out(vty, "Warning...%s", VTY_NEWLINE);
-                       break;
-               case CMD_ERR_AMBIGUOUS:
-                       vty_out(vty, "%% Ambiguous command.%s", VTY_NEWLINE);
-                       break;
-               case CMD_ERR_NO_MATCH:
-                       vty_out(vty, "%% Unknown command.%s", VTY_NEWLINE);
-                       break;
-               case CMD_ERR_INCOMPLETE:
-                       vty_out(vty, "%% Command incomplete.%s", VTY_NEWLINE);
-                       break;
-               }
-       cmd_free_strvec(vline);
-
-       return ret;
-}
-
-static const char telnet_backward_char = 0x08;
-static const char telnet_space_char = ' ';
-
-/* Basic function to write buffer to vty. */
-static void vty_write(struct vty *vty, const char *buf, size_t nbytes)
-{
-       if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
-               return;
-
-       /* Should we do buffering here ?  And make vty_flush (vty) ? */
-       buffer_put(vty->obuf, buf, nbytes);
-}
-
-/* Ensure length of input buffer.  Is buffer is short, double it. */
-static void vty_ensure(struct vty *vty, int length)
-{
-       if (vty->max <= length) {
-               vty->max *= 2;
-               vty->buf = talloc_realloc_size(tall_vty_ctx, vty->buf, vty->max);
-               // FIXME: check return
-       }
-}
-
-/* Basic function to insert character into vty. */
-static void vty_self_insert(struct vty *vty, char c)
-{
-       int i;
-       int length;
-
-       vty_ensure(vty, vty->length + 1);
-       length = vty->length - vty->cp;
-       memmove(&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);
-       vty->buf[vty->cp] = c;
-
-       vty_write(vty, &vty->buf[vty->cp], length + 1);
-       for (i = 0; i < length; i++)
-               vty_write(vty, &telnet_backward_char, 1);
-
-       vty->cp++;
-       vty->length++;
-}
-
-/* Self insert character 'c' in overwrite mode. */
-static void vty_self_insert_overwrite(struct vty *vty, char c)
-{
-       vty_ensure(vty, vty->length + 1);
-       vty->buf[vty->cp++] = c;
-
-       if (vty->cp > vty->length)
-               vty->length++;
-
-       if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
-               return;
-
-       vty_write(vty, &c, 1);
-}
-
-/* Insert a word into vty interface with overwrite mode. */
-static void vty_insert_word_overwrite(struct vty *vty, char *str)
-{
-       int len = strlen(str);
-       vty_write(vty, str, len);
-       strcpy(&vty->buf[vty->cp], str);
-       vty->cp += len;
-       vty->length = vty->cp;
-}
-
-/* Forward character. */
-static void vty_forward_char(struct vty *vty)
-{
-       if (vty->cp < vty->length) {
-               vty_write(vty, &vty->buf[vty->cp], 1);
-               vty->cp++;
-       }
-}
-
-/* Backward character. */
-static void vty_backward_char(struct vty *vty)
-{
-       if (vty->cp > 0) {
-               vty->cp--;
-               vty_write(vty, &telnet_backward_char, 1);
-       }
-}
-
-/* Move to the beginning of the line. */
-static void vty_beginning_of_line(struct vty *vty)
-{
-       while (vty->cp)
-               vty_backward_char(vty);
-}
-
-/* Move to the end of the line. */
-static void vty_end_of_line(struct vty *vty)
-{
-       while (vty->cp < vty->length)
-               vty_forward_char(vty);
-}
-
-/* Add current command line to the history buffer. */
-static void vty_hist_add(struct vty *vty)
-{
-       int index;
-
-       if (vty->length == 0)
-               return;
-
-       index = vty->hindex ? vty->hindex - 1 : VTY_MAXHIST - 1;
-
-       /* Ignore the same string as previous one. */
-       if (vty->hist[index])
-               if (strcmp(vty->buf, vty->hist[index]) == 0) {
-                       vty->hp = vty->hindex;
-                       return;
-               }
-
-       /* Insert history entry. */
-       if (vty->hist[vty->hindex])
-               talloc_free(vty->hist[vty->hindex]);
-       vty->hist[vty->hindex] = talloc_strdup(tall_vty_ctx, vty->buf);
-
-       /* History index rotation. */
-       vty->hindex++;
-       if (vty->hindex == VTY_MAXHIST)
-               vty->hindex = 0;
-
-       vty->hp = vty->hindex;
-}
-
-/* Get telnet window size. */
-static int
-vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes)
-{
-#ifdef TELNET_OPTION_DEBUG
-  int i;
-
-  for (i = 0; i < nbytes; i++)
-    {
-      switch (buf[i])
-       {
-       case IAC:
-         vty_out (vty, "IAC ");
-         break;
-       case WILL:
-         vty_out (vty, "WILL ");
-         break;
-       case WONT:
-         vty_out (vty, "WONT ");
-         break;
-       case DO:
-         vty_out (vty, "DO ");
-         break;
-       case DONT:
-         vty_out (vty, "DONT ");
-         break;
-       case SB:
-         vty_out (vty, "SB ");
-         break;
-       case SE:
-         vty_out (vty, "SE ");
-         break;
-       case TELOPT_ECHO:
-         vty_out (vty, "TELOPT_ECHO %s", VTY_NEWLINE);
-         break;
-       case TELOPT_SGA:
-         vty_out (vty, "TELOPT_SGA %s", VTY_NEWLINE);
-         break;
-       case TELOPT_NAWS:
-         vty_out (vty, "TELOPT_NAWS %s", VTY_NEWLINE);
-         break;
-       default:
-         vty_out (vty, "%x ", buf[i]);
-         break;
-       }
-    }
-  vty_out (vty, "%s", VTY_NEWLINE);
-
-#endif /* TELNET_OPTION_DEBUG */
-
-  switch (buf[0])
-    {
-    case SB:
-      vty->sb_len = 0;
-      vty->iac_sb_in_progress = 1;
-      return 0;
-      break;
-    case SE: 
-      {
-       if (!vty->iac_sb_in_progress)
-         return 0;
-
-       if ((vty->sb_len == 0) || (vty->sb_buf[0] == '\0'))
-         {
-           vty->iac_sb_in_progress = 0;
-           return 0;
-         }
-       switch (vty->sb_buf[0])
-         {
-         case TELOPT_NAWS:
-           if (vty->sb_len != TELNET_NAWS_SB_LEN)
-             vty_out(vty,"RFC 1073 violation detected: telnet NAWS option "
-                       "should send %d characters, but we received %lu",
-                       TELNET_NAWS_SB_LEN, (u_long)vty->sb_len);
-           else if (sizeof(vty->sb_buf) < TELNET_NAWS_SB_LEN)
-             vty_out(vty, "Bug detected: sizeof(vty->sb_buf) %lu < %d, "
-                      "too small to handle the telnet NAWS option",
-                      (u_long)sizeof(vty->sb_buf), TELNET_NAWS_SB_LEN);
-           else
-             {
-               vty->width = ((vty->sb_buf[1] << 8)|vty->sb_buf[2]);
-               vty->height = ((vty->sb_buf[3] << 8)|vty->sb_buf[4]);
-#ifdef TELNET_OPTION_DEBUG
-               vty_out(vty, "TELNET NAWS window size negotiation completed: "
-                             "width %d, height %d%s",
-                       vty->width, vty->height, VTY_NEWLINE);
-#endif
-             }
-           break;
-         }
-       vty->iac_sb_in_progress = 0;
-       return 0;
-       break;
-      }
-    default:
-      break;
-    }
-  return 1;
-}
-
-/* Execute current command line. */
-static int vty_execute(struct vty *vty)
-{
-       int ret;
-
-       ret = CMD_SUCCESS;
-
-       switch (vty->node) {
-       case AUTH_NODE:
-       case AUTH_ENABLE_NODE:
-               vty_auth(vty, vty->buf);
-               break;
-       default:
-               ret = vty_command(vty, vty->buf);
-               if (vty->type == VTY_TERM)
-                       vty_hist_add(vty);
-               break;
-       }
-
-       /* Clear command line buffer. */
-       vty->cp = vty->length = 0;
-       vty_clear_buf(vty);
-
-       if (vty->status != VTY_CLOSE)
-               vty_prompt(vty);
-
-       return ret;
-}
-
-/* Send WILL TELOPT_ECHO to remote server. */
-static void
-vty_will_echo (struct vty *vty)
-{
-       unsigned char cmd[] = { IAC, WILL, TELOPT_ECHO, '\0' };
-       vty_out (vty, "%s", cmd);
-}
-
-/* Make suppress Go-Ahead telnet option. */
-static void
-vty_will_suppress_go_ahead (struct vty *vty)
-{
-       unsigned char cmd[] = { IAC, WILL, TELOPT_SGA, '\0' };
-       vty_out (vty, "%s", cmd);
-}
-
-/* Make don't use linemode over telnet. */
-static void
-vty_dont_linemode (struct vty *vty)
-{
-       unsigned char cmd[] = { IAC, DONT, TELOPT_LINEMODE, '\0' };
-       vty_out (vty, "%s", cmd);
-}
-
-/* Use window size. */
-static void
-vty_do_window_size (struct vty *vty)
-{
-       unsigned char cmd[] = { IAC, DO, TELOPT_NAWS, '\0' };
-       vty_out (vty, "%s", cmd);
-}
-
-static void vty_kill_line_from_beginning(struct vty *);
-static void vty_redraw_line(struct vty *);
-
-/* Print command line history.  This function is called from
-   vty_next_line and vty_previous_line. */
-static void vty_history_print(struct vty *vty)
-{
-       int length;
-
-       vty_kill_line_from_beginning(vty);
-
-       /* Get previous line from history buffer */
-       length = strlen(vty->hist[vty->hp]);
-       memcpy(vty->buf, vty->hist[vty->hp], length);
-       vty->cp = vty->length = length;
-
-       /* Redraw current line */
-       vty_redraw_line(vty);
-}
-
-/* Show next command line history. */
-static void vty_next_line(struct vty *vty)
-{
-       int try_index;
-
-       if (vty->hp == vty->hindex)
-               return;
-
-       /* Try is there history exist or not. */
-       try_index = vty->hp;
-       if (try_index == (VTY_MAXHIST - 1))
-               try_index = 0;
-       else
-               try_index++;
-
-       /* If there is not history return. */
-       if (vty->hist[try_index] == NULL)
-               return;
-       else
-               vty->hp = try_index;
-
-       vty_history_print(vty);
-}
-
-/* Show previous command line history. */
-static void vty_previous_line(struct vty *vty)
-{
-       int try_index;
-
-       try_index = vty->hp;
-       if (try_index == 0)
-               try_index = VTY_MAXHIST - 1;
-       else
-               try_index--;
-
-       if (vty->hist[try_index] == NULL)
-               return;
-       else
-               vty->hp = try_index;
-
-       vty_history_print(vty);
-}
-
-/* This function redraw all of the command line character. */
-static void vty_redraw_line(struct vty *vty)
-{
-       vty_write(vty, vty->buf, vty->length);
-       vty->cp = vty->length;
-}
-
-/* Forward word. */
-static void vty_forward_word(struct vty *vty)
-{
-       while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
-               vty_forward_char(vty);
-
-       while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
-               vty_forward_char(vty);
-}
-
-/* Backward word without skipping training space. */
-static void vty_backward_pure_word(struct vty *vty)
-{
-       while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
-               vty_backward_char(vty);
-}
-
-/* Backward word. */
-static void vty_backward_word(struct vty *vty)
-{
-       while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
-               vty_backward_char(vty);
-
-       while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
-               vty_backward_char(vty);
-}
-
-/* When '^D' is typed at the beginning of the line we move to the down
-   level. */
-static void vty_down_level(struct vty *vty)
-{
-       vty_out(vty, "%s", VTY_NEWLINE);
-       (*config_exit_cmd.func) (NULL, vty, 0, NULL);
-       vty_prompt(vty);
-       vty->cp = 0;
-}
-
-/* When '^Z' is received from vty, move down to the enable mode. */
-static void vty_end_config(struct vty *vty)
-{
-       vty_out(vty, "%s", VTY_NEWLINE);
-
-       switch (vty->node) {
-       case VIEW_NODE:
-       case ENABLE_NODE:
-               /* Nothing to do. */
-               break;
-       case CONFIG_NODE:
-       case VTY_NODE:
-               vty_config_unlock(vty);
-               vty->node = ENABLE_NODE;
-               break;
-       default:
-               /* Unknown node, we have to ignore it. */
-               break;
-       }
-
-       vty_prompt(vty);
-       vty->cp = 0;
-}
-
-/* Delete a charcter at the current point. */
-static void vty_delete_char(struct vty *vty)
-{
-       int i;
-       int size;
-
-       if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
-               return;
-
-       if (vty->length == 0) {
-               vty_down_level(vty);
-               return;
-       }
-
-       if (vty->cp == vty->length)
-               return;         /* completion need here? */
-
-       size = vty->length - vty->cp;
-
-       vty->length--;
-       memmove(&vty->buf[vty->cp], &vty->buf[vty->cp + 1], size - 1);
-       vty->buf[vty->length] = '\0';
-
-       vty_write(vty, &vty->buf[vty->cp], size - 1);
-       vty_write(vty, &telnet_space_char, 1);
-
-       for (i = 0; i < size; i++)
-               vty_write(vty, &telnet_backward_char, 1);
-}
-
-/* Delete a character before the point. */
-static void vty_delete_backward_char(struct vty *vty)
-{
-       if (vty->cp == 0)
-               return;
-
-       vty_backward_char(vty);
-       vty_delete_char(vty);
-}
-
-/* Kill rest of line from current point. */
-static void vty_kill_line(struct vty *vty)
-{
-       int i;
-       int size;
-
-       size = vty->length - vty->cp;
-
-       if (size == 0)
-               return;
-
-       for (i = 0; i < size; i++)
-               vty_write(vty, &telnet_space_char, 1);
-       for (i = 0; i < size; i++)
-               vty_write(vty, &telnet_backward_char, 1);
-
-       memset(&vty->buf[vty->cp], 0, size);
-       vty->length = vty->cp;
-}
-
-/* Kill line from the beginning. */
-static void vty_kill_line_from_beginning(struct vty *vty)
-{
-       vty_beginning_of_line(vty);
-       vty_kill_line(vty);
-}
-
-/* Delete a word before the point. */
-static void vty_forward_kill_word(struct vty *vty)
-{
-       while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
-               vty_delete_char(vty);
-       while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
-               vty_delete_char(vty);
-}
-
-/* Delete a word before the point. */
-static void vty_backward_kill_word(struct vty *vty)
-{
-       while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
-               vty_delete_backward_char(vty);
-       while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
-               vty_delete_backward_char(vty);
-}
-
-/* Transpose chars before or at the point. */
-static void vty_transpose_chars(struct vty *vty)
-{
-       char c1, c2;
-
-       /* If length is short or point is near by the beginning of line then
-          return. */
-       if (vty->length < 2 || vty->cp < 1)
-               return;
-
-       /* In case of point is located at the end of the line. */
-       if (vty->cp == vty->length) {
-               c1 = vty->buf[vty->cp - 1];
-               c2 = vty->buf[vty->cp - 2];
-
-               vty_backward_char(vty);
-               vty_backward_char(vty);
-               vty_self_insert_overwrite(vty, c1);
-               vty_self_insert_overwrite(vty, c2);
-       } else {
-               c1 = vty->buf[vty->cp];
-               c2 = vty->buf[vty->cp - 1];
-
-               vty_backward_char(vty);
-               vty_self_insert_overwrite(vty, c1);
-               vty_self_insert_overwrite(vty, c2);
-       }
-}
-
-/* Do completion at vty interface. */
-static void vty_complete_command(struct vty *vty)
-{
-       int i;
-       int ret;
-       char **matched = NULL;
-       vector vline;
-
-       if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
-               return;
-
-       vline = cmd_make_strvec(vty->buf);
-       if (vline == NULL)
-               return;
-
-       /* In case of 'help \t'. */
-       if (isspace((int)vty->buf[vty->length - 1]))
-               vector_set(vline, '\0');
-
-       matched = cmd_complete_command(vline, vty, &ret);
-
-       cmd_free_strvec(vline);
-
-       vty_out(vty, "%s", VTY_NEWLINE);
-       switch (ret) {
-       case CMD_ERR_AMBIGUOUS:
-               vty_out(vty, "%% Ambiguous command.%s", VTY_NEWLINE);
-               vty_prompt(vty);
-               vty_redraw_line(vty);
-               break;
-       case CMD_ERR_NO_MATCH:
-               /* vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE); */
-               vty_prompt(vty);
-               vty_redraw_line(vty);
-               break;
-       case CMD_COMPLETE_FULL_MATCH:
-               vty_prompt(vty);
-               vty_redraw_line(vty);
-               vty_backward_pure_word(vty);
-               vty_insert_word_overwrite(vty, matched[0]);
-               vty_self_insert(vty, ' ');
-               //talloc_free(matched[0]);
-               break;
-       case CMD_COMPLETE_MATCH:
-               vty_prompt(vty);
-               vty_redraw_line(vty);
-               vty_backward_pure_word(vty);
-               vty_insert_word_overwrite(vty, matched[0]);
-               talloc_free(matched[0]);
-               vector_only_index_free(matched);
-               return;
-               break;
-       case CMD_COMPLETE_LIST_MATCH:
-               for (i = 0; matched[i] != NULL; i++) {
-                       if (i != 0 && ((i % 6) == 0))
-                               vty_out(vty, "%s", VTY_NEWLINE);
-                       vty_out(vty, "%-10s ", matched[i]);
-                       talloc_free(matched[i]);
-               }
-               vty_out(vty, "%s", VTY_NEWLINE);
-
-               vty_prompt(vty);
-               vty_redraw_line(vty);
-               break;
-       case CMD_ERR_NOTHING_TODO:
-               vty_prompt(vty);
-               vty_redraw_line(vty);
-               break;
-       default:
-               break;
-       }
-       if (matched)
-               vector_only_index_free(matched);
-}
-
-static void
-vty_describe_fold(struct vty *vty, int cmd_width,
-                 unsigned int desc_width, struct desc *desc)
-{
-       char *buf;
-       const char *cmd, *p;
-       int pos;
-
-       cmd = desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd;
-
-       if (desc_width <= 0) {
-               vty_out(vty, "  %-*s  %s%s", cmd_width, cmd, desc->str,
-                       VTY_NEWLINE);
-               return;
-       }
-
-       buf = _talloc_zero(tall_vty_ctx, strlen(desc->str) + 1, "describe_fold");
-       if (!buf)
-               return;
-
-       for (p = desc->str; strlen(p) > desc_width; p += pos + 1) {
-               for (pos = desc_width; pos > 0; pos--)
-                       if (*(p + pos) == ' ')
-                               break;
-
-               if (pos == 0)
-                       break;
-
-               strncpy(buf, p, pos);
-               buf[pos] = '\0';
-               vty_out(vty, "  %-*s  %s%s", cmd_width, cmd, buf, VTY_NEWLINE);
-
-               cmd = "";
-       }
-
-       vty_out(vty, "  %-*s  %s%s", cmd_width, cmd, p, VTY_NEWLINE);
-
-       talloc_free(buf);
-}
-
-/* Describe matched command function. */
-static void vty_describe_command(struct vty *vty)
-{
-       int ret;
-       vector vline;
-       vector describe;
-       unsigned int i, width, desc_width;
-       struct desc *desc, *desc_cr = NULL;
-
-       vline = cmd_make_strvec(vty->buf);
-
-       /* In case of '> ?'. */
-       if (vline == NULL) {
-               vline = vector_init(1);
-               vector_set(vline, '\0');
-       } else if (isspace((int)vty->buf[vty->length - 1]))
-               vector_set(vline, '\0');
-
-       describe = cmd_describe_command(vline, vty, &ret);
-
-       vty_out(vty, "%s", VTY_NEWLINE);
-
-       /* Ambiguous error. */
-       switch (ret) {
-       case CMD_ERR_AMBIGUOUS:
-               cmd_free_strvec(vline);
-               vty_out(vty, "%% Ambiguous command.%s", VTY_NEWLINE);
-               vty_prompt(vty);
-               vty_redraw_line(vty);
-               return;
-               break;
-       case CMD_ERR_NO_MATCH:
-               cmd_free_strvec(vline);
-               vty_out(vty, "%% There is no matched command.%s", VTY_NEWLINE);
-               vty_prompt(vty);
-               vty_redraw_line(vty);
-               return;
-               break;
-       }
-
-       /* Get width of command string. */
-       width = 0;
-       for (i = 0; i < vector_active(describe); i++)
-               if ((desc = vector_slot(describe, i)) != NULL) {
-                       unsigned int len;
-
-                       if (desc->cmd[0] == '\0')
-                               continue;
-
-                       len = strlen(desc->cmd);
-                       if (desc->cmd[0] == '.')
-                               len--;
-
-                       if (width < len)
-                               width = len;
-               }
-
-       /* Get width of description string. */
-       desc_width = vty->width - (width + 6);
-
-       /* Print out description. */
-       for (i = 0; i < vector_active(describe); i++)
-               if ((desc = vector_slot(describe, i)) != NULL) {
-                       if (desc->cmd[0] == '\0')
-                               continue;
-
-                       if (strcmp(desc->cmd, "<cr>") == 0) {
-                               desc_cr = desc;
-                               continue;
-                       }
-
-                       if (!desc->str)
-                               vty_out(vty, "  %-s%s",
-                                       desc->cmd[0] ==
-                                       '.' ? desc->cmd + 1 : desc->cmd,
-                                       VTY_NEWLINE);
-                       else if (desc_width >= strlen(desc->str))
-                               vty_out(vty, "  %-*s  %s%s", width,
-                                       desc->cmd[0] ==
-                                       '.' ? desc->cmd + 1 : desc->cmd,
-                                       desc->str, VTY_NEWLINE);
-                       else
-                               vty_describe_fold(vty, width, desc_width, desc);
-
-#if 0
-                       vty_out(vty, "  %-*s %s%s", width
-                               desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
-                               desc->str ? desc->str : "", VTY_NEWLINE);
-#endif                         /* 0 */
-               }
-
-       if ((desc = desc_cr)) {
-               if (!desc->str)
-                       vty_out(vty, "  %-s%s",
-                               desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
-                               VTY_NEWLINE);
-               else if (desc_width >= strlen(desc->str))
-                       vty_out(vty, "  %-*s  %s%s", width,
-                               desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
-                               desc->str, VTY_NEWLINE);
-               else
-                       vty_describe_fold(vty, width, desc_width, desc);
-       }
-
-       cmd_free_strvec(vline);
-       vector_free(describe);
-
-       vty_prompt(vty);
-       vty_redraw_line(vty);
-}
-
-/* ^C stop current input and do not add command line to the history. */
-static void vty_stop_input(struct vty *vty)
-{
-       vty->cp = vty->length = 0;
-       vty_clear_buf(vty);
-       vty_out(vty, "%s", VTY_NEWLINE);
-
-       switch (vty->node) {
-       case VIEW_NODE:
-       case ENABLE_NODE:
-               /* Nothing to do. */
-               break;
-       case CONFIG_NODE:
-       case VTY_NODE:
-               vty_config_unlock(vty);
-               vty->node = ENABLE_NODE;
-               break;
-       default:
-               /* Unknown node, we have to ignore it. */
-               break;
-       }
-       vty_prompt(vty);
-
-       /* Set history pointer to the latest one. */
-       vty->hp = vty->hindex;
-}
-
-#define CONTROL(X)  ((X) - '@')
-#define VTY_NORMAL     0
-#define VTY_PRE_ESCAPE 1
-#define VTY_ESCAPE     2
-
-/* Escape character command map. */
-static void vty_escape_map(unsigned char c, struct vty *vty)
-{
-       switch (c) {
-       case ('A'):
-               vty_previous_line(vty);
-               break;
-       case ('B'):
-               vty_next_line(vty);
-               break;
-       case ('C'):
-               vty_forward_char(vty);
-               break;
-       case ('D'):
-               vty_backward_char(vty);
-               break;
-       default:
-               break;
-       }
-
-       /* Go back to normal mode. */
-       vty->escape = VTY_NORMAL;
-}
-
-/* Quit print out to the buffer. */
-static void vty_buffer_reset(struct vty *vty)
-{
-       buffer_reset(vty->obuf);
-       vty_prompt(vty);
-       vty_redraw_line(vty);
-}
-
-/* Read data via vty socket. */
-int vty_read(struct vty *vty)
-{
-       int i;
-       int nbytes;
-       unsigned char buf[VTY_READ_BUFSIZ];
-
-       int vty_sock = vty->fd;
-
-       /* Read raw data from socket */
-       if ((nbytes = read(vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) {
-               if (nbytes < 0) {
-                       if (ERRNO_IO_RETRY(errno)) {
-                               vty_event(VTY_READ, vty_sock, vty);
-                               return 0;
-                       }
-               }
-               buffer_reset(vty->obuf);
-               vty->status = VTY_CLOSE;
-       }
-
-       for (i = 0; i < nbytes; i++) {
-               if (buf[i] == IAC) {
-                       if (!vty->iac) {
-                               vty->iac = 1;
-                               continue;
-                       } else {
-                               vty->iac = 0;
-                       }
-               }
-
-               if (vty->iac_sb_in_progress && !vty->iac) {
-                       if (vty->sb_len < sizeof(vty->sb_buf))
-                               vty->sb_buf[vty->sb_len] = buf[i];
-                       vty->sb_len++;
-                       continue;
-               }
-
-               if (vty->iac) {
-                       /* In case of telnet command */
-                       int ret = 0;
-                       ret = vty_telnet_option(vty, buf + i, nbytes - i);
-                       vty->iac = 0;
-                       i += ret;
-                       continue;
-               }
-
-               if (vty->status == VTY_MORE) {
-                       switch (buf[i]) {
-                       case CONTROL('C'):
-                       case 'q':
-                       case 'Q':
-                               vty_buffer_reset(vty);
-                               break;
-#if 0                          /* More line does not work for "show ip bgp".  */
-                       case '\n':
-                       case '\r':
-                               vty->status = VTY_MORELINE;
-                               break;
-#endif
-                       default:
-                               break;
-                       }
-                       continue;
-               }
-
-               /* Escape character. */
-               if (vty->escape == VTY_ESCAPE) {
-                       vty_escape_map(buf[i], vty);
-                       continue;
-               }
-
-               /* Pre-escape status. */
-               if (vty->escape == VTY_PRE_ESCAPE) {
-                       switch (buf[i]) {
-                       case '[':
-                               vty->escape = VTY_ESCAPE;
-                               break;
-                       case 'b':
-                               vty_backward_word(vty);
-                               vty->escape = VTY_NORMAL;
-                               break;
-                       case 'f':
-                               vty_forward_word(vty);
-                               vty->escape = VTY_NORMAL;
-                               break;
-                       case 'd':
-                               vty_forward_kill_word(vty);
-                               vty->escape = VTY_NORMAL;
-                               break;
-                       case CONTROL('H'):
-                       case 0x7f:
-                               vty_backward_kill_word(vty);
-                               vty->escape = VTY_NORMAL;
-                               break;
-                       default:
-                               vty->escape = VTY_NORMAL;
-                               break;
-                       }
-                       continue;
-               }
-
-               switch (buf[i]) {
-               case CONTROL('A'):
-                       vty_beginning_of_line(vty);
-                       break;
-               case CONTROL('B'):
-                       vty_backward_char(vty);
-                       break;
-               case CONTROL('C'):
-                       vty_stop_input(vty);
-                       break;
-               case CONTROL('D'):
-                       vty_delete_char(vty);
-                       break;
-               case CONTROL('E'):
-                       vty_end_of_line(vty);
-                       break;
-               case CONTROL('F'):
-                       vty_forward_char(vty);
-                       break;
-               case CONTROL('H'):
-               case 0x7f:
-                       vty_delete_backward_char(vty);
-                       break;
-               case CONTROL('K'):
-                       vty_kill_line(vty);
-                       break;
-               case CONTROL('N'):
-                       vty_next_line(vty);
-                       break;
-               case CONTROL('P'):
-                       vty_previous_line(vty);
-                       break;
-               case CONTROL('T'):
-                       vty_transpose_chars(vty);
-                       break;
-               case CONTROL('U'):
-                       vty_kill_line_from_beginning(vty);
-                       break;
-               case CONTROL('W'):
-                       vty_backward_kill_word(vty);
-                       break;
-               case CONTROL('Z'):
-                       vty_end_config(vty);
-                       break;
-               case '\n':
-               case '\r':
-                       vty_out(vty, "%s", VTY_NEWLINE);
-                       vty_execute(vty);
-                       break;
-               case '\t':
-                       vty_complete_command(vty);
-                       break;
-               case '?':
-                       if (vty->node == AUTH_NODE
-                           || vty->node == AUTH_ENABLE_NODE)
-                               vty_self_insert(vty, buf[i]);
-                       else
-                               vty_describe_command(vty);
-                       break;
-               case '\033':
-                       if (i + 1 < nbytes && buf[i + 1] == '[') {
-                               vty->escape = VTY_ESCAPE;
-                               i++;
-                       } else
-                               vty->escape = VTY_PRE_ESCAPE;
-                       break;
-               default:
-                       if (buf[i] > 31 && buf[i] < 127)
-                               vty_self_insert(vty, buf[i]);
-                       break;
-               }
-       }
-
-       /* Check status. */
-       if (vty->status == VTY_CLOSE)
-               vty_close(vty);
-       else {
-               vty_event(VTY_WRITE, vty_sock, vty);
-               vty_event(VTY_READ, vty_sock, vty);
-       }
-       return 0;
-}
-
-/* Read up configuration file */
-static int
-vty_read_file(FILE *confp)
-{
-       int ret;
-       struct vty *vty;
-
-       vty = vty_new();
-       vty->fd = 0;
-       vty->type = VTY_FILE;
-       vty->node = CONFIG_NODE;
-
-       ret = config_from_file(vty, confp);
-
-       if (ret != CMD_SUCCESS) {
-               switch (ret) {
-               case CMD_ERR_AMBIGUOUS:
-                       fprintf(stderr, "Ambiguous command.\n");
-                       break;
-               case CMD_ERR_NO_MATCH:
-                       fprintf(stderr, "There is no such command.\n");
-                       break;
-               }
-               fprintf(stderr, "Error occurred during reading below "
-                       "line:\n%s\n", vty->buf);
-               vty_close(vty);
-               return -EINVAL;
-       }
-
-       vty_close(vty);
-       return 0;
-}
-
-/* Create new vty structure. */
-struct vty *
-vty_create (int vty_sock, void *priv)
-{
-  struct vty *vty;
-
-       struct termios t;
-
-       tcgetattr(vty_sock, &t);
-       cfmakeraw(&t);
-       tcsetattr(vty_sock, TCSANOW, &t);
-
-  /* Allocate new vty structure and set up default values. */
-  vty = vty_new ();
-  vty->fd = vty_sock;
-  vty->priv = priv;
-  vty->type = VTY_TERM;
-  if (no_password_check)
-    {
-      if (host.advanced)
-       vty->node = ENABLE_NODE;
-      else
-       vty->node = VIEW_NODE;
-    }
-  else
-    vty->node = AUTH_NODE;
-  vty->fail = 0;
-  vty->cp = 0;
-  vty_clear_buf (vty);
-  vty->length = 0;
-  memset (vty->hist, 0, sizeof (vty->hist));
-  vty->hp = 0;
-  vty->hindex = 0;
-  vector_set_index (vtyvec, vty_sock, vty);
-  vty->status = VTY_NORMAL;
-  if (host.lines >= 0)
-    vty->lines = host.lines;
-  else
-    vty->lines = -1;
-
-  if (! no_password_check)
-    {
-      /* Vty is not available if password isn't set. */
-      if (host.password == NULL && host.password_encrypt == NULL)
-       {
-         vty_out (vty, "Vty password is not set.%s", VTY_NEWLINE);
-         vty->status = VTY_CLOSE;
-         vty_close (vty);
-         return NULL;
-       }
-    }
-
-  /* Say hello to the world. */
-  vty_hello (vty);
-  if (! no_password_check)
-    vty_out (vty, "%sUser Access Verification%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
-
-  /* Setting up terminal. */
-  vty_will_echo (vty);
-  vty_will_suppress_go_ahead (vty);
-
-  vty_dont_linemode (vty);
-  vty_do_window_size (vty);
-  /* vty_dont_lflow_ahead (vty); */
-
-  vty_prompt (vty);
-
-  /* Add read/write thread. */
-  vty_event (VTY_WRITE, vty_sock, vty);
-  vty_event (VTY_READ, vty_sock, vty);
-
-  return vty;
-}
-
-DEFUN(config_who, config_who_cmd, "who", "Display who is on vty\n")
-{
-       unsigned int i;
-       struct vty *v;
-
-       for (i = 0; i < vector_active(vtyvec); i++)
-               if ((v = vector_slot(vtyvec, i)) != NULL)
-                       vty_out(vty, "%svty[%d] %s",
-                               v->config ? "*" : " ", i, VTY_NEWLINE);
-       return CMD_SUCCESS;
-}
-
-/* Move to vty configuration mode. */
-DEFUN(line_vty,
-      line_vty_cmd,
-      "line vty", "Configure a terminal line\n" "Virtual terminal\n")
-{
-       vty->node = VTY_NODE;
-       return CMD_SUCCESS;
-}
-
-/* vty login. */
-DEFUN(vty_login, vty_login_cmd, "login", "Enable password checking\n")
-{
-       no_password_check = 0;
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_vty_login,
-      no_vty_login_cmd, "no login", NO_STR "Enable password checking\n")
-{
-       no_password_check = 1;
-       return CMD_SUCCESS;
-}
-
-DEFUN(service_advanced_vty,
-      service_advanced_vty_cmd,
-      "service advanced-vty",
-      "Set up miscellaneous service\n" "Enable advanced mode vty interface\n")
-{
-       host.advanced = 1;
-       return CMD_SUCCESS;
-}
-
-DEFUN(no_service_advanced_vty,
-      no_service_advanced_vty_cmd,
-      "no service advanced-vty",
-      NO_STR
-      "Set up miscellaneous service\n" "Enable advanced mode vty interface\n")
-{
-       host.advanced = 0;
-       return CMD_SUCCESS;
-}
-
-DEFUN(terminal_monitor,
-      terminal_monitor_cmd,
-      "terminal monitor",
-      "Set terminal line parameters\n"
-      "Copy debug output to the current terminal line\n")
-{
-       vty->monitor = 1;
-       return CMD_SUCCESS;
-}
-
-DEFUN(terminal_no_monitor,
-      terminal_no_monitor_cmd,
-      "terminal no monitor",
-      "Set terminal line parameters\n"
-      NO_STR "Copy debug output to the current terminal line\n")
-{
-       vty->monitor = 0;
-       return CMD_SUCCESS;
-}
-
-DEFUN(show_history,
-      show_history_cmd,
-      "show history", SHOW_STR "Display the session command history\n")
-{
-       int index;
-
-       for (index = vty->hindex + 1; index != vty->hindex;) {
-               if (index == VTY_MAXHIST) {
-                       index = 0;
-                       continue;
-               }
-
-               if (vty->hist[index] != NULL)
-                       vty_out(vty, "  %s%s", vty->hist[index], VTY_NEWLINE);
-
-               index++;
-       }
-
-       return CMD_SUCCESS;
-}
-
-/* Display current configuration. */
-static int vty_config_write(struct vty *vty)
-{
-       vty_out(vty, "line vty%s", VTY_NEWLINE);
-
-       /* login */
-       if (no_password_check)
-               vty_out(vty, " no login%s", VTY_NEWLINE);
-
-       vty_out(vty, "!%s", VTY_NEWLINE);
-
-       return CMD_SUCCESS;
-}
-
-struct cmd_node vty_node = {
-       VTY_NODE,
-       "%s(config-line)# ",
-       1,
-};
-
-/* Reset all VTY status. */
-void vty_reset()
-{
-       unsigned int i;
-       struct vty *vty;
-       struct thread *vty_serv_thread;
-
-       for (i = 0; i < vector_active(vtyvec); i++)
-               if ((vty = vector_slot(vtyvec, i)) != NULL) {
-                       buffer_reset(vty->obuf);
-                       vty->status = VTY_CLOSE;
-                       vty_close(vty);
-               }
-
-       for (i = 0; i < vector_active(Vvty_serv_thread); i++)
-               if ((vty_serv_thread =
-                    vector_slot(Vvty_serv_thread, i)) != NULL) {
-                       //thread_cancel (vty_serv_thread);
-                       vector_slot(Vvty_serv_thread, i) = NULL;
-                       close(i);
-               }
-}
-
-static void vty_save_cwd(void)
-{
-       char cwd[MAXPATHLEN];
-       char *c ;
-
-       c = getcwd(cwd, MAXPATHLEN);
-
-       if (!c) {
-               if (chdir(SYSCONFDIR) != 0)
-                   perror("chdir failed");
-               if (getcwd(cwd, MAXPATHLEN) == NULL)
-                   perror("getcwd failed");
-       }
-
-       vty_cwd = _talloc_zero(tall_vty_ctx, strlen(cwd) + 1, "save_cwd");
-       strcpy(vty_cwd, cwd);
-}
-
-char *vty_get_cwd()
-{
-       return vty_cwd;
-}
-
-int vty_shell_serv(struct vty *vty)
-{
-       return vty->type == VTY_SHELL_SERV ? 1 : 0;
-}
-
-void vty_init_vtysh()
-{
-       vtyvec = vector_init(VECTOR_MIN_SIZE);
-}
-
-extern void *tall_bsc_ctx;
-/* Install vty's own commands like `who' command. */
-void vty_init()
-{
-       tall_vty_ctx = talloc_named_const(NULL, 0, "vty");
-       tall_vty_vec_ctx = talloc_named_const(tall_vty_ctx, 0, "vty_vector");
-       tall_vty_cmd_ctx = talloc_named_const(tall_vty_ctx, 0, "vty_command");
-
-       /* For further configuration read, preserve current directory. */
-       vty_save_cwd();
-
-       vtyvec = vector_init(VECTOR_MIN_SIZE);
-
-       /* Install bgp top node. */
-       install_node(&vty_node, vty_config_write);
-
-       install_element(VIEW_NODE, &config_who_cmd);
-       install_element(VIEW_NODE, &show_history_cmd);
-       install_element(ENABLE_NODE, &config_who_cmd);
-       install_element(CONFIG_NODE, &line_vty_cmd);
-       install_element(CONFIG_NODE, &service_advanced_vty_cmd);
-       install_element(CONFIG_NODE, &no_service_advanced_vty_cmd);
-       install_element(CONFIG_NODE, &show_history_cmd);
-       install_element(ENABLE_NODE, &terminal_monitor_cmd);
-       install_element(ENABLE_NODE, &terminal_no_monitor_cmd);
-       install_element(ENABLE_NODE, &show_history_cmd);
-
-       install_default(VTY_NODE);
-       install_element(VTY_NODE, &vty_login_cmd);
-       install_element(VTY_NODE, &no_vty_login_cmd);
-}
-
-int vty_read_config_file(const char *file_name)
-{
-       OSMOCOM_FILE *cfile;
-       int rc;
-
-       cfile = osmocom_fopen(file_name, "r");
-       if (!cfile)
-               return -ENOENT;
-
-       rc = vty_read_file(cfile);
-       osmocom_fclose(cfile);
-
-       host_config_set(file_name);
-
-       return rc;
-}
index 3f6baff..7d2a711 100644 (file)
@@ -25,9 +25,8 @@
 #include <unistd.h>
 #include <sys/types.h>
 
-#include <vty/command.h>
-#include <vty/buffer.h>
-#include <vty/vty.h>
+#include <osmocom/vty.h>
+#include <osmocom/vty/telnet_interface.h>
 
 #include <osmocore/gsm48.h>
 #include <osmocom/osmocom_data.h>
@@ -42,6 +41,7 @@ int mncc_hold(struct osmocom_ms *ms);
 int mncc_retrieve(struct osmocom_ms *ms, int number);
 
 extern struct llist_head ms_list;
+extern struct llist_head active_connections;
 
 struct cmd_node ms_node = {
        MS_NODE,
@@ -847,29 +847,76 @@ DEFUN(cfg_test_hplmn, cfg_test_hplmn_cmd, "hplmn-search (everywhere|foreign-coun
        return CMD_SUCCESS;
 }
 
+enum node_type ms_vty_go_parent(struct vty *vty)
+{
+       switch (vty->node) {
+       case MS_NODE:
+               vty->node = CONFIG_NODE;
+               vty->index = NULL;
+               break;
+       case TESTSIM_NODE:
+               vty->node = MS_NODE;
+               break;
+       default:
+               vty->node = CONFIG_NODE;
+       }
+
+       return vty->node;
+}
+
+/* Down vty node level. */
+gDEFUN(ournode_exit,
+       ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
+{
+       switch (vty->node) {
+       case MS_NODE:
+               vty->node = CONFIG_NODE;
+               vty->index = NULL;
+               break;
+       case TESTSIM_NODE:
+               vty->node = MS_NODE;
+               break;
+       default:
+               break;
+       }
+       return CMD_SUCCESS;
+}
+
+/* End of configuration. */
+gDEFUN(ournode_end,
+       ournode_end_cmd, "end", "End current mode and change to enable mode.")
+{
+       switch (vty->node) {
+       case VIEW_NODE:
+       case ENABLE_NODE:
+               /* Nothing to do. */
+               break;
+       case CONFIG_NODE:
+       case VTY_NODE:
+       case MS_NODE:
+       case TESTSIM_NODE:
+               vty_config_unlock(vty);
+               vty->node = ENABLE_NODE;
+               vty->index = NULL;
+               vty->index_sub = NULL;
+               break;
+       default:
+               break;
+       }
+       return CMD_SUCCESS;
+}
+
 int ms_vty_init(void)
 {
-       cmd_init(1);
-       vty_init();
-
-       install_element(ENABLE_NODE, &show_ms_cmd);
-       install_element(VIEW_NODE, &show_ms_cmd);
-       install_element(ENABLE_NODE, &show_subscr_cmd);
-       install_element(VIEW_NODE, &show_subscr_cmd);
-       install_element(ENABLE_NODE, &show_support_cmd);
-       install_element(VIEW_NODE, &show_support_cmd);
-       install_element(ENABLE_NODE, &show_states_cmd);
-       install_element(VIEW_NODE, &show_states_cmd);
-       install_element(ENABLE_NODE, &show_cell_cmd);
-       install_element(VIEW_NODE, &show_cell_cmd);
-       install_element(ENABLE_NODE, &show_cell_si_cmd);
-       install_element(VIEW_NODE, &show_cell_si_cmd);
-       install_element(ENABLE_NODE, &show_ba_cmd);
-       install_element(VIEW_NODE, &show_ba_cmd);
-       install_element(ENABLE_NODE, &show_forb_la_cmd);
-       install_element(VIEW_NODE, &show_forb_la_cmd);
-       install_element(ENABLE_NODE, &show_forb_plmn_cmd);
-       install_element(VIEW_NODE, &show_forb_plmn_cmd);
+       install_element_ve(&show_ms_cmd);
+       install_element_ve(&show_subscr_cmd);
+       install_element_ve(&show_support_cmd);
+       install_element_ve(&show_states_cmd);
+       install_element_ve(&show_cell_cmd);
+       install_element_ve(&show_cell_si_cmd);
+       install_element_ve(&show_ba_cmd);
+       install_element_ve(&show_forb_la_cmd);
+       install_element_ve(&show_forb_plmn_cmd);
 
        install_element(ENABLE_NODE, &insert_test_cmd);
        install_element(ENABLE_NODE, &remove_sim_cmd);
@@ -880,8 +927,11 @@ int ms_vty_init(void)
        install_element(ENABLE_NODE, &call_retr_cmd);
 
        install_element(CONFIG_NODE, &cfg_ms_cmd);
+       install_element(CONFIG_NODE, &ournode_end_cmd);
        install_node(&ms_node, config_write_ms);
        install_default(MS_NODE);
+       install_element(MS_NODE, &ournode_exit_cmd);
+       install_element(MS_NODE, &ournode_end_cmd);
        install_element(MS_NODE, &cfg_ms_mode_cmd);
        install_element(MS_NODE, &cfg_ms_imei_cmd);
        install_element(MS_NODE, &cfg_ms_imei_fixed_cmd);
@@ -898,6 +948,8 @@ int ms_vty_init(void)
        install_element(MS_NODE, &cfg_testsim_cmd);
        install_node(&testsim_node, config_write_dummy);
        install_default(TESTSIM_NODE);
+       install_element(TESTSIM_NODE, &ournode_exit_cmd);
+       install_element(TESTSIM_NODE, &ournode_end_cmd);
        install_element(TESTSIM_NODE, &cfg_test_imsi_cmd);
        install_element(TESTSIM_NODE, &cfg_test_barr_cmd);
        install_element(TESTSIM_NODE, &cfg_test_no_barr_cmd);
@@ -908,3 +960,38 @@ int ms_vty_init(void)
        return 0;
 }
 
+void vty_notify(struct osmocom_ms *ms, const char *fmt, ...)
+{
+       struct telnet_connection *connection;
+       char buffer[1000];
+       va_list args;
+       struct vty *vty;
+
+       if (fmt) {
+               va_start(args, fmt);
+               vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
+               buffer[sizeof(buffer) - 1] = '\0';
+               va_end(args);
+
+               if (!buffer[0])
+                       return;
+       }
+
+       llist_for_each_entry(connection, &active_connections, entry) {
+               vty = connection->vty;
+               if (!vty)
+                       continue;
+               if (!fmt) {
+                       vty_out(vty, "%s%% (MS %s)%s", VTY_NEWLINE, ms->name,
+                               VTY_NEWLINE);
+                       continue;
+               }
+               if (buffer[strlen(buffer) - 1] == '\n') {
+                       buffer[strlen(buffer) - 1] = '\0';
+                       vty_out(vty, "%% %s%s", buffer, VTY_NEWLINE);
+                       buffer[strlen(buffer)] = '\n';
+               } else
+                       vty_out(vty, "%% %s", buffer);
+       }
+}
+