mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-29 17:13:46 +00:00
lib/command.c: rewrite command matching/parsing
Add support for keyword commands. Includes new documentation for DEFUN() in lib/command.h, for preexisting features as well as new keyword specification. Signed-off-by: Christian Franke <chris@opensourcerouting.org> Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
e712d0e366
commit
cd40b329a2
@ -277,9 +277,6 @@ babel_init(int argc, char **argv)
|
||||
/* this replace kernel_setup && kernel_setup_socket */
|
||||
babelz_zebra_init ();
|
||||
|
||||
/* Sort all installed commands. */
|
||||
sort_node ();
|
||||
|
||||
/* Get zebra configuration file. */
|
||||
zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
|
||||
vty_read_config (babel_config_file, babel_config_default);
|
||||
|
@ -431,9 +431,6 @@ main (int argc, char **argv)
|
||||
/* BGP related initialization. */
|
||||
bgp_init ();
|
||||
|
||||
/* Sort CLI commands. */
|
||||
sort_node ();
|
||||
|
||||
/* Parse config file. */
|
||||
vty_read_config (config_file, config_default);
|
||||
|
||||
|
@ -339,8 +339,6 @@ main (int argc, char **argv, char **envp)
|
||||
|
||||
isis_zebra_init ();
|
||||
|
||||
sort_node ();
|
||||
|
||||
/* parse config file */
|
||||
/* this is needed three times! because we have interfaces before the areas */
|
||||
vty_read_config (config_file, config_default);
|
||||
|
1849
lib/command.c
1849
lib/command.c
File diff suppressed because it is too large
Load Diff
195
lib/command.h
195
lib/command.h
@ -138,18 +138,32 @@ struct cmd_element
|
||||
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 */
|
||||
vector tokens; /* Vector of cmd_tokens */
|
||||
u_char attr; /* Command attributes */
|
||||
};
|
||||
|
||||
/* Command description structure. */
|
||||
struct desc
|
||||
|
||||
enum cmd_token_type
|
||||
{
|
||||
TOKEN_TERMINAL = 0,
|
||||
TOKEN_MULTIPLE,
|
||||
TOKEN_KEYWORD,
|
||||
};
|
||||
|
||||
/* Command description structure. */
|
||||
struct cmd_token
|
||||
{
|
||||
enum cmd_token_type type;
|
||||
|
||||
/* Used for type == MULTIPLE */
|
||||
vector multiple; /* vector of cmd_token, type == FINAL */
|
||||
|
||||
/* Used for type == KEYWORD */
|
||||
vector keyword; /* vector of vector of cmd_tokens */
|
||||
|
||||
/* Used for type == TERMINAL */
|
||||
char *cmd; /* Command string. */
|
||||
char *str; /* Command's description. */
|
||||
char *desc; /* Command's description. */
|
||||
};
|
||||
|
||||
/* Return value of the commands. */
|
||||
@ -192,7 +206,170 @@ struct desc
|
||||
int argc __attribute__ ((unused)), \
|
||||
const char *argv[] __attribute__ ((unused)) )
|
||||
|
||||
/* DEFUN for vty command interafce. Little bit hacky ;-). */
|
||||
/* DEFUN for vty command interafce. Little bit hacky ;-).
|
||||
*
|
||||
* DEFUN(funcname, cmdname, cmdstr, helpstr)
|
||||
*
|
||||
* funcname
|
||||
* ========
|
||||
*
|
||||
* Name of the function that will be defined.
|
||||
*
|
||||
* cmdname
|
||||
* =======
|
||||
*
|
||||
* Name of the struct that will be defined for the command.
|
||||
*
|
||||
* cmdstr
|
||||
* ======
|
||||
*
|
||||
* The cmdstr defines the command syntax. It is used by the vty subsystem
|
||||
* and vtysh to perform matching and completion in the cli. So you have to take
|
||||
* care to construct it adhering to the following grammar. The names used
|
||||
* for the production rules losely represent the names used in lib/command.c
|
||||
*
|
||||
* cmdstr = cmd_token , { " " , cmd_token } ;
|
||||
*
|
||||
* cmd_token = cmd_terminal
|
||||
* | cmd_multiple
|
||||
* | cmd_keyword ;
|
||||
*
|
||||
* cmd_terminal_fixed = fixed_string
|
||||
* | variable
|
||||
* | range
|
||||
* | ipv4
|
||||
* | ipv4_prefix
|
||||
* | ipv6
|
||||
* | ipv6_prefix ;
|
||||
*
|
||||
* cmd_terminal = cmd_terminal_fixed
|
||||
* | option
|
||||
* | vararg ;
|
||||
*
|
||||
* multiple_part = cmd_terminal_fixed ;
|
||||
* cmd_multiple = "(" , multiple_part , ( "|" | { "|" , multiple_part } ) , ")" ;
|
||||
*
|
||||
* keyword_part = fixed_string , { " " , ( cmd_terminal_fixed | cmd_multiple ) } ;
|
||||
* cmd_keyword = "{" , keyword_part , { "|" , keyword_part } , "}" ;
|
||||
*
|
||||
* lowercase = "a" | ... | "z" ;
|
||||
* uppercase = "A" | ... | "Z" ;
|
||||
* digit = "0" | ... | "9" ;
|
||||
* number = digit , { digit } ;
|
||||
*
|
||||
* fixed_string = (lowercase | digit) , { lowercase | digit | uppercase | "-" | "_" } ;
|
||||
* variable = uppercase , { uppercase | "_" } ;
|
||||
* range = "<" , number , "-" , number , ">" ;
|
||||
* ipv4 = "A.B.C.D" ;
|
||||
* ipv4_prefix = "A.B.C.D/M" ;
|
||||
* ipv6 = "X:X::X:X" ;
|
||||
* ipv6_prefix = "X:X::X:X/M" ;
|
||||
* option = "[" , variable , "]" ;
|
||||
* vararg = "." , variable ;
|
||||
*
|
||||
* To put that all in a textual description: A cmdstr is a sequence of tokens,
|
||||
* separated by spaces.
|
||||
*
|
||||
* Terminal Tokens:
|
||||
*
|
||||
* A very simple cmdstring would be something like: "show ip bgp". It consists
|
||||
* of three Terminal Tokens, each containing a fixed string. When this command
|
||||
* is called, no arguments will be passed down to the function implementing it,
|
||||
* as it only consists of fixed strings.
|
||||
*
|
||||
* Apart from fixed strings, Terminal Tokens can also contain variables:
|
||||
* An example would be "show ip bgp A.B.C.D". This command expects an IPv4
|
||||
* as argument. As this is a variable, the IP address entered by the user will
|
||||
* be passed down as an argument. Apart from two exceptions, the other options
|
||||
* for Terminal Tokens behave exactly as we just discussed and only make a
|
||||
* difference for the CLI. The two exceptions will be discussed in the next
|
||||
* paragraphs.
|
||||
*
|
||||
* A Terminal Token can contain a so called option match. This is a simple
|
||||
* string variable that the user may omit. An example would be:
|
||||
* "show interface [IFNAME]". If the user calls this without an interface as
|
||||
* argument, no arguments will be passed down to the function implementing
|
||||
* this command. Otherwise, the interface name will be provided to the function
|
||||
* as a regular argument.
|
||||
|
||||
* Also, a Terminal Token can contain a so called vararg. This is used e.g. in
|
||||
* "show ip bgp regexp .LINE". The last token is a vararg match and will
|
||||
* consume all the arguments the user inputs on the command line and append
|
||||
* those to the list of arguments passed down to the function implementing this
|
||||
* command. (Therefore, it doesn't make much sense to have any tokens after a
|
||||
* vararg because the vararg will already consume all the words the user entered
|
||||
* in the CLI)
|
||||
*
|
||||
* Multiple Tokens:
|
||||
*
|
||||
* The Multiple Token type can be used if there are multiple possibilities what
|
||||
* arguments may be used for a command, but it should map to the same function
|
||||
* nonetheless. An example would be "ip route A.B.C.D/M (reject|blackhole)"
|
||||
* In that case both "reject" and "blackhole" would be acceptable as last
|
||||
* arguments. The words matched by Multiple Tokens are always added to the
|
||||
* argument list, even if they are matched by fixed strings. Such a Multiple
|
||||
* Token can contain almost any type of token that would also be acceptable
|
||||
* for a Terminal Token, the exception are optional variables and varag.
|
||||
*
|
||||
* There is one special case that is used in some places of Quagga that should be
|
||||
* pointed out here shortly. An example would be "password (8|) WORD". This
|
||||
* construct is used to have fixed strings communicated as arguments. (The "8"
|
||||
* will be passed down as an argument in this case) It does not mean that
|
||||
* the "8" is optional. Another historic and possibly surprising property of
|
||||
* this construct is that it consumes two parts of helpstr. (Help
|
||||
* strings will be explained later)
|
||||
*
|
||||
* Keyword Tokens:
|
||||
*
|
||||
* There are commands that take a lot of different and possibly optional arguments.
|
||||
* An example from ospf would be the "default-information originate" command. This
|
||||
* command takes a lot of optional arguments that may be provided in any order.
|
||||
* To accomodate such commands, the Keyword Token has been implemented.
|
||||
* Using the keyword token, the "default-information originate" command and all
|
||||
* its possible options can be represented using this single cmdstr:
|
||||
* "default-information originate \
|
||||
* {always|metric <0-16777214>|metric-type (1|2)|route-map WORD}"
|
||||
*
|
||||
* Keywords always start with a fixed string and may be followed by arguments.
|
||||
* Except optional variables and vararg, everything is permitted here.
|
||||
*
|
||||
* For the special case of a keyword without arguments, either NULL or the
|
||||
* keyword itself will be pushed as an argument, depending on whether the
|
||||
* keyword is present.
|
||||
* For the other keywords, arguments will be only pushed for
|
||||
* variables/Multiple Tokens. If the keyword is not present, the arguments that
|
||||
* would have been pushed will be substituted by NULL.
|
||||
*
|
||||
* A few examples:
|
||||
* "default information originate metric-type 1 metric 1000"
|
||||
* would yield the following arguments:
|
||||
* { NULL, "1000", "1", NULL }
|
||||
*
|
||||
* "default information originate always route-map RMAP-DEFAULT"
|
||||
* would yield the following arguments:
|
||||
* { "always", NULL, NULL, "RMAP-DEFAULT" }
|
||||
*
|
||||
* helpstr
|
||||
* =======
|
||||
*
|
||||
* The helpstr is used to show a short explantion for the commands that
|
||||
* are available when the user presses '?' on the CLI. It is the concatenation
|
||||
* of the helpstrings for all the tokens that make up the command.
|
||||
*
|
||||
* There should be one helpstring for each token in the cmdstr except those
|
||||
* containing other tokens, like Multiple or Keyword Tokens. For those, there
|
||||
* will only be the helpstrings of the contained tokens.
|
||||
*
|
||||
* The individual helpstrings are expected to be in the same order as their
|
||||
* respective Tokens appear in the cmdstr. They should each be terminated with
|
||||
* a linefeed. The last helpstring should be terminated with a linefeed as well.
|
||||
*
|
||||
* Care should also be taken to avoid having similar tokens with different
|
||||
* helpstrings. Imagine e.g. the commands "show ip ospf" and "show ip bgp".
|
||||
* they both contain a helpstring for "show", but only one will be displayed
|
||||
* when the user enters "sh?". If those two helpstrings differ, it is not
|
||||
* defined which one will be shown and the behavior is therefore unpredictable.
|
||||
*/
|
||||
#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
|
||||
DEFUN_CMD_FUNC_DECL(funcname) \
|
||||
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
|
||||
@ -330,7 +507,6 @@ struct desc
|
||||
extern void install_node (struct cmd_node *, int (*) (struct vty *));
|
||||
extern void install_default (enum node_type);
|
||||
extern void install_element (enum node_type, struct cmd_element *);
|
||||
extern void sort_node (void);
|
||||
|
||||
/* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated
|
||||
string with a space between each element (allocated using
|
||||
@ -346,7 +522,6 @@ extern int config_from_file (struct vty *, FILE *);
|
||||
extern enum node_type node_parent (enum node_type);
|
||||
extern int cmd_execute_command (vector, struct vty *, struct cmd_element **, int);
|
||||
extern int cmd_execute_command_strict (vector, struct vty *, struct cmd_element **);
|
||||
extern void config_replace_string (struct cmd_element *, char *, ...);
|
||||
extern void cmd_init (int);
|
||||
extern void cmd_terminate (void);
|
||||
|
||||
|
@ -54,7 +54,7 @@ struct memory_list memory_list_lib[] =
|
||||
{ MTYPE_ROUTE_MAP_RULE, "Route map rule" },
|
||||
{ MTYPE_ROUTE_MAP_RULE_STR, "Route map rule str" },
|
||||
{ MTYPE_ROUTE_MAP_COMPILED, "Route map compiled" },
|
||||
{ MTYPE_DESC, "Command desc" },
|
||||
{ MTYPE_CMD_TOKENS, "Command desc" },
|
||||
{ MTYPE_KEY, "Key" },
|
||||
{ MTYPE_KEYCHAIN, "Key chain" },
|
||||
{ MTYPE_IF_RMAP, "Interface route map" },
|
||||
|
54
lib/vty.c
54
lib/vty.c
@ -931,23 +931,23 @@ vty_complete_command (struct vty *vty)
|
||||
|
||||
static void
|
||||
vty_describe_fold (struct vty *vty, int cmd_width,
|
||||
unsigned int desc_width, struct desc *desc)
|
||||
unsigned int desc_width, struct cmd_token *token)
|
||||
{
|
||||
char *buf;
|
||||
const char *cmd, *p;
|
||||
int pos;
|
||||
|
||||
cmd = desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd;
|
||||
cmd = token->cmd[0] == '.' ? token->cmd + 1 : token->cmd;
|
||||
|
||||
if (desc_width <= 0)
|
||||
{
|
||||
vty_out (vty, " %-*s %s%s", cmd_width, cmd, desc->str, VTY_NEWLINE);
|
||||
vty_out (vty, " %-*s %s%s", cmd_width, cmd, token->desc, VTY_NEWLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = XCALLOC (MTYPE_TMP, strlen (desc->str) + 1);
|
||||
buf = XCALLOC (MTYPE_TMP, strlen (token->desc) + 1);
|
||||
|
||||
for (p = desc->str; strlen (p) > desc_width; p += pos + 1)
|
||||
for (p = token->desc; strlen (p) > desc_width; p += pos + 1)
|
||||
{
|
||||
for (pos = desc_width; pos > 0; pos--)
|
||||
if (*(p + pos) == ' ')
|
||||
@ -976,7 +976,7 @@ vty_describe_command (struct vty *vty)
|
||||
vector vline;
|
||||
vector describe;
|
||||
unsigned int i, width, desc_width;
|
||||
struct desc *desc, *desc_cr = NULL;
|
||||
struct cmd_token *token, *token_cr = NULL;
|
||||
|
||||
vline = cmd_make_strvec (vty->buf);
|
||||
|
||||
@ -1010,15 +1010,15 @@ vty_describe_command (struct vty *vty)
|
||||
/* Get width of command string. */
|
||||
width = 0;
|
||||
for (i = 0; i < vector_active (describe); i++)
|
||||
if ((desc = vector_slot (describe, i)) != NULL)
|
||||
if ((token = vector_slot (describe, i)) != NULL)
|
||||
{
|
||||
unsigned int len;
|
||||
|
||||
if (desc->cmd[0] == '\0')
|
||||
if (token->cmd[0] == '\0')
|
||||
continue;
|
||||
|
||||
len = strlen (desc->cmd);
|
||||
if (desc->cmd[0] == '.')
|
||||
len = strlen (token->cmd);
|
||||
if (token->cmd[0] == '.')
|
||||
len--;
|
||||
|
||||
if (width < len)
|
||||
@ -1030,27 +1030,27 @@ vty_describe_command (struct vty *vty)
|
||||
|
||||
/* Print out description. */
|
||||
for (i = 0; i < vector_active (describe); i++)
|
||||
if ((desc = vector_slot (describe, i)) != NULL)
|
||||
if ((token = vector_slot (describe, i)) != NULL)
|
||||
{
|
||||
if (desc->cmd[0] == '\0')
|
||||
if (token->cmd[0] == '\0')
|
||||
continue;
|
||||
|
||||
if (strcmp (desc->cmd, command_cr) == 0)
|
||||
if (strcmp (token->cmd, command_cr) == 0)
|
||||
{
|
||||
desc_cr = desc;
|
||||
token_cr = token;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!desc->str)
|
||||
if (!token->desc)
|
||||
vty_out (vty, " %-s%s",
|
||||
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
|
||||
token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
|
||||
VTY_NEWLINE);
|
||||
else if (desc_width >= strlen (desc->str))
|
||||
else if (desc_width >= strlen (token->desc))
|
||||
vty_out (vty, " %-*s %s%s", width,
|
||||
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
|
||||
desc->str, VTY_NEWLINE);
|
||||
token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
|
||||
token->desc, VTY_NEWLINE);
|
||||
else
|
||||
vty_describe_fold (vty, width, desc_width, desc);
|
||||
vty_describe_fold (vty, width, desc_width, token);
|
||||
|
||||
#if 0
|
||||
vty_out (vty, " %-*s %s%s", width
|
||||
@ -1059,18 +1059,18 @@ vty_describe_command (struct vty *vty)
|
||||
#endif /* 0 */
|
||||
}
|
||||
|
||||
if ((desc = desc_cr))
|
||||
if ((token = token_cr))
|
||||
{
|
||||
if (!desc->str)
|
||||
if (!token->desc)
|
||||
vty_out (vty, " %-s%s",
|
||||
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
|
||||
token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
|
||||
VTY_NEWLINE);
|
||||
else if (desc_width >= strlen (desc->str))
|
||||
else if (desc_width >= strlen (token->desc))
|
||||
vty_out (vty, " %-*s %s%s", width,
|
||||
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
|
||||
desc->str, VTY_NEWLINE);
|
||||
token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
|
||||
token->desc, VTY_NEWLINE);
|
||||
else
|
||||
vty_describe_fold (vty, width, desc_width, desc);
|
||||
vty_describe_fold (vty, width, desc_width, token);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -325,9 +325,6 @@ main (int argc, char *argv[], char *envp[])
|
||||
/* initialize ospf6 */
|
||||
ospf6_init ();
|
||||
|
||||
/* sort command vector */
|
||||
sort_node ();
|
||||
|
||||
/* parse config file */
|
||||
vty_read_config (config_file, config_default);
|
||||
|
||||
|
@ -310,8 +310,6 @@ main (int argc, char **argv)
|
||||
ospf_opaque_init ();
|
||||
#endif /* HAVE_OPAQUE_LSA */
|
||||
|
||||
sort_node ();
|
||||
|
||||
/* Get configuration file. */
|
||||
vty_read_config (config_file, config_default);
|
||||
|
||||
|
@ -287,9 +287,6 @@ main (int argc, char **argv)
|
||||
rip_zclient_init ();
|
||||
rip_peer_init ();
|
||||
|
||||
/* Sort all installed commands. */
|
||||
sort_node ();
|
||||
|
||||
/* Get configuration file. */
|
||||
vty_read_config (config_file, config_default);
|
||||
|
||||
|
@ -282,9 +282,6 @@ main (int argc, char **argv)
|
||||
zebra_init ();
|
||||
ripng_peer_init ();
|
||||
|
||||
/* Sort all installed commands. */
|
||||
sort_node ();
|
||||
|
||||
/* Get configuration file. */
|
||||
vty_read_config (config_file, config_default);
|
||||
|
||||
|
@ -171,8 +171,6 @@ main (int argc, char **argv)
|
||||
/* OSPF vty inits. */
|
||||
test_vty_init ();
|
||||
|
||||
sort_node ();
|
||||
|
||||
/* Change to the daemon program. */
|
||||
if (daemon_mode && daemon (0, 0) < 0)
|
||||
{
|
||||
|
@ -233,8 +233,6 @@ test_init(void)
|
||||
cmd->daemon = 0;
|
||||
cmd->func = test_callback;
|
||||
}
|
||||
sort_node();
|
||||
|
||||
test_load();
|
||||
vty_init_vtysh();
|
||||
}
|
||||
@ -340,8 +338,8 @@ test_run(struct prng *prng, struct vty *vty, const char *cmd, unsigned int edit_
|
||||
{
|
||||
for (j = 0; j < vector_active(descriptions); j++)
|
||||
{
|
||||
struct desc *cmd = vector_slot(descriptions, j);
|
||||
printf(" '%s' '%s'\n", cmd->cmd, cmd->str);
|
||||
struct cmd_token *cmd = vector_slot(descriptions, j);
|
||||
printf(" '%s' '%s'\n", cmd->cmd, cmd->desc);
|
||||
}
|
||||
vector_free(descriptions);
|
||||
}
|
||||
|
@ -554,7 +554,7 @@ vtysh_rl_describe (void)
|
||||
vector vline;
|
||||
vector describe;
|
||||
int width;
|
||||
struct desc *desc;
|
||||
struct cmd_token *token;
|
||||
|
||||
vline = cmd_make_strvec (rl_line_buffer);
|
||||
|
||||
@ -592,15 +592,15 @@ vtysh_rl_describe (void)
|
||||
/* Get width of command string. */
|
||||
width = 0;
|
||||
for (i = 0; i < vector_active (describe); i++)
|
||||
if ((desc = vector_slot (describe, i)) != NULL)
|
||||
if ((token = vector_slot (describe, i)) != NULL)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (desc->cmd[0] == '\0')
|
||||
if (token->cmd[0] == '\0')
|
||||
continue;
|
||||
|
||||
len = strlen (desc->cmd);
|
||||
if (desc->cmd[0] == '.')
|
||||
len = strlen (token->cmd);
|
||||
if (token->cmd[0] == '.')
|
||||
len--;
|
||||
|
||||
if (width < len)
|
||||
@ -608,19 +608,19 @@ vtysh_rl_describe (void)
|
||||
}
|
||||
|
||||
for (i = 0; i < vector_active (describe); i++)
|
||||
if ((desc = vector_slot (describe, i)) != NULL)
|
||||
if ((token = vector_slot (describe, i)) != NULL)
|
||||
{
|
||||
if (desc->cmd[0] == '\0')
|
||||
if (token->cmd[0] == '\0')
|
||||
continue;
|
||||
|
||||
if (! desc->str)
|
||||
if (! token->desc)
|
||||
fprintf (stdout," %-s\n",
|
||||
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd);
|
||||
token->cmd[0] == '.' ? token->cmd + 1 : token->cmd);
|
||||
else
|
||||
fprintf (stdout," %-*s %s\n",
|
||||
width,
|
||||
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
|
||||
desc->str);
|
||||
token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
|
||||
token->desc);
|
||||
}
|
||||
|
||||
cmd_free_strvec (vline);
|
||||
|
@ -299,8 +299,6 @@ main (int argc, char **argv, char **env)
|
||||
|
||||
vty_init_vtysh ();
|
||||
|
||||
sort_node ();
|
||||
|
||||
/* Read vtysh configuration file before connecting to daemons. */
|
||||
vtysh_read_config (config_default);
|
||||
|
||||
|
@ -343,9 +343,6 @@ main (int argc, char **argv)
|
||||
interface_list ();
|
||||
route_read ();
|
||||
|
||||
/* Sort VTY commands. */
|
||||
sort_node ();
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
zebra_snmp_init ();
|
||||
#endif /* HAVE_SNMP */
|
||||
|
@ -298,9 +298,6 @@ main (int argc, char **argv)
|
||||
route_read ();
|
||||
zebra_vty_init();
|
||||
|
||||
/* Sort VTY commands. */
|
||||
sort_node ();
|
||||
|
||||
/* Configuration file read*/
|
||||
vty_read_config (config_file, config_default);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user