From 718e3744195351130f4ce7dbe0613f4b3e23df93 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 13 Dec 2002 20:15:29 +0000 Subject: Initial revision --- lib/command.c | 2981 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2981 insertions(+) create mode 100644 lib/command.c (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c new file mode 100644 index 00000000..8cbecce1 --- /dev/null +++ b/lib/command.c @@ -0,0 +1,2981 @@ +/* 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 + +#include "command.h" +#include "memory.h" +#include "log.h" +#include "version.h" + +/* Command vector which includes some level of command lists. Normally + each daemon maintains each own cmdvec. */ +vector cmdvec; + +/* Host information structure. */ +struct host host; + +/* Default motd string. */ +char *default_motd = +"\r\n\ +Hello, this is zebra (version " ZEBRA_VERSION ").\r\n\ +Copyright 1996-2002 Kunihiro Ishiguro.\r\n\ +\r\n"; + +/* 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 +}; + +/* Utility function to concatenate argv argument into a single string + with inserting ' ' character between each argument. */ +char * +argv_concat (char **argv, int argc, int shift) +{ + int i; + int len; + int index; + char *str; + + str = NULL; + index = 0; + + for (i = shift; i < argc; i++) + { + len = strlen (argv[i]); + + if (i == shift) + { + str = XSTRDUP (MTYPE_TMP, argv[i]); + index = len; + } + else + { + str = XREALLOC (MTYPE_TMP, str, (index + len + 2)); + str[index++] = ' '; + memcpy (str + index, argv[i], len); + index += len; + str[index] = '\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 (). */ +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); +} + +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 () +{ + int i, j; + struct cmd_node *cnode; + vector descvec; + struct cmd_element *cmd_element; + + for (i = 0; i < vector_max (cmdvec); i++) + if ((cnode = vector_slot (cmdvec, i)) != NULL) + { + vector cmd_vector = cnode->cmd_vector; + qsort (cmd_vector->index, cmd_vector->max, sizeof (void *), cmp_node); + + for (j = 0; j < vector_max (cmd_vector); j++) + if ((cmd_element = vector_slot (cmd_vector, j)) != NULL) + { + descvec = vector_slot (cmd_element->strvec, + vector_max (cmd_element->strvec) - 1); + qsort (descvec->index, descvec->max, 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 (char *string) +{ + char *cp, *start, *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 = XMALLOC (MTYPE_STRVEC, strlen + 1); + 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) +{ + int i; + char *cp; + + if (!v) + return; + + for (i = 0; i < vector_max (v); i++) + if ((cp = vector_slot (v, i)) != NULL) + XFREE (MTYPE_STRVEC, cp); + + vector_free (v); +} + +/* Fetch next description. Used in cmd_make_descvec(). */ +char * +cmd_desc_str (char **string) +{ + char *cp, *start, *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 = XMALLOC (MTYPE_STRVEC, strlen + 1); + memcpy (token, start, strlen); + *(token + strlen) = '\0'; + + *string = cp; + + return token; +} + +/* New string vector. */ +vector +cmd_make_descvec (char *string, char *descstr) +{ + int multiple = 0; + char *sp; + char *token; + int len; + char *cp; + 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 = XMALLOC (MTYPE_STRVEC, len + 1); + memcpy (token, sp, len); + *(token + len) = '\0'; + + desc = XCALLOC (MTYPE_DESC, sizeof (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. */ +int +cmd_cmdsize (vector strvec) +{ + int i; + char *str; + int size = 0; + vector descvec; + + for (i = 0; i < vector_max (strvec); i++) + { + descvec = vector_slot (strvec, i); + + if (vector_max (descvec) == 1) + { + struct desc *desc = vector_slot (descvec, 0); + + str = desc->cmd; + + if (str == NULL || CMD_OPTION (str)) + return size; + else + size++; + } + else + size++; + } + return size; +} + +/* Return prompt character of specified node. */ +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); +} + +static unsigned char itoa64[] = +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +void +to64(char *s, long v, int n) +{ + while (--n >= 0) + { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +char *zencrypt (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); +} + +/* This function write configuration of this host. */ +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 (host.logfile) + vty_out (vty, "log file %s%s", host.logfile, VTY_NEWLINE); + + if (host.log_stdout) + vty_out (vty, "log stdout%s", VTY_NEWLINE); + + if (host.log_syslog) + vty_out (vty, "log syslog%s", VTY_NEWLINE); + + if (zlog_default->maskpri != LOG_DEBUG) + vty_out (vty, "log trap %s%s", zlog_priority[zlog_default->maskpri], VTY_NEWLINE); + + if (zlog_default->record_priority == 1) + vty_out (vty, "log record-priority%s", VTY_NEWLINE); + + 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.motd) + vty_out (vty, "no banner motd%s", VTY_NEWLINE); + + return 1; +} + +/* Utility function for getting command vector. */ +vector +cmd_node_vector (vector v, enum node_type ntype) +{ + struct cmd_node *cnode = vector_slot (v, ntype); + return cnode->cmd_vector; +} + +/* Filter command vector by symbol */ +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; +} + +/* 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 +}; + +enum match_type +cmd_ipv4_match (char *str) +{ + 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; +} + +enum match_type +cmd_ipv4_prefix_match (char *str) +{ + 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 + +enum match_type +cmd_ipv6_match (char *str) +{ + int state = STATE_START; + int colons = 0, nums = 0, double_colon = 0; + char *sp = NULL; + + if (str == NULL) + return partly_match; + + if (strspn (str, IPV6_ADDR_STR) != strlen (str)) + return no_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; +} + +enum match_type +cmd_ipv6_prefix_match (char *str) +{ + int state = STATE_START; + int colons = 0, nums = 0, double_colon = 0; + int mask; + 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; +} + +#define DECIMAL_STRLEN_MAX 10 + +int +cmd_range_match (char *range, 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. */ +enum match_type +cmd_filter_by_completion (char *command, vector v, int index) +{ + int i; + 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_max (v); i++) + if ((cmd_element = vector_slot (v, i)) != NULL) + { + if (index >= vector_max (cmd_element->strvec)) + vector_slot (v, i) = NULL; + else + { + int j; + int matched = 0; + + descvec = vector_slot (cmd_element->strvec, index); + + for (j = 0; j < vector_max (descvec); j++) + { + 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++; + } + } + 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++; + } + } + 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. */ +enum match_type +cmd_filter_by_string (char *command, vector v, int index) +{ + int i; + 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_max (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_max (cmd_element->strvec)) + vector_slot (v, i) = NULL; + else + { + int j; + int matched = 0; + + descvec = vector_slot (cmd_element->strvec, index); + + for (j = 0; j < vector_max (descvec); j++) + { + 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++; + } + } + 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++; + } + } + 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 */ +int +is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) +{ + int i; + int j; + char *str = NULL; + struct cmd_element *cmd_element; + char *matched = NULL; + vector descvec; + struct desc *desc; + + for (i = 0; i < vector_max (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_max (descvec); j++) + { + enum match_type ret; + + desc = vector_slot (descvec, j); + 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; + 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; + 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 */ +char * +cmd_entry_function (char *src, 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 */ +char * +cmd_entry_function_desc (char *src, char *dst) +{ + if (CMD_VARARG (dst)) + return dst; + + if (CMD_RANGE (dst)) + { + if (cmd_range_match (dst, src)) + return dst; + else + return NULL; + } + + 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; + } + + 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. */ +int +cmd_unique_string (vector v, char *str) +{ + int i; + char *match; + + for (i = 0; i < vector_max (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. */ +int +desc_unique_string (vector v, char *str) +{ + int i; + struct desc *desc; + + for (i = 0; i < vector_max (v); i++) + if ((desc = vector_slot (v, i)) != NULL) + if (strcmp (desc->cmd, str) == 0) + return 1; + return 0; +} + +/* '?' describe command support. */ +vector +cmd_describe_command (vector vline, struct vty *vty, int *status) +{ + int i; + vector cmd_vector; +#define INIT_MATCHVEC_SIZE 10 + vector matchvec; + struct cmd_element *cmd_element; + int index; + static struct desc desc_cr = { "", "" }; + + /* Set index. */ + index = vector_max (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. */ + for (i = 0; i < index; i++) + { + enum match_type match; + char *command; + int ret; + + 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; + int j, k; + + for (j = 0; j < vector_max (cmd_vector); j++) + if ((cmd_element = vector_slot (cmd_vector, j)) != NULL) + { + descvec = vector_slot (cmd_element->strvec, + vector_max (cmd_element->strvec) - 1); + for (k = 0; k < vector_max (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 description vector. */ + for (i = 0; i < vector_max (cmd_vector); i++) + if ((cmd_element = vector_slot (cmd_vector, i)) != NULL) + { + char *string = NULL; + vector strvec = cmd_element->strvec; + + if (index > vector_max (strvec)) + vector_slot (cmd_vector, i) = NULL; + else + { + /* Check is command is completed. */ + if (index == vector_max (strvec)) + { + string = ""; + if (! desc_unique_string (matchvec, string)) + vector_set (matchvec, &desc_cr); + } + else + { + int j; + vector descvec = vector_slot (strvec, index); + struct desc *desc; + + for (j = 0; j < vector_max (descvec); j++) + { + desc = vector_slot (descvec, j); + string = cmd_entry_function_desc (vector_slot (vline, index), 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; +} + +/* Check LCD of matched command. */ +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. */ +char ** +cmd_complete_command (vector vline, struct vty *vty, int *status) +{ + 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; + int index = vector_max (vline) - 1; + char **match_str; + struct desc *desc; + vector descvec; + char *command; + int lcd; + + /* First, filter by preceeding command string */ + for (i = 0; i < index; i++) + { + enum match_type match; + int ret; + + command = vector_slot (vline, i); + + /* 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_max (cmd_vector); i++) + if ((cmd_element = vector_slot (cmd_vector, i)) != NULL) + { + char *string; + vector strvec = cmd_element->strvec; + + /* Check field length */ + if (index >= vector_max (strvec)) + vector_slot (cmd_vector, i) = NULL; + else + { + int j; + + descvec = vector_slot (strvec, index); + for (j = 0; j < vector_max (descvec); j++) + { + 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, XSTRDUP (MTYPE_TMP, 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 = XMALLOC (MTYPE_TMP, lcd + 1); + memcpy (lcdstr, matchvec->index[0], lcd); + lcdstr[lcd] = '\0'; + + /* match_str = (char **) &lcdstr; */ + + /* Free matchvec. */ + for (i = 0; i < vector_max (matchvec); i++) + { + if (vector_slot (matchvec, i)) + XFREE (MTYPE_TMP, 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; +} + +/* Execute command by argument vline vector. */ +int +cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) +{ + int i; + int index; + vector cmd_vector; + struct cmd_element *cmd_element; + struct cmd_element *matched_element; + unsigned int matched_count, incomplete_count; + int argc; + 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_max (vline); index++) + { + int ret; + + command = vector_slot (vline, index); + + 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_max (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; +#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_max (vline); i++) + { + if (varflag) + argv[argc++] = vector_slot (vline, i); + else + { + vector descvec = vector_slot (matched_element->strvec, i); + + if (vector_max (descvec) == 1) + { + struct desc *desc = vector_slot (descvec, 0); + char *str = desc->cmd; + + if (CMD_VARARG (str)) + varflag = 1; + + if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str)) + 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); +} + +/* Execute command by argument readline. */ +int +cmd_execute_command_strict (vector vline, struct vty *vty, + struct cmd_element **cmd) +{ + int i; + int index; + vector cmd_vector; + struct cmd_element *cmd_element; + struct cmd_element *matched_element; + unsigned int matched_count, incomplete_count; + int argc; + 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_max (vline); index++) + { + int ret; + + command = vector_slot (vline, index); + + 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_max (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_max (vline); i++) + { + if (varflag) + argv[argc++] = vector_slot (vline, i); + else + { + vector descvec = vector_slot (matched_element->strvec, i); + + if (vector_max (descvec) == 1) + { + struct desc *desc = vector_slot (descvec, 0); + char *str = desc->cmd; + + if (CMD_VARARG (str)) + varflag = 1; + + if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str)) + 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, FILE *fp) +{ + int ret; + vector vline; + + while (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 */ + if (ret != CMD_SUCCESS && ret != CMD_WARNING) + { + if (vty->node == KEYCHAIN_KEY_NODE) + { + vty->node = KEYCHAIN_NODE; + + ret = cmd_execute_command_strict (vline, vty, NULL); + + if (ret != CMD_SUCCESS && ret != CMD_WARNING) + { + vty->node = CONFIG_NODE; + ret = cmd_execute_command_strict (vline, vty, NULL); + } + } + else + { + vty->node = CONFIG_NODE; + ret = cmd_execute_command_strict (vline, vty, NULL); + } + } + + cmd_free_strvec (vline); + + if (ret != CMD_SUCCESS && ret != CMD_WARNING) + 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 VIEW_NODE: + case ENABLE_NODE: + if (vty_shell (vty)) + exit (0); + else + vty->status = VTY_CLOSE; + break; + case CONFIG_NODE: + vty->node = ENABLE_NODE; + vty_config_unlock (vty); + break; + case INTERFACE_NODE: + case ZEBRA_NODE: + case BGP_NODE: + case RIP_NODE: + case RIPNG_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case KEYCHAIN_NODE: + case MASC_NODE: + case RMAP_NODE: + case VTY_NODE: + vty->node = CONFIG_NODE; + break; + case BGP_VPNV4_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV6_NODE: + vty->node = BGP_NODE; + break; + case KEYCHAIN_KEY_NODE: + vty->node = KEYCHAIN_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 INTERFACE_NODE: + case ZEBRA_NODE: + case RIP_NODE: + case RIPNG_NODE: + case BGP_NODE: + case BGP_VPNV4_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV6_NODE: + case RMAP_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case KEYCHAIN_NODE: + case KEYCHAIN_KEY_NODE: + case MASC_NODE: + case VTY_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 zebra version\n") +{ + vty_out (vty, "Zebra %s (%s).%s", ZEBRA_VERSION, + host_name, + VTY_NEWLINE); + vty_out (vty, "Copyright 1996-2002, Kunihiro Ishiguro.%s", 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, + "Zebra VTY provides advanced help feature. 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") +{ + int i; + struct cmd_node *cnode = vector_slot (cmdvec, vty->node); + struct cmd_element *cmd; + + for (i = 0; i < vector_max (cnode->cmd_vector); i++) + if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL) + 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") +{ + 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 = malloc (strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1); + strcpy (config_file_sav, config_file); + strcat (config_file_sav, CONF_BACKUP_EXT); + + + config_file_tmp = malloc (strlen (config_file) + 8); + sprintf (config_file_tmp, "%s.XXXXXX", config_file); + + /* Open file to configuration write. */ + fd = mkstemp (config_file_tmp); + if (fd < 0) + { + vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp, + VTY_NEWLINE); + free (config_file_tmp); + 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! Zebra configuration saved from vty\n! "); + vty_time_print (file_vty, 1); + vty_out (file_vty, "!\n"); + + for (i = 0; i < vector_max (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 (unlink (config_file_sav) != 0) + if (errno != ENOENT) + { + vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav, + VTY_NEWLINE); + free (config_file_sav); + free (config_file_tmp); + unlink (config_file_tmp); + return CMD_WARNING; + } + if (link (config_file, config_file_sav) != 0) + { + vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav, + VTY_NEWLINE); + free (config_file_sav); + free (config_file_tmp); + unlink (config_file_tmp); + return CMD_WARNING; + } + sync (); + if (unlink (config_file) != 0) + { + vty_out (vty, "Can't unlink configuration file %s.%s", config_file, + VTY_NEWLINE); + free (config_file_sav); + free (config_file_tmp); + unlink (config_file_tmp); + return CMD_WARNING; + } + if (link (config_file_tmp, config_file) != 0) + { + vty_out (vty, "Can't save configuration file %s.%s", config_file, + VTY_NEWLINE); + free (config_file_sav); + free (config_file_tmp); + unlink (config_file_tmp); + return CMD_WARNING; + } + unlink (config_file_tmp); + sync (); + + free (config_file_sav); + free (config_file_tmp); + 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") +{ + int i; + struct cmd_node *node; + + if (vty->type == VTY_SHELL_SERV) + { + for (i = 0; i < vector_max (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_max (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]; + FILE *confp; + + confp = 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 (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); + } + + 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) + XFREE (0, host.name); + + host.name = strdup (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) + XFREE (0, 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) + XFREE (0, host.password); + host.password = NULL; + if (host.password_encrypt) + XFREE (0, host.password_encrypt); + host.password_encrypt = XSTRDUP (0, strdup (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) + XFREE (0, host.password); + host.password = NULL; + + if (host.encrypt) + { + if (host.password_encrypt) + XFREE (0, host.password_encrypt); + host.password_encrypt = XSTRDUP (0, zencrypt (argv[0])); + } + else + host.password = XSTRDUP (0, 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) + XFREE (0, host.enable); + host.enable = NULL; + + if (host.enable_encrypt) + XFREE (0, host.enable_encrypt); + host.enable_encrypt = XSTRDUP (0, 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) + XFREE (0, host.enable); + host.enable = NULL; + + /* Plain password input. */ + if (host.encrypt) + { + if (host.enable_encrypt) + XFREE (0, host.enable_encrypt); + host.enable_encrypt = XSTRDUP (0, zencrypt (argv[0])); + } + else + host.enable = XSTRDUP (0, 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) + XFREE (0, host.enable); + host.enable = NULL; + + if (host.enable_encrypt) + XFREE (0, host.enable_encrypt); + host.enable_encrypt = NULL; + + return CMD_SUCCESS; +} + +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) + XFREE (0, host.password_encrypt); + host.password_encrypt = XSTRDUP (0, zencrypt (host.password)); + } + if (host.enable) + { + if (host.enable_encrypt) + XFREE (0, host.enable_encrypt); + host.enable_encrypt = XSTRDUP (0, 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) + XFREE (0, host.password_encrypt); + host.password_encrypt = NULL; + + if (host.enable_encrypt) + XFREE (0, host.enable_encrypt); + host.enable_encrypt = NULL; + + return CMD_SUCCESS; +} + +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 (config_log_stdout, + config_log_stdout_cmd, + "log stdout", + "Logging control\n" + "Logging goes to stdout\n") +{ + zlog_set_flag (NULL, ZLOG_STDOUT); + host.log_stdout = 1; + return CMD_SUCCESS; +} + +DEFUN (no_config_log_stdout, + no_config_log_stdout_cmd, + "no log stdout", + NO_STR + "Logging control\n" + "Cancel logging to stdout\n") +{ + zlog_reset_flag (NULL, ZLOG_STDOUT); + host.log_stdout = 0; + return CMD_SUCCESS; +} + +DEFUN (config_log_file, + config_log_file_cmd, + "log file FILENAME", + "Logging control\n" + "Logging to file\n" + "Logging filename\n") +{ + int ret; + char *cwd; + char *fullpath; + + /* Path detection. */ + if (! IS_DIRECTORY_SEP (*argv[0])) + { + cwd = getcwd (NULL, MAXPATHLEN); + fullpath = XMALLOC (MTYPE_TMP, + strlen (cwd) + strlen (argv[0]) + 2); + sprintf (fullpath, "%s/%s", cwd, argv[0]); + } + else + fullpath = argv[0]; + + ret = zlog_set_file (NULL, ZLOG_FILE, fullpath); + + if (!ret) + { + vty_out (vty, "can't open logfile %s\n", argv[0]); + return CMD_WARNING; + } + + if (host.logfile) + XFREE (MTYPE_TMP, host.logfile); + + host.logfile = strdup (argv[0]); + + return CMD_SUCCESS; +} + +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) + XFREE (MTYPE_TMP, host.logfile); + + host.logfile = NULL; + + return CMD_SUCCESS; +} + +DEFUN (config_log_syslog, + config_log_syslog_cmd, + "log syslog", + "Logging control\n" + "Logging goes to syslog\n") +{ + zlog_set_flag (NULL, ZLOG_SYSLOG); + host.log_syslog = 1; + return CMD_SUCCESS; +} + +DEFUN (no_config_log_syslog, + no_config_log_syslog_cmd, + "no log syslog", + NO_STR + "Logging control\n" + "Cancel logging to syslog\n") +{ + zlog_reset_flag (NULL, ZLOG_SYSLOG); + host.log_syslog = 0; + return CMD_SUCCESS; +} + +DEFUN (config_log_trap, + config_log_trap_cmd, + "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)", + "Logging control\n" + "Limit logging to specifed level\n") +{ + int new_level ; + + for ( new_level = 0 ; zlog_priority [new_level] != NULL ; new_level ++ ) + { + if ( strcmp ( argv[0], zlog_priority [new_level] ) == 0 ) + /* found new logging level */ + { + zlog_default->maskpri = new_level; + return CMD_SUCCESS; + } + } + return CMD_ERR_NO_MATCH; +} + +DEFUN (no_config_log_trap, + no_config_log_trap_cmd, + "no log trap", + NO_STR + "Logging control\n" + "Permit all logging information\n") +{ + zlog_default->maskpri = 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; +} + + +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; + return CMD_SUCCESS; +} + +/* Set config filename. Called from vty.c */ +void +host_config_set (char *filename) +{ + host.config = strdup (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; + + /* 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); + } + + if (terminal) + { + install_default (ENABLE_NODE); + install_element (ENABLE_NODE, &config_disable_cmd); + install_element (ENABLE_NODE, &config_terminal_cmd); + install_element (ENABLE_NODE, ©_runningconfig_startupconfig_cmd); + } + install_element (ENABLE_NODE, &show_startup_config_cmd); + install_element (ENABLE_NODE, &show_version_cmd); + install_element (ENABLE_NODE, &config_terminal_length_cmd); + install_element (ENABLE_NODE, &config_terminal_no_length_cmd); + + if (terminal) + install_default (CONFIG_NODE); + install_element (CONFIG_NODE, &hostname_cmd); + install_element (CONFIG_NODE, &no_hostname_cmd); + 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); + if (terminal) + { + install_element (CONFIG_NODE, &config_log_stdout_cmd); + install_element (CONFIG_NODE, &no_config_log_stdout_cmd); + install_element (CONFIG_NODE, &config_log_file_cmd); + install_element (CONFIG_NODE, &no_config_log_file_cmd); + install_element (CONFIG_NODE, &config_log_syslog_cmd); + install_element (CONFIG_NODE, &no_config_log_syslog_cmd); + install_element (CONFIG_NODE, &config_log_trap_cmd); + install_element (CONFIG_NODE, &no_config_log_trap_cmd); + install_element (CONFIG_NODE, &config_log_record_priority_cmd); + install_element (CONFIG_NODE, &no_config_log_record_priority_cmd); + install_element (CONFIG_NODE, &service_password_encrypt_cmd); + install_element (CONFIG_NODE, &no_service_password_encrypt_cmd); + install_element (CONFIG_NODE, &banner_motd_default_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)); +} -- cgit v1.2.3 From b92938a7364d220f2ca6d77a5722433159520e02 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 13 Dec 2002 21:20:42 +0000 Subject: Yon Uriarte [zebra 16671] [PATCH] CLI extensions. --- lib/command.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 157 insertions(+), 22 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 8cbecce1..8fd2b648 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1411,9 +1411,21 @@ desc_unique_string (vector v, char *str) return 0; } +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. */ vector -cmd_describe_command (vector vline, struct vty *vty, int *status) +cmd_describe_command_real (vector vline, struct vty *vty, int *status) { int i; vector cmd_vector; @@ -1536,6 +1548,40 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) 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; + 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_max (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. */ int cmd_lcd (char **matched) @@ -1571,7 +1617,7 @@ cmd_lcd (char **matched) /* Command line completion support. */ char ** -cmd_complete_command (vector vline, struct vty *vty, int *status) +cmd_complete_command_real (vector vline, struct vty *vty, int *status) { int i; vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); @@ -1717,9 +1763,59 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) 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; + 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_max (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 node_parent ( enum node_type node ) +{ + enum node_type ret; + + switch ( node ) { + case KEYCHAIN_KEY_NODE: + ret = KEYCHAIN_NODE; + break; + default: + ret = CONFIG_NODE; + } + + return ret; +} + /* Execute command by argument vline vector. */ int -cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) +cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd) { int i; int index; @@ -1842,6 +1938,59 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) return (*matched_element->func) (matched_element, vty, argc, argv); } + +int +cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { + int ret; + enum node_type onode = vty->node; + + if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) + { + vector shifted_vline; + 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_max (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; + } + + + ret = cmd_execute_command_real (vline, vty, cmd); + + /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */ + if ( ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node > CONFIG_NODE ) + { + /* XXX try node_parent(vty->node)? */ + vty->node = CONFIG_NODE; + ret = cmd_execute_command_real (vline, vty, cmd); + if (ret != CMD_SUCCESS && ret != CMD_WARNING) + { + /* if the command changed the node dont reset it */ + if( vty->node == CONFIG_NODE ) + vty->node = onode; + return ret; + } + else + if( vty->node == CONFIG_NODE ) + vty->node = onode; + /* if the command changed the node dont reset it */ + } + return ret; +} + /* Execute command by argument readline. */ int cmd_execute_command_strict (vector vline, struct vty *vty, @@ -1981,27 +2130,13 @@ config_from_file (struct vty *vty, FILE *fp) ret = cmd_execute_command_strict (vline, vty, NULL); /* Try again with setting node to CONFIG_NODE */ - if (ret != CMD_SUCCESS && ret != CMD_WARNING) + while (ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node != CONFIG_NODE) { - if (vty->node == KEYCHAIN_KEY_NODE) - { - vty->node = KEYCHAIN_NODE; - - ret = cmd_execute_command_strict (vline, vty, NULL); - - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - { - vty->node = CONFIG_NODE; - ret = cmd_execute_command_strict (vline, vty, NULL); - } - } - else - { - vty->node = CONFIG_NODE; - ret = cmd_execute_command_strict (vline, vty, NULL); - } + vty->node = node_parent(vty->node); + ret = cmd_execute_command_strict (vline, vty, NULL); } - + cmd_free_strvec (vline); if (ret != CMD_SUCCESS && ret != CMD_WARNING) -- cgit v1.2.3 From eda031f6f3558239da5ceb196312ff71aa74fef1 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Jan 2003 00:39:19 +0000 Subject: Finish off merge off CLI extensions, see below for description. Merge should be off: From havanna_moon@gmx.net Sat Jan 18 00:37:13 2003 Date: Mon, 9 Dec 2002 05:32:58 +0100 (CET) From: Yon Uriarte To: "the list(tm) Zebra" Subject: [zebra 16671] [PATCH] CLI extensions. Hi, this patch adds 2 improvements to the CLI (lib/command.c): #1) When in subconfig mode (router XXX, interface XXX, ...) commands that fail for that node are tried on the main CONFIG_NODE. This is great for configuring interfaces or changing the sub-config mode quickly, without the need to type 'exit' between commands: ospfd(config)# int eth1 ospfd(config-if)# ip ospf cost 9 ospfd(config-if)# ip ospf prio 101 ospfd(config-if)# router ospf ospfd(config-router)# network 1.1.1.0/24 area 51 ospfd(config-router)# int eth2 ospfd(config-if)# ip ospf authentication message-digest ospfd(config-if)# ^Z ospfd# Is this IOS-like or does IOS try to walk up the tree of config sub-modes instead of directly trying the command on CONFIG_NODE? CAVEATS: "?" and "TAB" don't work. IIRC IOS doesnt show that help neither. NON-CAVEATS: This wont break much, as config_from_file() already does try a failed command on the parent node of the actual vty->node. If changing the code to walk the node tree instead of directly trying the command on the ENABLE_NODE the same semantics would be in use and no future bugs could creep in. #2) When in config or subconfig mode use the "do " prefix to execute commans of the ENABLE_NODE. "?" and "TAB" work. The space after the "do" is needed: ospfd(config-router)# do % There is no matched command. ospfd(config-router)# do clear Reset functions configure Configuration from vty interface copy Copy configuration debug Debugging functions (see also 'undebug') disable Turn off privileged mode command end End current mode and change to enable mode. exit Exit current mode and down to previous mode help Description of the interactive help system list Print command list no Negate a command or set its defaults quit Exit current mode and down to previous mode show Show running system information terminal Set terminal line parameters who Display who is on vty write Write running configuration to memory, network, or terminal ospfd(config-router)# do sho ospfd(config-router)# do show me ospfd(config-router)# do show memory r ospfd(config-router)# do show memory rip RIP structure : 0 RIP route info : 0 RIP interface : 0 RIP peer : 0 RIP offset list : 0 RIP distance : 0 ospfd(config-router)# ^Z ospfd# CAVEATS: I don't have access to an IOS with this feature, so I implemented it from the comments on this mailing list (in fact my personal motivation was to implement feature #1, which I missed on zebra. But #2 sounded like a nice one to have, and xemacs was already parked on command.c ...). Is this IOS-like or are there differences? I will happily change this patch to mimick IOS or the mailing-list consensus on CLI-usability. regards, yon --- lib/command.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 8fd2b648..f0ddb6d7 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1582,6 +1582,40 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) } +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; + 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_max (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. */ int cmd_lcd (char **matched) @@ -1764,7 +1798,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) } char ** -cmd_complete_command (vector vline, struct vty *vty, int *status) +cmd_complete_command_real (vector vline, struct vty *vty, int *status) { char **ret; @@ -1939,6 +1973,59 @@ cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cm } +int +cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { + int ret; + enum node_type onode = vty->node; + + if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) + { + vector shifted_vline; + 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_max (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; + } + + + ret = cmd_execute_command_real (vline, vty, cmd); + + /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */ + if ( ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node > CONFIG_NODE ) + { + /* XXX try node_parent(vty->node)? */ + vty->node = CONFIG_NODE; + ret = cmd_execute_command_real (vline, vty, cmd); + if (ret != CMD_SUCCESS && ret != CMD_WARNING) + { + /* if the command changed the node dont reset it */ + if( vty->node == CONFIG_NODE ) + vty->node = onode; + return ret; + } + else + if( vty->node == CONFIG_NODE ) + vty->node = onode; + /* if the command changed the node dont reset it */ + } + return ret; +} + + int cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { int ret; -- cgit v1.2.3 From 9ab6812d1dd27813f3ae01624312edc21c1a0bb6 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Jan 2003 01:16:20 +0000 Subject: This patch adds Yon's CLI 'walk back up tree' patch. Following are email describing original patch and a shorter email describing changes to an updated patch, the one which is applied: From havanna_moon@gmx.net Sat Jan 18 00:37:13 2003 Date: Mon, 9 Dec 2002 05:32:58 +0100 (CET) From: Yon Uriarte To: "the list(tm) Zebra" Subject: [zebra 16671] [PATCH] CLI extensions. Hi, this patch adds 2 improvements to the CLI (lib/command.c): #1) When in subconfig mode (router XXX, interface XXX, ...) commands that fail for that node are tried on the main CONFIG_NODE. This is great for configuring interfaces or changing the sub-config mode quickly, without the need to type 'exit' between commands: ospfd(config)# int eth1 ospfd(config-if)# ip ospf cost 9 ospfd(config-if)# ip ospf prio 101 ospfd(config-if)# router ospf ospfd(config-router)# network 1.1.1.0/24 area 51 ospfd(config-router)# int eth2 ospfd(config-if)# ip ospf authentication message-digest ospfd(config-if)# ^Z ospfd# Is this IOS-like or does IOS try to walk up the tree of config sub-modes instead of directly trying the command on CONFIG_NODE? CAVEATS: "?" and "TAB" don't work. IIRC IOS doesnt show that help neither. NON-CAVEATS: This wont break much, as config_from_file() already does try a failed command on the parent node of the actual vty->node. If changing the code to walk the node tree instead of directly trying the command on the ENABLE_NODE the same semantics would be in use and no future bugs could creep in. #2) When in config or subconfig mode use the "do " prefix to execute commans of the ENABLE_NODE. "?" and "TAB" work. The space after the "do" is needed: ospfd(config-router)# do % There is no matched command. ospfd(config-router)# do clear Reset functions configure Configuration from vty interface copy Copy configuration debug Debugging functions (see also 'undebug') disable Turn off privileged mode command end End current mode and change to enable mode. exit Exit current mode and down to previous mode help Description of the interactive help system list Print command list no Negate a command or set its defaults quit Exit current mode and down to previous mode show Show running system information terminal Set terminal line parameters who Display who is on vty write Write running configuration to memory, network, or terminal ospfd(config-router)# do sho ospfd(config-router)# do show me ospfd(config-router)# do show memory r ospfd(config-router)# do show memory rip RIP structure : 0 RIP route info : 0 RIP interface : 0 RIP peer : 0 RIP offset list : 0 RIP distance : 0 ospfd(config-router)# ^Z ospfd# CAVEATS: I don't have access to an IOS with this feature, so I implemented it from the comments on this mailing list (in fact my personal motivation was to implement feature #1, which I missed on zebra. But #2 sounded like a nice one to have, and xemacs was already parked on command.c ...). Is this IOS-like or are there differences? I will happily change this patch to mimick IOS or the mailing-list consensus on CLI-usability. regards, yon From havanna_moon@gmx.net Sat Jan 18 01:13:11 2003 Date: Sat, 11 Jan 2003 23:36:51 +0100 (CET) From: Yon Uriarte To: zebra@zebra.org Subject: [zebra 17218] Re: [PATCH] CLI extensions. Hi, [redacted] > I prefer the IOS way for the node "up walking". This patch should walk the tree upwards: bgpd(config)# router bgp 1 bgpd(config-router)# address-family ipv4 multicast bgpd(config-router-af)# access-list 1 remark hola que tal bgpd(config)# I cant test all combinations, so I cant rule out some bugs. I'd love to get (long and explicit) bug reports. [redacted] --- lib/command.c | 153 ++++++++++++++++------------------------------------------ 1 file changed, 41 insertions(+), 112 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index f0ddb6d7..f57cf5ca 100644 --- a/lib/command.c +++ b/lib/command.c @@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */ #include "memory.h" #include "log.h" #include "version.h" +#include "thread.h" /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -1582,40 +1583,6 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) } -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; - 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_max (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. */ int cmd_lcd (char **matched) @@ -1798,7 +1765,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) } char ** -cmd_complete_command_real (vector vline, struct vty *vty, int *status) +cmd_complete_command (vector vline, struct vty *vty, int *status) { char **ret; @@ -1836,12 +1803,21 @@ enum node_type node_parent ( enum node_type node ) { enum node_type ret; - switch ( node ) { - case KEYCHAIN_KEY_NODE: - ret = KEYCHAIN_NODE; - break; - default: - ret = CONFIG_NODE; + assert (node > CONFIG_NODE); + + switch (node) + { + case BGP_VPNV4_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV6_NODE: + ret = BGP_NODE; + break; + case KEYCHAIN_KEY_NODE: + ret = KEYCHAIN_NODE; + break; + default: + ret = CONFIG_NODE; } return ret; @@ -1975,61 +1951,10 @@ cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cm int cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { - int ret; - enum node_type onode = vty->node; - - if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) - { - vector shifted_vline; - 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_max (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; - } - - - ret = cmd_execute_command_real (vline, vty, cmd); - - /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */ - if ( ret != CMD_SUCCESS && ret != CMD_WARNING - && vty->node > CONFIG_NODE ) - { - /* XXX try node_parent(vty->node)? */ - vty->node = CONFIG_NODE; - ret = cmd_execute_command_real (vline, vty, cmd); - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - { - /* if the command changed the node dont reset it */ - if( vty->node == CONFIG_NODE ) - vty->node = onode; - return ret; - } - else - if( vty->node == CONFIG_NODE ) - vty->node = onode; - /* if the command changed the node dont reset it */ - } - return ret; -} - + int ret, saved_ret, tried = 0; + enum node_type onode, try_node; -int -cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { - int ret; - enum node_type onode = vty->node; + onode = try_node = vty->node; if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) { @@ -2054,28 +1979,27 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { } - ret = cmd_execute_command_real (vline, vty, cmd); + saved_ret = ret = cmd_execute_command_real (vline, vty, cmd); /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */ - if ( ret != CMD_SUCCESS && ret != CMD_WARNING + while ( ret != CMD_SUCCESS && ret != CMD_WARNING && vty->node > CONFIG_NODE ) { - /* XXX try node_parent(vty->node)? */ - vty->node = CONFIG_NODE; + try_node = node_parent(try_node); + vty->node = try_node; ret = cmd_execute_command_real (vline, vty, cmd); - if (ret != CMD_SUCCESS && ret != CMD_WARNING) + tried = 1; + if (ret == CMD_SUCCESS || ret == CMD_WARNING) { - /* if the command changed the node dont reset it */ - if( vty->node == CONFIG_NODE ) - vty->node = onode; + /* succesfull command, leave the node as is */ return ret; } - else - if( vty->node == CONFIG_NODE ) - vty->node = onode; - /* if the command changed the node dont reset it */ } - return ret; + /* no command succeeded, reset the vty to the original node and + return the error for this node */ + if ( tried ) + vty->node = onode; + return saved_ret; } /* Execute command by argument readline. */ @@ -2219,11 +2143,11 @@ config_from_file (struct vty *vty, FILE *fp) /* Try again with setting node to CONFIG_NODE */ while (ret != CMD_SUCCESS && ret != CMD_WARNING && vty->node != CONFIG_NODE) - { + { vty->node = node_parent(vty->node); - ret = cmd_execute_command_strict (vline, vty, NULL); - } - + ret = cmd_execute_command_strict (vline, vty, NULL); + } + cmd_free_strvec (vline); if (ret != CMD_SUCCESS && ret != CMD_WARNING) @@ -3199,5 +3123,10 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &no_service_terminal_length_cmd); } + if (terminal) + { + install_element(VIEW_NODE, &show_thread_cpu_cmd); + install_element(ENABLE_NODE, &show_thread_cpu_cmd); + } srand(time(NULL)); } -- cgit v1.2.3 From 726f9b2bbdd5a607f7b0a10a64547739b807e361 Mon Sep 17 00:00:00 2001 From: hasso Date: Sun, 25 May 2003 21:04:54 +0000 Subject: Last fixes from 6Wind patch. --- lib/command.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index f57cf5ca..5d429338 100644 --- a/lib/command.c +++ b/lib/command.c @@ -718,6 +718,8 @@ cmd_ipv6_match (char *str) int state = STATE_START; int colons = 0, nums = 0, double_colon = 0; char *sp = NULL; + struct sockaddr_in6 sin6_dummy; + int ret; if (str == NULL) return partly_match; @@ -725,6 +727,15 @@ cmd_ipv6_match (char *str) 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) -- cgit v1.2.3 From b21b19c5785487f2ff4a6ce38f45c2e6c35f4363 Mon Sep 17 00:00:00 2001 From: paul Date: Sun, 15 Jun 2003 01:28:29 +0000 Subject: 2003-06-15 Paul Jakma * lib/vty.{c,h}: Remove vty layer depending on a 'master' global, pass the thread master in explicitly to vty_init. Sort out some header dependency problems with lib/command.h * zebra/: Move globals to struct zebrad. Update vty_init(). * (.*)/\1_main.c: update call to vty_init(). --- lib/command.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 5d429338..ade413bb 100644 --- a/lib/command.c +++ b/lib/command.c @@ -20,11 +20,14 @@ Boston, MA 02111-1307, USA. */ #include -#include "command.h" + #include "memory.h" #include "log.h" #include "version.h" #include "thread.h" +#include "vector.h" +#include "vty.h" +#include "command.h" /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ -- cgit v1.2.3 From 22e0a9e6c7bd7775da6bfb00d9a4114643cf9369 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 11 Jul 2003 17:55:46 +0000 Subject: 2003-07-11 Vsevolod Sipakov * lib/command.c: Add missing HAVE_IPV6 defines. see bug id #23: http://bugzilla.dishone.st/show_bug.cgi?id=23 --- lib/command.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index ade413bb..c6203be4 100644 --- a/lib/command.c +++ b/lib/command.c @@ -715,6 +715,8 @@ cmd_ipv4_prefix_match (char *str) #define STATE_SLASH 6 #define STATE_MASK 7 +#ifdef HAVE_IPV6 + enum match_type cmd_ipv6_match (char *str) { @@ -952,6 +954,8 @@ cmd_ipv6_prefix_match (char *str) return exact_match; } +#endif /* HAVE_IPV6 */ + #define DECIMAL_STRLEN_MAX 10 int @@ -1046,6 +1050,7 @@ cmd_filter_by_completion (char *command, vector v, int index) matched++; } } +#ifdef HAVE_IPV6 else if (CMD_IPV6 (str)) { if (cmd_ipv6_match (command)) @@ -1066,6 +1071,7 @@ cmd_filter_by_completion (char *command, vector v, int index) matched++; } } +#endif /* HAVE_IPV6 */ else if (CMD_IPV4 (str)) { if (cmd_ipv4_match (command)) @@ -1160,6 +1166,7 @@ cmd_filter_by_string (char *command, vector v, int index) matched++; } } +#ifdef HAVE_IPV6 else if (CMD_IPV6 (str)) { if (cmd_ipv6_match (command) == exact_match) @@ -1178,6 +1185,7 @@ cmd_filter_by_string (char *command, vector v, int index) matched++; } } +#endif /* HAVE_IPV6 */ else if (CMD_IPV4 (str)) { if (cmd_ipv4_match (command) == exact_match) @@ -1272,6 +1280,7 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) match++; } break; +#ifdef HAVE_IPV6 case ipv6_match: if (CMD_IPV6 (str)) match++; @@ -1285,6 +1294,7 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) match++; } break; +#endif /* HAVE_IPV6 */ case ipv4_match: if (CMD_IPV4 (str)) match++; @@ -1350,6 +1360,7 @@ cmd_entry_function_desc (char *src, char *dst) return NULL; } +#ifdef HAVE_IPV6 if (CMD_IPV6 (dst)) { if (cmd_ipv6_match (src)) @@ -1365,6 +1376,7 @@ cmd_entry_function_desc (char *src, char *dst) else return NULL; } +#endif /* HAVE_IPV6 */ if (CMD_IPV4 (dst)) { -- cgit v1.2.3 From 12ab19f1863e80134353244967a87805b12fe722 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 26 Jul 2003 06:14:55 +0000 Subject: 2003-07-26 Paul Jakma * lib/command.c: Add config_log_syslog_facility_cmd, to set syslog facility. This was a commit to zebra.org on May 20, merge in to zebra-pj. --- lib/command.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 173 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index c6203be4..f207fc66 100644 --- a/lib/command.c +++ b/lib/command.c @@ -448,6 +448,71 @@ char *zencrypt (char *passwd) return crypt (passwd, salt); } +char * +syslog_facility_print (int facility) +{ + switch (facility) + { + case LOG_KERN: + return "kern"; + break; + case LOG_USER: + return "user"; + break; + case LOG_MAIL: + return "mail"; + break; + case LOG_DAEMON: + return "daemon"; + break; + case LOG_AUTH: + return "auth"; + break; + case LOG_SYSLOG: + return "syslog"; + break; + case LOG_LPR: + return "lpr"; + break; + case LOG_NEWS: + return "news"; + break; + case LOG_UUCP: + return "uucp"; + break; + case LOG_CRON: + return "cron"; + break; + case LOG_LOCAL0: + return "local0"; + break; + case LOG_LOCAL1: + return "local1"; + break; + case LOG_LOCAL2: + return "local2"; + break; + case LOG_LOCAL3: + return "local3"; + break; + case LOG_LOCAL4: + return "local4"; + break; + case LOG_LOCAL5: + return "local5"; + break; + case LOG_LOCAL6: + return "local6"; + break; + case LOG_LOCAL7: + return "local7"; + break; + default: + break; + } + return ""; +} + /* This function write configuration of this host. */ int config_write_host (struct vty *vty) @@ -477,8 +542,12 @@ config_write_host (struct vty *vty) vty_out (vty, "log stdout%s", VTY_NEWLINE); if (host.log_syslog) - vty_out (vty, "log syslog%s", VTY_NEWLINE); - + { + vty_out (vty, "log syslog"); + if (zlog_default->facility != LOG_DAEMON) + vty_out (vty, " facility %s", syslog_facility_print (zlog_default->facility)); + vty_out (vty, "%s", VTY_NEWLINE); + } if (zlog_default->maskpri != LOG_DEBUG) vty_out (vty, "log trap %s%s", zlog_priority[zlog_default->maskpri], VTY_NEWLINE); @@ -2959,6 +3028,79 @@ DEFUN (config_log_syslog, { zlog_set_flag (NULL, ZLOG_SYSLOG); host.log_syslog = 1; + zlog_default->facility = LOG_DAEMON; + return CMD_SUCCESS; +} + +DEFUN (config_log_syslog_facility, + config_log_syslog_facility_cmd, + "log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", + "Logging control\n" + "Logging goes to syslog\n" + "Facility parameter for syslog messages\n" + "Kernel\n" + "User process\n" + "Mail system\n" + "System daemons\n" + "Authorization system\n" + "Syslog itself\n" + "Line printer system\n" + "USENET news\n" + "Unix-to-Unix copy system\n" + "Cron/at facility\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n") +{ + int facility = LOG_DAEMON; + + zlog_set_flag (NULL, ZLOG_SYSLOG); + host.log_syslog = 1; + + if (strncmp (argv[0], "kern", 1) == 0) + facility = LOG_KERN; + else if (strncmp (argv[0], "user", 2) == 0) + facility = LOG_USER; + else if (strncmp (argv[0], "mail", 1) == 0) + facility = LOG_MAIL; + else if (strncmp (argv[0], "daemon", 1) == 0) + facility = LOG_DAEMON; + else if (strncmp (argv[0], "auth", 1) == 0) + facility = LOG_AUTH; + else if (strncmp (argv[0], "syslog", 1) == 0) + facility = LOG_SYSLOG; + else if (strncmp (argv[0], "lpr", 2) == 0) + facility = LOG_LPR; + else if (strncmp (argv[0], "news", 1) == 0) + facility = LOG_NEWS; + else if (strncmp (argv[0], "uucp", 2) == 0) + facility = LOG_UUCP; + else if (strncmp (argv[0], "cron", 1) == 0) + facility = LOG_CRON; + else if (strncmp (argv[0], "local0", 6) == 0) + facility = LOG_LOCAL0; + else if (strncmp (argv[0], "local1", 6) == 0) + facility = LOG_LOCAL1; + else if (strncmp (argv[0], "local2", 6) == 0) + facility = LOG_LOCAL2; + else if (strncmp (argv[0], "local3", 6) == 0) + facility = LOG_LOCAL3; + else if (strncmp (argv[0], "local4", 6) == 0) + facility = LOG_LOCAL4; + else if (strncmp (argv[0], "local5", 6) == 0) + facility = LOG_LOCAL5; + else if (strncmp (argv[0], "local6", 6) == 0) + facility = LOG_LOCAL6; + else if (strncmp (argv[0], "local7", 6) == 0) + facility = LOG_LOCAL7; + + zlog_default->facility = facility; + return CMD_SUCCESS; } @@ -2971,9 +3113,36 @@ DEFUN (no_config_log_syslog, { zlog_reset_flag (NULL, ZLOG_SYSLOG); host.log_syslog = 0; + zlog_default->facility = LOG_DAEMON; return CMD_SUCCESS; } +ALIAS (no_config_log_syslog, + no_config_log_syslog_facility_cmd, + "no log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", + NO_STR + "Logging control\n" + "Logging goes to syslog\n" + "Facility parameter for syslog messages\n" + "Kernel\n" + "User process\n" + "Mail system\n" + "System daemons\n" + "Authorization system\n" + "Syslog itself\n" + "Line printer system\n" + "USENET news\n" + "Unix-to-Unix copy system\n" + "Cron/at facility\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n" + "Local use\n") + DEFUN (config_log_trap, config_log_trap_cmd, "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)", @@ -3136,7 +3305,9 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &config_log_file_cmd); install_element (CONFIG_NODE, &no_config_log_file_cmd); install_element (CONFIG_NODE, &config_log_syslog_cmd); + install_element (CONFIG_NODE, &config_log_syslog_facility_cmd); install_element (CONFIG_NODE, &no_config_log_syslog_cmd); + install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd); install_element (CONFIG_NODE, &config_log_trap_cmd); install_element (CONFIG_NODE, &no_config_log_trap_cmd); install_element (CONFIG_NODE, &config_log_record_priority_cmd); -- cgit v1.2.3 From e8f2984c00d406781eff42db7afcdae5d5a6a366 Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 12 Aug 2003 13:08:31 +0000 Subject: 2003-08-12 Paul Jakma 2003-08-12 Paul Jakma * Makefile.am: redhat/zebra.* -> redhat/quagga.* * configure.ac: Bump autoconf prerequisite to 2.53. dist name zebra -> quagga. general Zebra -> Quagga where appropriate (ie not zebra daemon). User and group zebra->quagga. s/ZEBRA\(_VERSION\)/QUAGGA\1/. * bgpd/bgp_main.c: s/ZEBRA\(_VERSION\)/QUAGGA\1/ * lib/command.c: Update banners and s/ZEBRA\(_VERSION\)/QUAGGA\1/ * lib/print_version.c: ditto * lib/version.h: s/ZEBRA\(_VERSION\)/QUAGGA\1/ and bump version. Change ZEBRA_URL. * lib/smux.c: s/ZEBRA\(_VERSION\)/QUAGGA\1/ * lib/vty.h: Change Zebra.conf to Quagga.conf (integrated file) * ospf6d/ospf6{,_main}.c: s/ZEBRA\(_VERSION\)/QUAGGA\1/ * ospfd/ospf_main.c: s/ZEBRA\(_VERSION\)/QUAGGA\1/ --- lib/command.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index f207fc66..71db3aa1 100644 --- a/lib/command.c +++ b/lib/command.c @@ -39,7 +39,7 @@ struct host host; /* Default motd string. */ char *default_motd = "\r\n\ -Hello, this is zebra (version " ZEBRA_VERSION ").\r\n\ +Hello, this is quagga (version " QUAGGA_VERSION ").\r\n\ Copyright 1996-2002 Kunihiro Ishiguro.\r\n\ \r\n"; @@ -2393,7 +2393,7 @@ DEFUN (show_version, SHOW_STR "Displays zebra version\n") { - vty_out (vty, "Zebra %s (%s).%s", ZEBRA_VERSION, + vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host_name, VTY_NEWLINE); vty_out (vty, "Copyright 1996-2002, Kunihiro Ishiguro.%s", VTY_NEWLINE); -- cgit v1.2.3 From 42053f4e3a0bb8d4e2df7c9d626629cc14dfc285 Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 13 Aug 2003 02:54:44 +0000 Subject: 2003-08-13 Paul Jakma * lib/version.h: Add QUAGGA_PROGNAME * lib/smux.c: hardcoded zebra/quagga -> QUAGGA_PROGNAME * lib/command.c: ditto * vtysh/vtysh_user.c: ditto --- lib/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 71db3aa1..e8c9203f 100644 --- a/lib/command.c +++ b/lib/command.c @@ -39,7 +39,7 @@ struct host host; /* Default motd string. */ char *default_motd = "\r\n\ -Hello, this is quagga (version " QUAGGA_VERSION ").\r\n\ +Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ Copyright 1996-2002 Kunihiro Ishiguro.\r\n\ \r\n"; -- cgit v1.2.3 From 54aba54c10d7cc98023a49e3a8a3509cbd358867 Mon Sep 17 00:00:00 2001 From: paul Date: Thu, 21 Aug 2003 20:28:24 +0000 Subject: 2003-08-20 Yasuhiro Ohara * command.c: Fix display problem for command line description. --- lib/command.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index e8c9203f..8c60fc4f 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1529,6 +1529,9 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) vector matchvec; struct cmd_element *cmd_element; int index; + int ret; + enum match_type match; + char *command; static struct desc desc_cr = { "", "" }; /* Set index. */ @@ -1541,14 +1544,10 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) 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++) { - enum match_type match; - char *command; - int ret; - command = vector_slot (vline, i); - match = cmd_filter_by_completion (command, cmd_vector, i); if (match == vararg_match) @@ -1570,7 +1569,6 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) } vector_set (matchvec, &desc_cr); - vector_free (cmd_vector); return matchvec; @@ -1593,6 +1591,11 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) /* 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_max (cmd_vector); i++) if ((cmd_element = vector_slot (cmd_vector, i)) != NULL) @@ -1600,12 +1603,13 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) char *string = NULL; vector strvec = cmd_element->strvec; - if (index > vector_max (strvec)) + /* if command is NULL, index may be equal to vector_max */ + if (command && index >= vector_max (strvec)) vector_slot (cmd_vector, i) = NULL; else { - /* Check is command is completed. */ - if (index == vector_max (strvec)) + /* Check if command is completed. */ + if (command == NULL && index == vector_max (strvec)) { string = ""; if (! desc_unique_string (matchvec, string)) @@ -1620,7 +1624,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) for (j = 0; j < vector_max (descvec); j++) { desc = vector_slot (descvec, j); - string = cmd_entry_function_desc (vector_slot (vline, index), desc->cmd); + string = cmd_entry_function_desc (command, desc->cmd); if (string) { /* Uniqueness check */ -- cgit v1.2.3 From aa593d5e2638566ead1e69381e60639550991ff2 Mon Sep 17 00:00:00 2001 From: gdt Date: Mon, 22 Dec 2003 20:15:53 +0000 Subject: 2003-12-22 Christian Hammers * configure.ac (and everywhere a regular file is opened for writing): use file permissions from configure rather than compiled-in umask. --- lib/command.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 8c60fc4f..43a0bb3f 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2552,6 +2552,14 @@ DEFUN (config_write_file, free (config_file_sav); free (config_file_tmp); + + if (chmod (config_file, 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; -- cgit v1.2.3 From 9e867fe663c4eb43c36f35067c0dd092e8c83c14 Mon Sep 17 00:00:00 2001 From: jardin Date: Tue, 23 Dec 2003 08:56:18 +0000 Subject: Merge isisd into the Quagga's framework: - add privs support - use misc quagga's definitions - make it compile"able" - fix segfault cases related to hostname() - add debug isis xxx command This patch has been approved by Paul Jakma. --- lib/command.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 43a0bb3f..24113062 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2325,6 +2325,7 @@ DEFUN (config_exit, case RIPNG_NODE: case OSPF_NODE: case OSPF6_NODE: + case ISIS_NODE: case KEYCHAIN_NODE: case MASC_NODE: case RMAP_NODE: @@ -2377,6 +2378,7 @@ DEFUN (config_end, case RMAP_NODE: case OSPF_NODE: case OSPF6_NODE: + case ISIS_NODE: case KEYCHAIN_NODE: case KEYCHAIN_KEY_NODE: case MASC_NODE: -- cgit v1.2.3 From 5e4fa1646cafe9e6f8dd78501bea0d2fe1eafdb4 Mon Sep 17 00:00:00 2001 From: gdt Date: Tue, 16 Mar 2004 14:38:36 +0000 Subject: 2004-03-16 David Young * (many) reference rather than "version.h", because version.h is a generated file and not present in the source tree when using objdir builds. (committed by gdt) works fine with normal builds; didn't try objdir --- lib/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 24113062..8b6ae3d0 100644 --- a/lib/command.c +++ b/lib/command.c @@ -23,7 +23,7 @@ Boston, MA 02111-1307, USA. */ #include "memory.h" #include "log.h" -#include "version.h" +#include #include "thread.h" #include "vector.h" #include "vty.h" -- cgit v1.2.3 From 34553cc3c996bb530652663810664935f40f5560 Mon Sep 17 00:00:00 2001 From: hasso Date: Fri, 27 Aug 2004 13:56:39 +0000 Subject: Make "terminal length <0-512>" command work in vtysh. --- lib/command.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 8b6ae3d0..088ad38c 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3300,8 +3300,11 @@ cmd_init (int terminal) } install_element (ENABLE_NODE, &show_startup_config_cmd); install_element (ENABLE_NODE, &show_version_cmd); - install_element (ENABLE_NODE, &config_terminal_length_cmd); - install_element (ENABLE_NODE, &config_terminal_no_length_cmd); + if (terminal) + { + install_element (ENABLE_NODE, &config_terminal_length_cmd); + install_element (ENABLE_NODE, &config_terminal_no_length_cmd); + } if (terminal) install_default (CONFIG_NODE); -- cgit v1.2.3 From 33394766a502eff6315bd8d9b1c43a773b2ec35b Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 13 Sep 2004 11:27:57 +0000 Subject: 2004-09-13 Paul Jakma * configure.ac: capitalise the package name. autoconf lowercases it for PACKAGE_TARNAME. * lib/command.c: Update the copyright string in the default motd. --- lib/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 088ad38c..2ed62526 100644 --- a/lib/command.c +++ b/lib/command.c @@ -40,7 +40,7 @@ struct host host; char *default_motd = "\r\n\ Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ -Copyright 1996-2002 Kunihiro Ishiguro.\r\n\ +Copyright 1996-2004 Kunihiro Ishiguro, et al.\r\n\ \r\n"; /* Standard command node structures. */ -- cgit v1.2.3 From e7168df4eff0d377621c45deb32cfcfa72e0dd83 Mon Sep 17 00:00:00 2001 From: hasso Date: Sun, 3 Oct 2004 20:11:32 +0000 Subject: Big vtysh cleanup. See changelogs for details. --- lib/command.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 2ed62526..a4cf9ebf 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3300,23 +3300,22 @@ cmd_init (int terminal) } 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); - } - if (terminal) - install_default (CONFIG_NODE); - install_element (CONFIG_NODE, &hostname_cmd); - install_element (CONFIG_NODE, &no_hostname_cmd); - 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); if (terminal) { + install_element (ENABLE_NODE, &config_terminal_length_cmd); + install_element (ENABLE_NODE, &config_terminal_no_length_cmd); + + install_default (CONFIG_NODE); + + install_element (CONFIG_NODE, &hostname_cmd); + install_element (CONFIG_NODE, &no_hostname_cmd); + 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); + install_element (CONFIG_NODE, &config_log_stdout_cmd); install_element (CONFIG_NODE, &no_config_log_stdout_cmd); install_element (CONFIG_NODE, &config_log_file_cmd); @@ -3335,10 +3334,7 @@ cmd_init (int terminal) 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); - } - if (terminal) - { install_element(VIEW_NODE, &show_thread_cpu_cmd); install_element(ENABLE_NODE, &show_thread_cpu_cmd); } -- cgit v1.2.3 From 8c328f1106cf0498333c2d8a96940e7b4581e316 Mon Sep 17 00:00:00 2001 From: hasso Date: Tue, 5 Oct 2004 21:01:23 +0000 Subject: Number of warnings is down to 3 again in lib directory. A lot of const's added to strings and a lot of int -> unsigned int changes. --- lib/command.c | 131 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 63 insertions(+), 68 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index a4cf9ebf..c65e6fa8 100644 --- a/lib/command.c +++ b/lib/command.c @@ -37,7 +37,7 @@ vector cmdvec; struct host host; /* Default motd string. */ -char *default_motd = +const char *default_motd = "\r\n\ Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ Copyright 1996-2004 Kunihiro Ishiguro, et al.\r\n\ @@ -142,7 +142,7 @@ cmp_desc (const void *p, const void *q) void sort_node () { - int i, j; + unsigned int i, j; struct cmd_node *cnode; vector descvec; struct cmd_element *cmd_element; @@ -218,7 +218,7 @@ cmd_make_strvec (char *string) void cmd_free_strvec (vector v) { - int i; + unsigned int i; char *cp; if (!v) @@ -268,14 +268,14 @@ cmd_desc_str (char **string) /* New string vector. */ vector -cmd_make_descvec (char *string, char *descstr) +cmd_make_descvec (const char *string, const char *descstr) { int multiple = 0; - char *sp; + const char *sp; char *token; int len; - char *cp; - char *dp; + const char *cp; + const char *dp; vector allvec; vector strvec = NULL; struct desc *desc; @@ -363,8 +363,7 @@ cmd_make_descvec (char *string, char *descstr) int cmd_cmdsize (vector strvec) { - int i; - char *str; + unsigned int i; int size = 0; vector descvec; @@ -376,9 +375,7 @@ cmd_cmdsize (vector strvec) { struct desc *desc = vector_slot (descvec, 0); - str = desc->cmd; - - if (str == NULL || CMD_OPTION (str)) + if (desc->cmd == NULL || CMD_OPTION (desc->cmd)) return size; else size++; @@ -390,7 +387,7 @@ cmd_cmdsize (vector strvec) } /* Return prompt character of specified node. */ -char * +const char * cmd_prompt (enum node_type node) { struct cmd_node *cnode; @@ -448,7 +445,7 @@ char *zencrypt (char *passwd) return crypt (passwd, salt); } -char * +const char * syslog_facility_print (int facility) { switch (facility) @@ -639,9 +636,9 @@ enum match_type }; enum match_type -cmd_ipv4_match (char *str) +cmd_ipv4_match (const char *str) { - char *sp; + const char *sp; int dots = 0, nums = 0; char buf[4]; @@ -696,9 +693,9 @@ cmd_ipv4_match (char *str) } enum match_type -cmd_ipv4_prefix_match (char *str) +cmd_ipv4_prefix_match (const char *str) { - char *sp; + const char *sp; int dots = 0; char buf[4]; @@ -787,11 +784,11 @@ cmd_ipv4_prefix_match (char *str) #ifdef HAVE_IPV6 enum match_type -cmd_ipv6_match (char *str) +cmd_ipv6_match (const char *str) { int state = STATE_START; int colons = 0, nums = 0, double_colon = 0; - char *sp = NULL; + const char *sp = NULL; struct sockaddr_in6 sin6_dummy; int ret; @@ -893,12 +890,12 @@ cmd_ipv6_match (char *str) } enum match_type -cmd_ipv6_prefix_match (char *str) +cmd_ipv6_prefix_match (const char *str) { int state = STATE_START; int colons = 0, nums = 0, double_colon = 0; int mask; - char *sp = NULL; + const char *sp = NULL; char *endptr = NULL; if (str == NULL) @@ -1028,7 +1025,7 @@ cmd_ipv6_prefix_match (char *str) #define DECIMAL_STRLEN_MAX 10 int -cmd_range_match (char *range, char *str) +cmd_range_match (const char *range, const char *str) { char *p; char buf[DECIMAL_STRLEN_MAX + 1]; @@ -1074,10 +1071,10 @@ cmd_range_match (char *range, char *str) /* Make completion match and return match type flag. */ enum match_type -cmd_filter_by_completion (char *command, vector v, int index) +cmd_filter_by_completion (char *command, vector v, unsigned int index) { - int i; - char *str; + unsigned int i; + const char *str; struct cmd_element *cmd_element; enum match_type match_type; vector descvec; @@ -1093,7 +1090,7 @@ cmd_filter_by_completion (char *command, vector v, int index) vector_slot (v, i) = NULL; else { - int j; + unsigned int j; int matched = 0; descvec = vector_slot (cmd_element->strvec, index); @@ -1189,10 +1186,10 @@ cmd_filter_by_completion (char *command, vector v, int index) /* Filter vector by command character with index. */ enum match_type -cmd_filter_by_string (char *command, vector v, int index) +cmd_filter_by_string (char *command, vector v, unsigned int index) { - int i; - char *str; + unsigned int i; + const char *str; struct cmd_element *cmd_element; enum match_type match_type; vector descvec; @@ -1210,7 +1207,7 @@ cmd_filter_by_string (char *command, vector v, int index) vector_slot (v, i) = NULL; else { - int j; + unsigned int j; int matched = 0; descvec = vector_slot (cmd_element->strvec, index); @@ -1299,11 +1296,11 @@ cmd_filter_by_string (char *command, vector v, int index) int is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) { - int i; - int j; - char *str = NULL; + unsigned int i; + unsigned int j; + const char *str = NULL; struct cmd_element *cmd_element; - char *matched = NULL; + const char *matched = NULL; vector descvec; struct desc *desc; @@ -1393,8 +1390,8 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) } /* If src matches dst return dst string, otherwise return NULL */ -char * -cmd_entry_function (char *src, char *dst) +const char * +cmd_entry_function (const char *src, const char *dst) { /* Skip variable arguments. */ if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) || @@ -1415,8 +1412,8 @@ cmd_entry_function (char *src, char *dst) /* 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 */ -char * -cmd_entry_function_desc (char *src, char *dst) +const char * +cmd_entry_function_desc (const char *src, const char *dst) { if (CMD_VARARG (dst)) return dst; @@ -1480,9 +1477,9 @@ cmd_entry_function_desc (char *src, char *dst) /* Check same string element existence. If it isn't there return 1. */ int -cmd_unique_string (vector v, char *str) +cmd_unique_string (vector v, const char *str) { - int i; + unsigned int i; char *match; for (i = 0; i < vector_max (v); i++) @@ -1495,9 +1492,9 @@ cmd_unique_string (vector v, char *str) /* Compare string to description vector. If there is same string return 1 else return 0. */ int -desc_unique_string (vector v, char *str) +desc_unique_string (vector v, const char *str) { - int i; + unsigned int i; struct desc *desc; for (i = 0; i < vector_max (v); i++) @@ -1523,12 +1520,12 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) { vector cmd_describe_command_real (vector vline, struct vty *vty, int *status) { - int i; + unsigned int i; vector cmd_vector; #define INIT_MATCHVEC_SIZE 10 vector matchvec; struct cmd_element *cmd_element; - int index; + unsigned int index; int ret; enum match_type match; char *command; @@ -1554,7 +1551,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) { struct cmd_element *cmd_element; vector descvec; - int j, k; + unsigned int j, k; for (j = 0; j < vector_max (cmd_vector); j++) if ((cmd_element = vector_slot (cmd_vector, j)) != NULL) @@ -1600,7 +1597,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) for (i = 0; i < vector_max (cmd_vector); i++) if ((cmd_element = vector_slot (cmd_vector, i)) != NULL) { - char *string = NULL; + const char *string = NULL; vector strvec = cmd_element->strvec; /* if command is NULL, index may be equal to vector_max */ @@ -1617,7 +1614,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) } else { - int j; + unsigned int j; vector descvec = vector_slot (strvec, index); struct desc *desc; @@ -1657,7 +1654,7 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) { enum node_type onode; vector shifted_vline; - int index; + unsigned int index; onode = vty->node; vty->node = ENABLE_NODE; @@ -1719,12 +1716,12 @@ cmd_lcd (char **matched) char ** cmd_complete_command_real (vector vline, struct vty *vty, int *status) { - int i; + 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; - int index = vector_max (vline) - 1; + unsigned int index = vector_max (vline) - 1; char **match_str; struct desc *desc; vector descvec; @@ -1767,7 +1764,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) for (i = 0; i < vector_max (cmd_vector); i++) if ((cmd_element = vector_slot (cmd_vector, i)) != NULL) { - char *string; + const char *string; vector strvec = cmd_element->strvec; /* Check field length */ @@ -1775,7 +1772,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) vector_slot (cmd_vector, i) = NULL; else { - int j; + unsigned int j; descvec = vector_slot (strvec, index); for (j = 0; j < vector_max (descvec); j++) @@ -1872,7 +1869,7 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) { enum node_type onode; vector shifted_vline; - int index; + unsigned int index; onode = vty->node; vty->node = ENABLE_NODE; @@ -1926,8 +1923,8 @@ enum node_type node_parent ( enum node_type node ) int cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd) { - int i; - int index; + unsigned int i; + unsigned int index; vector cmd_vector; struct cmd_element *cmd_element; struct cmd_element *matched_element; @@ -2020,12 +2017,11 @@ cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cm if (vector_max (descvec) == 1) { struct desc *desc = vector_slot (descvec, 0); - char *str = desc->cmd; - if (CMD_VARARG (str)) + if (CMD_VARARG (desc->cmd)) varflag = 1; - if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str)) + if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd)) argv[argc++] = vector_slot (vline, i); } else @@ -2058,7 +2054,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) { vector shifted_vline; - int index; + unsigned int index; vty->node = ENABLE_NODE; /* We can try it on enable node, cos' the vty is authenticated */ @@ -2106,8 +2102,8 @@ int cmd_execute_command_strict (vector vline, struct vty *vty, struct cmd_element **cmd) { - int i; - int index; + unsigned int i; + unsigned int index; vector cmd_vector; struct cmd_element *cmd_element; struct cmd_element *matched_element; @@ -2195,12 +2191,11 @@ cmd_execute_command_strict (vector vline, struct vty *vty, if (vector_max (descvec) == 1) { struct desc *desc = vector_slot (descvec, 0); - char *str = desc->cmd; - if (CMD_VARARG (str)) + if (CMD_VARARG (desc->cmd)) varflag = 1; - if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str)) + if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd)) argv[argc++] = vector_slot (vline, i); } else @@ -2437,7 +2432,7 @@ DEFUN (config_list, "list", "Print command list\n") { - int i; + unsigned int i; struct cmd_node *cnode = vector_slot (cmdvec, vty->node); struct cmd_element *cmd; @@ -2455,7 +2450,7 @@ DEFUN (config_write_file, "Write running configuration to memory, network, or terminal\n" "Write to configuration file\n") { - int i; + unsigned int i; int fd; struct cmd_node *node; char *config_file; @@ -2592,7 +2587,7 @@ DEFUN (config_write_terminal, "Write running configuration to memory, network, or terminal\n" "Write to terminal\n") { - int i; + unsigned int i; struct cmd_node *node; if (vty->type == VTY_SHELL_SERV) -- cgit v1.2.3 From 6ad96ea16ee54578391bb4ca88d047ac9d3654fc Mon Sep 17 00:00:00 2001 From: hasso Date: Thu, 7 Oct 2004 19:33:46 +0000 Subject: Make more strings const. --- lib/command.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index c65e6fa8..330470e5 100644 --- a/lib/command.c +++ b/lib/command.c @@ -233,9 +233,10 @@ cmd_free_strvec (vector v) /* Fetch next description. Used in cmd_make_descvec(). */ char * -cmd_desc_str (char **string) +cmd_desc_str (const char **string) { - char *cp, *start, *token; + const char *cp, *start; + char *token; int strlen; cp = *string; -- cgit v1.2.3 From ea8e9d972e8775f3e1c4e03fbacb18a42e8c4177 Mon Sep 17 00:00:00 2001 From: hasso Date: Thu, 7 Oct 2004 21:32:14 +0000 Subject: Even more const strings and fix to bugfix. --- lib/command.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 330470e5..2766a357 100644 --- a/lib/command.c +++ b/lib/command.c @@ -167,9 +167,10 @@ sort_node () character is separated by a space character. Return value is a vector which includes char ** data element. */ vector -cmd_make_strvec (char *string) +cmd_make_strvec (const char *string) { - char *cp, *start, *token; + const char *cp, *start; + char *token; int strlen; vector strvec; @@ -3303,9 +3304,13 @@ cmd_init (int terminal) install_element (ENABLE_NODE, &config_terminal_no_length_cmd); install_default (CONFIG_NODE); + } + + install_element (CONFIG_NODE, &hostname_cmd); + install_element (CONFIG_NODE, &no_hostname_cmd); - 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); -- cgit v1.2.3 From 9035efaa924c69f4f4fcb1049c7dc4f43b9da980 Mon Sep 17 00:00:00 2001 From: paul Date: Sun, 10 Oct 2004 11:56:56 +0000 Subject: 2004-10-10 Paul Jakma * version.h.in: (pid_output*) add const qualifier. * command.h: Change DEFUN func to take const char *[] rather than char **, to begin process of fixing compile warnings in lib/. Nearly all other changes in this commit follow from this change. * buffer.{c,h}: (buffer_write) pointer-arithmetic is gccism, take const void * and cast an automatic const char *p to it. (buffer_putstr) add const * command.c: (zencrypt) const qualifier (cmd_execute_command_real) ditto (cmd_execute_command_strict) ditto (config_log_file) ditto. Fix leak of getcwd() returned string. * memory.{c,h}: Add MTYPE_DISTRIBUTE_IFNAME for struct dist ifname. * distribute.{c,h}: Update with const qualifier. (distribute_free) use MTYPE_DISTRIBUTE_IFNAME (distribute_lookup) Cast to char *, note that it's ok. (distribute_hash_alloc) use MTYPE_DISTRIBUTE_IFNAME. (distribute_get) Cast to char *, note that it's ok. * filter.c: Update with const qualifier. * if.{c,h}: ditto. * if_rmap.{c,h}: ditto. (if_rmap_lookup) Cast to char *, note that it's ok. (if_rmap_get) ditto. * log.{c,h}: Update with const qualifier. * plist.{c,h}: ditto. * routemap.{c,h}: ditto. * smux.{c,h}: ditto. Fix some signed/unsigned comparisons. * sockopt.c: (getsockopt_cmsg_data) add return for error case. * vty.c: Update with const qualifier. --- lib/command.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 2766a357..168fe563 100644 --- a/lib/command.c +++ b/lib/command.c @@ -432,7 +432,7 @@ to64(char *s, long v, int n) } } -char *zencrypt (char *passwd) +char *zencrypt (const char *passwd) { char salt[6]; struct timeval tv; @@ -1932,7 +1932,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cm struct cmd_element *matched_element; unsigned int matched_count, incomplete_count; int argc; - char *argv[CMD_ARGC_MAX]; + const char *argv[CMD_ARGC_MAX]; enum match_type match = 0; int varflag; char *command; @@ -2111,7 +2111,7 @@ cmd_execute_command_strict (vector vline, struct vty *vty, struct cmd_element *matched_element; unsigned int matched_count, incomplete_count; int argc; - char *argv[CMD_ARGC_MAX]; + const char *argv[CMD_ARGC_MAX]; int varflag; enum match_type match = 0; char *command; @@ -2983,22 +2983,38 @@ DEFUN (config_log_file, "Logging filename\n") { int ret; - char *cwd; - char *fullpath; - + char *p = NULL; + const char *fullpath; + /* Path detection. */ if (! IS_DIRECTORY_SEP (*argv[0])) { - cwd = getcwd (NULL, MAXPATHLEN); - fullpath = XMALLOC (MTYPE_TMP, - strlen (cwd) + strlen (argv[0]) + 2); - sprintf (fullpath, "%s/%s", cwd, argv[0]); + 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 = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (argv[0]) + 2)) + == NULL) + { + zlog_err ("config_log_file: Unable to alloc mem!"); + return CMD_WARNING; + } + sprintf (p, "%s/%s", cwd, argv[0]); + fullpath = p; } else fullpath = argv[0]; ret = zlog_set_file (NULL, ZLOG_FILE, fullpath); + if (p) + XFREE (MTYPE_TMP, p); + if (!ret) { vty_out (vty, "can't open logfile %s\n", argv[0]); -- cgit v1.2.3 From 42d498658d85e36a7e5910955e7425b1fa2afa69 Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 13 Oct 2004 05:22:18 +0000 Subject: 2004-10-13 Paul Jakma * (global) more const'ification. * sockunion.c: (sockunion_su2str) buffer should be sized SU_ADDRSTRLEN. (sockunion_log) do not return stack variables, strdup buf before return. * vty.h: Fix up the VTY_GET_INTEGER macros. Testing caller supplied values against ULONG_MAX is daft, when caller probably has passed a type that can not hold ULONG_MAX. use a temporary long instead. Add VTY_GET_LONG, make VTY_GET_INTEGER_RANGE use it, make VTY_GET_INTEGER a define for VTY_GET_INTEGER_RANGE. --- lib/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 168fe563..0e61e0d8 100644 --- a/lib/command.c +++ b/lib/command.c @@ -78,7 +78,7 @@ struct cmd_node config_node = /* Utility function to concatenate argv argument into a single string with inserting ' ' character between each argument. */ char * -argv_concat (char **argv, int argc, int shift) +argv_concat (const char **argv, int argc, int shift) { int i; int len; -- cgit v1.2.3 From ddd85ed1af88068939cee36a43125ff8ad50cf79 Mon Sep 17 00:00:00 2001 From: hasso Date: Wed, 13 Oct 2004 08:18:07 +0000 Subject: Fix critical bugzilla #113. Make CMD_ERR_NOTHING_TODO nonfatal. --- lib/command.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 0e61e0d8..4495d221 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2238,15 +2238,16 @@ config_from_file (struct vty *vty, FILE *fp) /* Try again with setting node to CONFIG_NODE */ while (ret != CMD_SUCCESS && ret != CMD_WARNING - && vty->node != CONFIG_NODE) - { + && ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE) + { vty->node = node_parent(vty->node); - ret = cmd_execute_command_strict (vline, vty, NULL); - } + ret = cmd_execute_command_strict (vline, vty, NULL); + } cmd_free_strvec (vline); - if (ret != CMD_SUCCESS && ret != CMD_WARNING) + if (ret != CMD_SUCCESS && ret != CMD_WARNING + && ret != CMD_ERR_NOTHING_TODO) return ret; } return CMD_SUCCESS; -- cgit v1.2.3 From 6590f2c3dc10acaa04cea3206fd00445e0a6145c Mon Sep 17 00:00:00 2001 From: hasso Date: Tue, 19 Oct 2004 20:40:08 +0000 Subject: Small copyright string and hostname related cleanup. --- lib/command.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 4495d221..fc115d95 100644 --- a/lib/command.c +++ b/lib/command.c @@ -36,13 +36,6 @@ vector cmdvec; /* Host information structure. */ struct host host; -/* Default motd string. */ -const char *default_motd = -"\r\n\ -Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ -Copyright 1996-2004 Kunihiro Ishiguro, et al.\r\n\ -\r\n"; - /* Standard command node structures. */ struct cmd_node auth_node = { @@ -74,6 +67,21 @@ struct cmd_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"; + +void +print_version (const char *progname) +{ + printf ("%s version %s (%s)\n", progname, QUAGGA_VERSION, host.name); + printf ("%s\n", QUAGGA_COPYRIGHT); +} + /* Utility function to concatenate argv argument into a single string with inserting ' ' character between each argument. */ @@ -2397,10 +2405,8 @@ DEFUN (show_version, SHOW_STR "Displays zebra version\n") { - vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, - host_name, - VTY_NEWLINE); - vty_out (vty, "Copyright 1996-2002, Kunihiro Ishiguro.%s", VTY_NEWLINE); + vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name, VTY_NEWLINE); + vty_out (vty, "%s%s", QUAGGA_COPYRIGHT, VTY_NEWLINE); return CMD_SUCCESS; } @@ -2412,7 +2418,7 @@ DEFUN (config_help, "Description of the interactive help system\n") { vty_out (vty, - "Zebra VTY provides advanced help feature. When you need help,%s\ + "Quagga VTY provides advanced help feature. 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\ -- cgit v1.2.3 From 6099b3b56956322567323c11fd698b2328c6826b Mon Sep 17 00:00:00 2001 From: ajs Date: Sat, 20 Nov 2004 02:06:59 +0000 Subject: 2004-11-19 Andrew J. Schorr * global: Replace strerror with safe_strerror. And vtysh/vtysh.c needs to include "log.h" to pick up the declaration. --- lib/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index fc115d95..6c02c96e 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2562,7 +2562,7 @@ DEFUN (config_write_file, if (chmod (config_file, CONFIGFILE_MASK) != 0) { vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s", - config_file, strerror(errno), errno, VTY_NEWLINE); + config_file, safe_strerror(errno), errno, VTY_NEWLINE); return CMD_WARNING; } -- cgit v1.2.3 From d246bd965898f0ba6781f2b2048af9a5eba079d3 Mon Sep 17 00:00:00 2001 From: ajs Date: Tue, 23 Nov 2004 17:35:08 +0000 Subject: 2004-11-23 Andrew J. Schorr * log.c: (vzlog) Take a single va_list argument and use va_copy as necessary for multiple traversals. (zlog) Pass only one va_list to vzlog. (zlog_*,plog_*) Use a macro for boilerplate code; pass only one va_list to vzlog. (zlog_set_file) Remove unused 2nd argument (flags). (zlog_save_cwd,zlog_get_cwd,zlog_free_cwd) Remove unused functions. * log.h: Remove ZLOG_*_INDEX defines (no longer used). Remove unused 2nd argument from zlog_set_file prototype. Fix prototype for zlog_rotate. * command.c: (config_log_file) Remove unused 2nd arg to zlog_set_file. * vty.c: (vty_out) Fix stdarg usage to perform multiple traversals properly. (vty_log) Must use va_copy for multiple traversals of va_list arg. --- lib/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 6c02c96e..60b0124d 100644 --- a/lib/command.c +++ b/lib/command.c @@ -3017,7 +3017,7 @@ DEFUN (config_log_file, else fullpath = argv[0]; - ret = zlog_set_file (NULL, ZLOG_FILE, fullpath); + ret = zlog_set_file (NULL, fullpath); if (p) XFREE (MTYPE_TMP, p); -- cgit v1.2.3 From 56f2069a03a1be9bfd7605e43aa0d899b0d5ed60 Mon Sep 17 00:00:00 2001 From: ajs Date: Fri, 3 Dec 2004 17:40:31 +0000 Subject: 2004-12-03 Andrew J. Schorr * command.h: Remove fields log_stdout and log_syslog from struct host, since they are just trying to duplicate information in the zlog_default structure. Note that this fixes a bug since those fields were not registering any logging that was established in the initial call to openzlog (this affects only the zebra and ospf6d daemons). It is probably a bug to turn on any logging by default in the call to openzlog. * command.c: (config_write_host) Get logging info from zlog_default instead of now-removed fields host.log_stdout and host.log_syslog. (config_log_stdout,no_config_log_stdout) Do not set now-removed field host.log_stdout, since this info is recorded in zlog_default. (config_log_file) Use XSTRDUP (instead of strdup) to set host.logfile. (config_log_syslog,config_log_syslog_facility,no_config_log_syslog) Do not set now-removed field host.log_syslog, since this info is recorded in zlog_default. --- lib/command.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 60b0124d..99036d17 100644 --- a/lib/command.c +++ b/lib/command.c @@ -545,10 +545,10 @@ config_write_host (struct vty *vty) if (host.logfile) vty_out (vty, "log file %s%s", host.logfile, VTY_NEWLINE); - if (host.log_stdout) + if (zlog_default->flags & ZLOG_STDOUT) vty_out (vty, "log stdout%s", VTY_NEWLINE); - if (host.log_syslog) + if (zlog_default->flags & ZLOG_SYSLOG) { vty_out (vty, "log syslog"); if (zlog_default->facility != LOG_DAEMON) @@ -2966,7 +2966,6 @@ DEFUN (config_log_stdout, "Logging goes to stdout\n") { zlog_set_flag (NULL, ZLOG_STDOUT); - host.log_stdout = 1; return CMD_SUCCESS; } @@ -2978,7 +2977,6 @@ DEFUN (no_config_log_stdout, "Cancel logging to stdout\n") { zlog_reset_flag (NULL, ZLOG_STDOUT); - host.log_stdout = 0; return CMD_SUCCESS; } @@ -3031,7 +3029,7 @@ DEFUN (config_log_file, if (host.logfile) XFREE (MTYPE_TMP, host.logfile); - host.logfile = strdup (argv[0]); + host.logfile = XSTRDUP (MTYPE_TMP, argv[0]); return CMD_SUCCESS; } @@ -3061,7 +3059,6 @@ DEFUN (config_log_syslog, "Logging goes to syslog\n") { zlog_set_flag (NULL, ZLOG_SYSLOG); - host.log_syslog = 1; zlog_default->facility = LOG_DAEMON; return CMD_SUCCESS; } @@ -3094,7 +3091,6 @@ DEFUN (config_log_syslog_facility, int facility = LOG_DAEMON; zlog_set_flag (NULL, ZLOG_SYSLOG); - host.log_syslog = 1; if (strncmp (argv[0], "kern", 1) == 0) facility = LOG_KERN; @@ -3146,7 +3142,6 @@ DEFUN (no_config_log_syslog, "Cancel logging to syslog\n") { zlog_reset_flag (NULL, ZLOG_SYSLOG); - host.log_syslog = 0; zlog_default->facility = LOG_DAEMON; return CMD_SUCCESS; } -- cgit v1.2.3 From 274a4a4447b13f89f8237156a887d05a24a73cc6 Mon Sep 17 00:00:00 2001 From: ajs Date: Tue, 7 Dec 2004 15:39:31 +0000 Subject: 2004-12-07 Andrew J. Schorr * bgp_main.c: (main) The 2nd argument to openzlog has been removed. * isis_main.c: (main) The 2nd argument to openzlog has been removed. * ospf6_main.c: (main) The 2nd argument to openzlog has been removed. Note that stdout logging will no longer be enabled by default when not running as a daemon. * ospf_main.c: (main) The 2nd argument to openzlog has been removed. * rip_main.c: (main) The 2nd argument to openzlog has been removed. * ripng_main.c: (main) The 2nd argument to openzlog has been removed. * main.c: (main) The 2nd argument to openzlog has been removed. So stdout logging will no longer be enabled by default. * irdp_main.c: (irdp_finish) Reduce severity of shutdown message from LOG_WARNING to LOG_INFO. * vtysh.c: Make several functions static instead of global. Added several commands to support destination-specific logging levels. (vtysh_completion) This function is unused, so comment it out. * basic.texi: Document new logging features. Separate basic config commands from basic VTY commands. * log.h: Replace struct zlog flags and maskpri fields with maxlvl array to support individual logging levels for each destination. Remove the 2nd argument to openzlog since the default logging config should be standardized inside the library. Replaced the zlog_set_flag and zlog_reset_flag functions with zlog_set_level. And zlog_set_file now requires an additional log_level argument. Declare zlog_proto_names for use inside command.c in the "show logging" command. Added defines useful for command construction. * log.c: (vzlog) Decide where to send the message based on the individual logging levels configured for each destination. Remove support for ZLOG_STDERR since it was never actually used. Support record-priority for terminal monitors. (zlog_signal,zlog_backtrace_sigsafe) Support destination-specific logging levels. Remove stderr support (was never used). Added support for terminal monitor logging. (_zlog_assert_failed) Increase message severity to LOG_EMERG. (openzlog) Remove 2nd argument since default config should be standardized in library. By default, terminal monitoring is set to debug, and all other logging is disabled. (zlog_set_flag,zlog_reset_flag) Removed. (zlog_set_level) New function to replace zlog_set_flag and zlog_reset_flag. Supports destination-specific logging levels. (zlog_set_file,zlog_reset_file) Support file-specific logging level. (zlog_rotate) Log an error message if fopen fails, and support new file-specific logging level. * command.h: Change DEFUN_CMD_FUNC_DECL and DEFUN_CMD_FUNC_TEXT so that command functions will be static instead of global. Remove declarations for config_exit and config_help. Define new macros DEFUNSH_ATTR, DEFUNSH_HIDDEN, and DEFUNSH_DEPRECATED so we can have deprecated commands in vtysh. Similarly, for completeness, define macros ALIAS_SH, ALIAS_SH_HIDDEN, and ALIAS_SH_DEPRECATED. Also, fix bug in ALIAS_ATTR macro (didn't matter because it was never used). * command.c: Make many functions static instead of global. (facility_name,facility_match,level_match) New functions to support enhanced destination-specific logging levels. (config_write_host) Support new destination-specific logging levels. (config_logmsg) Added new "logmsg" command to help test logging system. (show_logging) Added "show logging" command to show the current configuration of the logging system. (config_log_stdout_level) Support explicit stdout logging level. (no_config_log_stdout) Now takes optional LEVEL arg. (config_log_monitor,config_log_monitor_level,no_config_log_monitor) New commands creating new "log monitor" commands to set terminal monitoring log level. (config_log_file_level) Support explicit file logging level. (config_log_syslog_level) Support explicit syslog logging level. (config_log_facility,no_config_log_facility) Implement new "log facility" command. (cmd_init) Add hooks for new commands: "show logging", "logmsg", "log stdout ", "log monitor", "log monitor ", "no log monitor", "log file ", "no log file ", "log syslog ", "log facility", and "no log facility". * vty.h: Added a "level" argument to vty_log so it can support "log record-priority". Declare new function vty_log_fixed for use in signal handlers. * vty.c: (vty_log,vty_log_out) Added a "level" argument to support "log record-priority" for vty terminal monitors. (vty_down_level) Use config_exit_cmd.func instead of calling config_exit directly (since command functions will now be static instead of global). (vty_log_fixed) New function to send terminal monitor messages from inside a signal handler. --- lib/command.c | 636 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 402 insertions(+), 234 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 99036d17..18829672 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,4 +1,7 @@ -/* Command interpreter routine for virtual terminal [aka TeletYpe] +/* + $Id: command.c,v 1.28 2004/12/07 15:39:32 ajs Exp $ + + Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro This file is part of GNU Zebra. @@ -75,6 +78,70 @@ Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ " QUAGGA_COPYRIGHT "\r\n\ \r\n"; + +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; +} + void print_version (const char *progname) { @@ -128,7 +195,7 @@ install_node (struct cmd_node *node, } /* Compare two command's string. Used in sort_node (). */ -int +static int cmp_node (const void *p, const void *q) { struct cmd_element *a = *(struct cmd_element **)p; @@ -137,7 +204,7 @@ cmp_node (const void *p, const void *q) return strcmp (a->string, b->string); } -int +static int cmp_desc (const void *p, const void *q) { struct desc *a = *(struct desc **)p; @@ -241,7 +308,7 @@ cmd_free_strvec (vector v) } /* Fetch next description. Used in cmd_make_descvec(). */ -char * +static char * cmd_desc_str (const char **string) { const char *cp, *start; @@ -277,7 +344,7 @@ cmd_desc_str (const char **string) } /* New string vector. */ -vector +static vector cmd_make_descvec (const char *string, const char *descstr) { int multiple = 0; @@ -370,7 +437,7 @@ cmd_make_descvec (const char *string, const char *descstr) /* Count mandantory string vector size. This is to determine inputed command has enough command length. */ -int +static int cmd_cmdsize (vector strvec) { unsigned int i; @@ -430,7 +497,7 @@ install_element (enum node_type ntype, struct cmd_element *cmd) static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -void +static void to64(char *s, long v, int n) { while (--n >= 0) @@ -440,7 +507,8 @@ to64(char *s, long v, int n) } } -char *zencrypt (const char *passwd) +static char * +zencrypt (const char *passwd) { char salt[6]; struct timeval tv; @@ -455,73 +523,8 @@ char *zencrypt (const char *passwd) return crypt (passwd, salt); } -const char * -syslog_facility_print (int facility) -{ - switch (facility) - { - case LOG_KERN: - return "kern"; - break; - case LOG_USER: - return "user"; - break; - case LOG_MAIL: - return "mail"; - break; - case LOG_DAEMON: - return "daemon"; - break; - case LOG_AUTH: - return "auth"; - break; - case LOG_SYSLOG: - return "syslog"; - break; - case LOG_LPR: - return "lpr"; - break; - case LOG_NEWS: - return "news"; - break; - case LOG_UUCP: - return "uucp"; - break; - case LOG_CRON: - return "cron"; - break; - case LOG_LOCAL0: - return "local0"; - break; - case LOG_LOCAL1: - return "local1"; - break; - case LOG_LOCAL2: - return "local2"; - break; - case LOG_LOCAL3: - return "local3"; - break; - case LOG_LOCAL4: - return "local4"; - break; - case LOG_LOCAL5: - return "local5"; - break; - case LOG_LOCAL6: - return "local6"; - break; - case LOG_LOCAL7: - return "local7"; - break; - default: - break; - } - return ""; -} - /* This function write configuration of this host. */ -int +static int config_write_host (struct vty *vty) { if (host.name) @@ -542,21 +545,46 @@ config_write_host (struct vty *vty) vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE); } - if (host.logfile) - vty_out (vty, "log file %s%s", host.logfile, VTY_NEWLINE); + if (zlog_default->default_lvl != LOG_DEBUG) + 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->flags & ZLOG_STDOUT) - vty_out (vty, "log stdout%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->flags & ZLOG_SYSLOG) + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) { vty_out (vty, "log syslog"); - if (zlog_default->facility != LOG_DAEMON) - vty_out (vty, " facility %s", syslog_facility_print (zlog_default->facility)); + 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->maskpri != LOG_DEBUG) - vty_out (vty, "log trap %s%s", zlog_priority[zlog_default->maskpri], 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); @@ -578,15 +606,17 @@ config_write_host (struct vty *vty) } /* Utility function for getting command vector. */ -vector +static vector cmd_node_vector (vector v, enum node_type ntype) { struct cmd_node *cnode = vector_slot (v, ntype); return cnode->cmd_vector; } -/* Filter command vector by symbol */ -int +#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; @@ -629,6 +659,7 @@ cmd_filter_by_symbol (char *command, char *symbol) } return 0; } +#endif /* Completion match types. */ enum match_type @@ -645,7 +676,7 @@ enum match_type exact_match }; -enum match_type +static enum match_type cmd_ipv4_match (const char *str) { const char *sp; @@ -702,7 +733,7 @@ cmd_ipv4_match (const char *str) return exact_match; } -enum match_type +static enum match_type cmd_ipv4_prefix_match (const char *str) { const char *sp; @@ -793,7 +824,7 @@ cmd_ipv4_prefix_match (const char *str) #ifdef HAVE_IPV6 -enum match_type +static enum match_type cmd_ipv6_match (const char *str) { int state = STATE_START; @@ -899,7 +930,7 @@ cmd_ipv6_match (const char *str) return exact_match; } -enum match_type +static enum match_type cmd_ipv6_prefix_match (const char *str) { int state = STATE_START; @@ -1034,7 +1065,7 @@ cmd_ipv6_prefix_match (const char *str) #define DECIMAL_STRLEN_MAX 10 -int +static int cmd_range_match (const char *range, const char *str) { char *p; @@ -1080,7 +1111,7 @@ cmd_range_match (const char *range, const char *str) } /* Make completion match and return match type flag. */ -enum match_type +static enum match_type cmd_filter_by_completion (char *command, vector v, unsigned int index) { unsigned int i; @@ -1195,7 +1226,7 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) } /* Filter vector by command character with index. */ -enum match_type +static enum match_type cmd_filter_by_string (char *command, vector v, unsigned int index) { unsigned int i; @@ -1303,7 +1334,7 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) } /* Check ambiguous match */ -int +static int is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) { unsigned int i; @@ -1400,7 +1431,7 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) } /* If src matches dst return dst string, otherwise return NULL */ -const char * +static const char * cmd_entry_function (const char *src, const char *dst) { /* Skip variable arguments. */ @@ -1422,7 +1453,7 @@ cmd_entry_function (const char *src, const char *dst) /* 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 */ -const char * +static const char * cmd_entry_function_desc (const char *src, const char *dst) { if (CMD_VARARG (dst)) @@ -1486,7 +1517,7 @@ cmd_entry_function_desc (const char *src, const char *dst) /* Check same string element existence. If it isn't there return 1. */ -int +static int cmd_unique_string (vector v, const char *str) { unsigned int i; @@ -1501,7 +1532,7 @@ cmd_unique_string (vector v, const char *str) /* Compare string to description vector. If there is same string return 1 else return 0. */ -int +static int desc_unique_string (vector v, const char *str) { unsigned int i; @@ -1514,7 +1545,7 @@ desc_unique_string (vector v, const char *str) return 0; } -int +static int cmd_try_do_shortcut (enum node_type node, char* first_word) { if ( first_word != NULL && node != AUTH_NODE && @@ -1527,7 +1558,7 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) { } /* '?' describe command support. */ -vector +static vector cmd_describe_command_real (vector vline, struct vty *vty, int *status) { unsigned int i; @@ -1690,7 +1721,7 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) /* Check LCD of matched command. */ -int +static int cmd_lcd (char **matched) { int i; @@ -1723,7 +1754,7 @@ cmd_lcd (char **matched) } /* Command line completion support. */ -char ** +static char ** cmd_complete_command_real (vector vline, struct vty *vty, int *status) { unsigned int i; @@ -1905,7 +1936,8 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) /* return parent node */ /* MUST eventually converge on CONFIG_NODE */ -enum node_type node_parent ( enum node_type node ) +static enum node_type +node_parent ( enum node_type node ) { enum node_type ret; @@ -1930,7 +1962,7 @@ enum node_type node_parent ( enum node_type node ) } /* Execute command by argument vline vector. */ -int +static int cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd) { unsigned int i; @@ -2959,40 +2991,158 @@ DEFUN (no_service_terminal_length, no_service_terminal_length_cmd, return CMD_SUCCESS; } +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))); + XFREE(MTYPE_TMP, 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" - "Logging goes to stdout\n") + "Set stdout logging level\n") { - zlog_set_flag (NULL, ZLOG_STDOUT); + 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", + "no log stdout [LEVEL]", NO_STR "Logging control\n" - "Cancel logging to stdout\n") + "Cancel logging to stdout\n" + "Logging level\n") { - zlog_reset_flag (NULL, ZLOG_STDOUT); + zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED); return CMD_SUCCESS; } -DEFUN (config_log_file, - config_log_file_cmd, - "log file FILENAME", +DEFUN (config_log_monitor, + config_log_monitor_cmd, + "log monitor", "Logging control\n" - "Logging to file\n" - "Logging filename\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 (*argv[0])) + if (! IS_DIRECTORY_SEP (*fname)) { char cwd[MAXPATHLEN+1]; cwd[MAXPATHLEN] = '\0'; @@ -3003,37 +3153,62 @@ DEFUN (config_log_file, return CMD_WARNING; } - if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (argv[0]) + 2)) + if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2)) == NULL) { zlog_err ("config_log_file: Unable to alloc mem!"); return CMD_WARNING; } - sprintf (p, "%s/%s", cwd, argv[0]); + sprintf (p, "%s/%s", cwd, fname); fullpath = p; } else - fullpath = argv[0]; + fullpath = fname; - ret = zlog_set_file (NULL, fullpath); + ret = zlog_set_file (NULL, fullpath, loglevel); if (p) XFREE (MTYPE_TMP, p); if (!ret) { - vty_out (vty, "can't open logfile %s\n", argv[0]); + vty_out (vty, "can't open logfile %s\n", fname); return CMD_WARNING; } if (host.logfile) XFREE (MTYPE_TMP, host.logfile); - host.logfile = XSTRDUP (MTYPE_TMP, argv[0]); + host.logfile = XSTRDUP (MTYPE_TMP, 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]", @@ -3052,154 +3227,135 @@ DEFUN (no_config_log_file, 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" - "Logging goes to syslog\n") + "Set syslog logging level\n") { - zlog_set_flag (NULL, ZLOG_SYSLOG); - zlog_default->facility = LOG_DAEMON; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); return CMD_SUCCESS; } -DEFUN (config_log_syslog_facility, - config_log_syslog_facility_cmd, - "log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", +DEFUN (config_log_syslog_level, + config_log_syslog_level_cmd, + "log syslog "LOG_LEVELS, "Logging control\n" - "Logging goes to syslog\n" - "Facility parameter for syslog messages\n" - "Kernel\n" - "User process\n" - "Mail system\n" - "System daemons\n" - "Authorization system\n" - "Syslog itself\n" - "Line printer system\n" - "USENET news\n" - "Unix-to-Unix copy system\n" - "Cron/at facility\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n") -{ - int facility = LOG_DAEMON; - - zlog_set_flag (NULL, ZLOG_SYSLOG); - - if (strncmp (argv[0], "kern", 1) == 0) - facility = LOG_KERN; - else if (strncmp (argv[0], "user", 2) == 0) - facility = LOG_USER; - else if (strncmp (argv[0], "mail", 1) == 0) - facility = LOG_MAIL; - else if (strncmp (argv[0], "daemon", 1) == 0) - facility = LOG_DAEMON; - else if (strncmp (argv[0], "auth", 1) == 0) - facility = LOG_AUTH; - else if (strncmp (argv[0], "syslog", 1) == 0) - facility = LOG_SYSLOG; - else if (strncmp (argv[0], "lpr", 2) == 0) - facility = LOG_LPR; - else if (strncmp (argv[0], "news", 1) == 0) - facility = LOG_NEWS; - else if (strncmp (argv[0], "uucp", 2) == 0) - facility = LOG_UUCP; - else if (strncmp (argv[0], "cron", 1) == 0) - facility = LOG_CRON; - else if (strncmp (argv[0], "local0", 6) == 0) - facility = LOG_LOCAL0; - else if (strncmp (argv[0], "local1", 6) == 0) - facility = LOG_LOCAL1; - else if (strncmp (argv[0], "local2", 6) == 0) - facility = LOG_LOCAL2; - else if (strncmp (argv[0], "local3", 6) == 0) - facility = LOG_LOCAL3; - else if (strncmp (argv[0], "local4", 6) == 0) - facility = LOG_LOCAL4; - else if (strncmp (argv[0], "local5", 6) == 0) - facility = LOG_LOCAL5; - else if (strncmp (argv[0], "local6", 6) == 0) - facility = LOG_LOCAL6; - else if (strncmp (argv[0], "local7", 6) == 0) - facility = LOG_LOCAL7; + "Set syslog logging level\n" + LOG_LEVEL_DESC) +{ + int level; - zlog_default->facility = facility; + 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", + "no log syslog [LEVEL]", NO_STR "Logging control\n" - "Cancel logging to syslog\n") + "Cancel logging to syslog\n" + "Logging level\n") { - zlog_reset_flag (NULL, ZLOG_SYSLOG); - zlog_default->facility = LOG_DAEMON; + 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 (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", + "no log syslog facility "LOG_FACILITIES, NO_STR "Logging control\n" "Logging goes to syslog\n" "Facility parameter for syslog messages\n" - "Kernel\n" - "User process\n" - "Mail system\n" - "System daemons\n" - "Authorization system\n" - "Syslog itself\n" - "Line printer system\n" - "USENET news\n" - "Unix-to-Unix copy system\n" - "Cron/at facility\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n") - -DEFUN (config_log_trap, - config_log_trap_cmd, - "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)", + LOG_FACILITY_DESC) + +DEFUN (config_log_facility, + config_log_facility_cmd, + "log facility "LOG_FACILITIES, "Logging control\n" - "Limit logging to specifed level\n") + "Facility parameter for syslog messages\n" + LOG_FACILITY_DESC) { - int new_level ; - - for ( new_level = 0 ; zlog_priority [new_level] != NULL ; new_level ++ ) - { - if ( strcmp ( argv[0], zlog_priority [new_level] ) == 0 ) - /* found new logging level */ - { - zlog_default->maskpri = new_level; - return CMD_SUCCESS; - } - } - return CMD_ERR_NO_MATCH; + 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_trap, - no_config_log_trap_cmd, - "no log trap", +DEFUN (no_config_log_facility, + no_config_log_facility_cmd, + "no log facility [FACILITY]", NO_STR "Logging control\n" - "Permit all logging information\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->maskpri = LOG_DEBUG; + zlog_default->default_lvl = LOG_DEBUG; return CMD_SUCCESS; } @@ -3304,6 +3460,7 @@ cmd_init (int terminal) 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, &show_logging_cmd); } if (terminal) @@ -3320,6 +3477,8 @@ cmd_init (int terminal) { install_element (ENABLE_NODE, &config_terminal_length_cmd); install_element (ENABLE_NODE, &config_terminal_no_length_cmd); + install_element (ENABLE_NODE, &show_logging_cmd); + install_element (ENABLE_NODE, &config_logmsg_cmd); install_default (CONFIG_NODE); } @@ -3336,13 +3495,22 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &no_enable_password_cmd); install_element (CONFIG_NODE, &config_log_stdout_cmd); + install_element (CONFIG_NODE, &config_log_stdout_level_cmd); install_element (CONFIG_NODE, &no_config_log_stdout_cmd); + install_element (CONFIG_NODE, &config_log_monitor_cmd); + install_element (CONFIG_NODE, &config_log_monitor_level_cmd); + install_element (CONFIG_NODE, &no_config_log_monitor_cmd); install_element (CONFIG_NODE, &config_log_file_cmd); + install_element (CONFIG_NODE, &config_log_file_level_cmd); install_element (CONFIG_NODE, &no_config_log_file_cmd); + install_element (CONFIG_NODE, &no_config_log_file_level_cmd); install_element (CONFIG_NODE, &config_log_syslog_cmd); + install_element (CONFIG_NODE, &config_log_syslog_level_cmd); install_element (CONFIG_NODE, &config_log_syslog_facility_cmd); install_element (CONFIG_NODE, &no_config_log_syslog_cmd); install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd); + install_element (CONFIG_NODE, &config_log_facility_cmd); + install_element (CONFIG_NODE, &no_config_log_facility_cmd); install_element (CONFIG_NODE, &config_log_trap_cmd); install_element (CONFIG_NODE, &no_config_log_trap_cmd); install_element (CONFIG_NODE, &config_log_record_priority_cmd); -- cgit v1.2.3 From 82146b88915ca614ee1c28659478d6e310d84110 Mon Sep 17 00:00:00 2001 From: ajs Date: Tue, 7 Dec 2004 17:15:55 +0000 Subject: 2004-12-07 Andrew J. Schorr * command.c: (config_write_host) Note that "log trap" is deprecated when writing out the config. --- lib/command.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 18829672..cabdb237 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.28 2004/12/07 15:39:32 ajs Exp $ + $Id: command.c,v 1.29 2004/12/07 17:15:56 ajs Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -546,8 +546,12 @@ config_write_host (struct vty *vty) } if (zlog_default->default_lvl != LOG_DEBUG) - vty_out (vty, "log trap %s%s", - zlog_priority[zlog_default->default_lvl], VTY_NEWLINE); + { + 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)) { -- cgit v1.2.3 From 2885f72d546a9d4673e4b9a607f8e30ab2e88cc9 Mon Sep 17 00:00:00 2001 From: ajs Date: Fri, 17 Dec 2004 23:16:33 +0000 Subject: 2004-12-17 Andrew J. Schorr * command.c: (do_echo) Added new "echo" command, useful for watchdog pinging to make sure the daemon is responsive. --- lib/command.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index cabdb237..2766c414 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.29 2004/12/07 17:15:56 ajs Exp $ + $Id: command.c,v 1.30 2004/12/17 23:16:33 ajs Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -2995,6 +2995,19 @@ DEFUN (no_service_terminal_length, no_service_terminal_length_cmd, 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)), VTY_NEWLINE); + XFREE(MTYPE_TMP, message); + return CMD_SUCCESS; +} + DEFUN (config_logmsg, config_logmsg_cmd, "logmsg "LOG_LEVELS" .MESSAGE", @@ -3465,6 +3478,7 @@ cmd_init (int terminal) install_element (VIEW_NODE, &config_terminal_length_cmd); install_element (VIEW_NODE, &config_terminal_no_length_cmd); install_element (VIEW_NODE, &show_logging_cmd); + install_element (VIEW_NODE, &echo_cmd); } if (terminal) @@ -3482,6 +3496,7 @@ cmd_init (int terminal) install_element (ENABLE_NODE, &config_terminal_length_cmd); install_element (ENABLE_NODE, &config_terminal_no_length_cmd); install_element (ENABLE_NODE, &show_logging_cmd); + install_element (ENABLE_NODE, &echo_cmd); install_element (ENABLE_NODE, &config_logmsg_cmd); install_default (CONFIG_NODE); -- cgit v1.2.3 From cba8a60639aa83659ce551e91266dcee8408fc23 Mon Sep 17 00:00:00 2001 From: hasso Date: Sun, 2 Jan 2005 18:51:01 +0000 Subject: Reverting some int -> unsigned int fixes in command.c for now. Fixes crash described in [quagga-dev 2292]. --- lib/command.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 2766c414..b1260af9 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.30 2004/12/17 23:16:33 ajs Exp $ + $Id: command.c,v 1.31 2005/01/02 18:51:01 hasso Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1565,12 +1565,12 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) { static vector cmd_describe_command_real (vector vline, struct vty *vty, int *status) { - unsigned int i; + int i; vector cmd_vector; #define INIT_MATCHVEC_SIZE 10 vector matchvec; struct cmd_element *cmd_element; - unsigned int index; + int index; int ret; enum match_type match; char *command; @@ -1761,12 +1761,12 @@ cmd_lcd (char **matched) static char ** cmd_complete_command_real (vector vline, struct vty *vty, int *status) { - unsigned int i; + 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 = vector_max (vline) - 1; + int index = vector_max (vline) - 1; char **match_str; struct desc *desc; vector descvec; -- cgit v1.2.3 From f867d32c4a0d6a18c5f7c042b9dd5798dce93e10 Mon Sep 17 00:00:00 2001 From: gdt Date: Fri, 14 Jan 2005 15:47:33 +0000 Subject: 2005-01-14 Greg Troxel * command.c (print_version): Don't print host.name if it is NULL. Fixes segfault on Solaris reported by Goetz von Escher (pullup candidate) --- lib/command.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index b1260af9..3891733b 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.31 2005/01/02 18:51:01 hasso Exp $ + $Id: command.c,v 1.32 2005/01/14 15:47:33 gdt Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -145,8 +145,10 @@ level_match(const char *s) void print_version (const char *progname) { - printf ("%s version %s (%s)\n", progname, QUAGGA_VERSION, host.name); - printf ("%s\n", QUAGGA_COPYRIGHT); + printf ("%s version %s", progname, QUAGGA_VERSION); + if (host.name != NULL) + printf (" (%s)", host.name); + printf ("\n%s\n", QUAGGA_COPYRIGHT); } -- cgit v1.2.3 From cb585b65d1a513fd62449cc031e273245a8fd6c0 Mon Sep 17 00:00:00 2001 From: ajs Date: Fri, 14 Jan 2005 17:09:38 +0000 Subject: 2005-01-14 Andrew J. Schorr * command.c (print_version): Do not bother even to examine host.name, since it is always NULL when this function is called from main. --- lib/command.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 3891733b..92bbac75 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.32 2005/01/14 15:47:33 gdt Exp $ + $Id: command.c,v 1.33 2005/01/14 17:09:38 ajs Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -142,13 +142,12 @@ level_match(const char *s) return ZLOG_DISABLED; } +/* This is called from main when a daemon is invoked with -v or --version. */ void print_version (const char *progname) { - printf ("%s version %s", progname, QUAGGA_VERSION); - if (host.name != NULL) - printf (" (%s)", host.name); - printf ("\n%s\n", QUAGGA_COPYRIGHT); + printf ("%s version %s\n", progname, QUAGGA_VERSION); + printf ("%s\n", QUAGGA_COPYRIGHT); } -- cgit v1.2.3 From 87d683b071dc7abfb30b666960ec480e64e19ce4 Mon Sep 17 00:00:00 2001 From: hasso Date: Sun, 16 Jan 2005 23:31:54 +0000 Subject: * command.[ch], vty.c: cmd_execute_command() function must not attempt to walk up in the node tree if called from vtysh. Different daemons might have commands with same syntax in different nodes (for example "router-id x.x.x.x" commands in zebra/ospfd/ospf6d daemons). * vtysh.c: Reflect changes in lib. cmd_execute_command() should know now that it's called from vtysh and must not attempt to walk up in the node tree. [pullup candidate] --- lib/command.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 92bbac75..8f9b98e5 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.33 2005/01/14 17:09:38 ajs Exp $ + $Id: command.c,v 1.34 2005/01/16 23:31:54 hasso Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -2092,7 +2092,8 @@ cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cm int -cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { +cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd, + int vtysh) { int ret, saved_ret, tried = 0; enum node_type onode, try_node; @@ -2123,6 +2124,9 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) { 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 ) -- cgit v1.2.3 From 13bfca7a1059a73a836f4813170f296a82266211 Mon Sep 17 00:00:00 2001 From: hasso Date: Sun, 23 Jan 2005 21:42:25 +0000 Subject: * lib/command.[ch]: Make node_parent() function nonstatic. vtyh.c will use it as well. * vtysh/vtysh.c: Implement walkup in node tree for vtysh as it already works in vty. --- lib/command.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 8f9b98e5..6b65a5d2 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.34 2005/01/16 23:31:54 hasso Exp $ + $Id: command.c,v 1.35 2005/01/23 21:42:25 hasso Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1941,7 +1941,7 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) /* return parent node */ /* MUST eventually converge on CONFIG_NODE */ -static enum node_type +enum node_type node_parent ( enum node_type node ) { enum node_type ret; -- cgit v1.2.3 From f6834d4c4031276361465dd19ef1918e239566c8 Mon Sep 17 00:00:00 2001 From: ajs Date: Fri, 28 Jan 2005 20:28:35 +0000 Subject: 2005-01-28 Andrew J. Schorr * lib/command.h: Document behavior of argv_concat function. * lib/command.c: (argv_concat) Calculate total string length first so we can call malloc just once (instead of realloc'ing to add each string element). (do_echo,config_logmsg) Allow for possible NULL return value from argv_concat. --- lib/command.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 6b65a5d2..be38fcc0 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.35 2005/01/23 21:42:25 hasso Exp $ + $Id: command.c,v 1.36 2005/01/28 20:28:35 ajs Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -157,31 +157,24 @@ char * argv_concat (const char **argv, int argc, int shift) { int i; - int len; - int index; + size_t len; char *str; + char *p; - str = NULL; - index = 0; - + len = 0; + for (i = shift; i < argc; i++) + len += strlen(argv[i])+1; + if (!len) + return NULL; + p = str = XMALLOC(MTYPE_TMP, len); for (i = shift; i < argc; i++) { - len = strlen (argv[i]); - - if (i == shift) - { - str = XSTRDUP (MTYPE_TMP, argv[i]); - index = len; - } - else - { - str = XREALLOC (MTYPE_TMP, str, (index + len + 2)); - str[index++] = ' '; - memcpy (str + index, argv[i], len); - index += len; - str[index] = '\0'; - } + size_t arglen; + memcpy(p, argv[i], (arglen = strlen(argv[i]))); + p += arglen; + *p++ = ' '; } + *(p-1) = '\0'; return str; } @@ -3008,8 +3001,10 @@ DEFUN_HIDDEN (do_echo, { char *message; - vty_out (vty, "%s%s",(message = argv_concat(argv, argc, 0)), VTY_NEWLINE); - XFREE(MTYPE_TMP, message); + vty_out (vty, "%s%s", ((message = argv_concat(argv, argc, 0)) ? message : ""), + VTY_NEWLINE); + if (message) + XFREE(MTYPE_TMP, message); return CMD_SUCCESS; } @@ -3026,8 +3021,9 @@ DEFUN (config_logmsg, if ((level = level_match(argv[0])) == ZLOG_DISABLED) return CMD_ERR_NO_MATCH; - zlog(NULL, level, (message = argv_concat(argv, argc, 1))); - XFREE(MTYPE_TMP, message); + zlog(NULL, level, ((message = argv_concat(argv, argc, 1)) ? message : "")); + if (message) + XFREE(MTYPE_TMP, message); return CMD_SUCCESS; } -- cgit v1.2.3 From 12f6ea2300402c821595297ff0c2c75055e50031 Mon Sep 17 00:00:00 2001 From: hasso Date: Mon, 7 Mar 2005 08:35:39 +0000 Subject: * command.c: host.name might be NULL. * vty.c: Fix fd leak. [backport candidate] --- lib/command.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index be38fcc0..1e1f3cf5 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.36 2005/01/28 20:28:35 ajs Exp $ + $Id: command.c,v 1.37 2005/03/07 08:35:39 hasso Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -2439,7 +2439,8 @@ DEFUN (show_version, SHOW_STR "Displays zebra version\n") { - vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name, VTY_NEWLINE); + vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name?host.name:"", + VTY_NEWLINE); vty_out (vty, "%s%s", QUAGGA_COPYRIGHT, VTY_NEWLINE); return CMD_SUCCESS; -- cgit v1.2.3 From 3b0c5d9a56560cfbfb1a8f5b9e6cc71025eb5490 Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 8 Mar 2005 10:43:43 +0000 Subject: 2005-03-08 Jeroen Massar * vty.c: (vty_hello) display motd file, if set * command.h: add char *motdfile to struct host * command.c: (config_write_host) write out motdfile config (banner_motd_file_cmd) new command, allow motd to be read from file. (no_banner_motd_cmd) free motdfile string, if needs be. (cmd_init) init (struct host).motdfile. Add new motd file commands. --- lib/command.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 1e1f3cf5..ca1100da 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.37 2005/03/07 08:35:39 hasso Exp $ + $Id: command.c,v 1.38 2005/03/08 10:43:43 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -597,7 +597,9 @@ config_write_host (struct vty *vty) vty_out (vty, "service terminal-length %d%s", host.lines, VTY_NEWLINE); - if (! host.motd) + 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; @@ -3399,6 +3401,18 @@ DEFUN (no_config_log_record_priority, return CMD_SUCCESS; } +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) free(host.motdfile); + host.motdfile = strdup(argv[0]); + return CMD_SUCCESS; +} DEFUN (banner_motd_default, banner_motd_default_cmd, @@ -3419,6 +3433,8 @@ DEFUN (no_banner_motd, "Strings for motd\n") { host.motd = NULL; + if (host.motdfile) free(host.motdfile); + host.motdfile = NULL; return CMD_SUCCESS; } @@ -3460,6 +3476,7 @@ cmd_init (int terminal) host.config = NULL; host.lines = -1; host.motd = default_motd; + host.motdfile = NULL; /* Install top nodes. */ install_node (&view_node, NULL); @@ -3539,6 +3556,7 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &service_password_encrypt_cmd); install_element (CONFIG_NODE, &no_service_password_encrypt_cmd); 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); -- cgit v1.2.3 From b45da6f01612e8ec1938cacfe0ea0ef34ad1afca Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 8 Mar 2005 15:16:57 +0000 Subject: 2005-03-08 Paul Jakma * command.c: (banner_motd_file_cmd) use XSTRDUP/XFREE * vty.c: (vty_hello) suggestions from Andrew, read by line and stub out trailling non-printable characters on each line thus allowing us to specify VTY_NEWLINE to vty_out. --- lib/command.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index ca1100da..7656f680 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.38 2005/03/08 10:43:43 paul Exp $ + $Id: command.c,v 1.39 2005/03/08 15:16:57 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -3409,8 +3409,10 @@ DEFUN (banner_motd_file, "Banner from a file\n" "Filename\n") { - if (host.motdfile) free(host.motdfile); - host.motdfile = strdup(argv[0]); + if (host.motdfile) + XFREE (MTYPE_TMP, host.motdfile); + host.motdfile = XSTRDUP (MTYPE_TMP, argv[0]); + return CMD_SUCCESS; } -- cgit v1.2.3 From 9c5d8562f8d24574ba1f43881d47cbc8ffc62027 Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 8 Mar 2005 15:56:42 +0000 Subject: 2005-03-08 Paul Jakma * command.c: (cmd_describe_command_real) sign compile warning fix (cmd_complete_command_real) ditto. (config_list_cmd) Don't list hidden or deprecated commands, hiding these from tab completion is still to be done. * command.h: cmd attr enum should start at 1. --- lib/command.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 7656f680..d83ebe12 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.39 2005/03/08 15:16:57 paul Exp $ + $Id: command.c,v 1.40 2005/03/08 15:56:42 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1561,12 +1561,12 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) { static vector cmd_describe_command_real (vector vline, struct vty *vty, int *status) { - int i; + unsigned int i; vector cmd_vector; #define INIT_MATCHVEC_SIZE 10 vector matchvec; struct cmd_element *cmd_element; - int index; + unsigned int index; int ret; enum match_type match; char *command; @@ -1757,12 +1757,12 @@ cmd_lcd (char **matched) static char ** cmd_complete_command_real (vector vline, struct vty *vty, int *status) { - int i; + 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; - int index = vector_max (vline) - 1; + unsigned int index = vector_max (vline) - 1; char **match_str; struct desc *desc; vector descvec; @@ -2483,7 +2483,9 @@ DEFUN (config_list, struct cmd_element *cmd; for (i = 0; i < vector_max (cnode->cmd_vector); i++) - if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL) + 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; -- cgit v1.2.3 From 220851816a699d9977702ea2b2501d4ede76e898 Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 8 Mar 2005 16:00:12 +0000 Subject: 2005-03-08 Paul Jakma * command.c: (no_banner_motd_cmd) use XFREE. * vty.c: (vty_hello) fix the indentation and comment. --- lib/command.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index d83ebe12..cf7f46b9 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.40 2005/03/08 15:56:42 paul Exp $ + $Id: command.c,v 1.41 2005/03/08 16:00:12 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -3437,7 +3437,8 @@ DEFUN (no_banner_motd, "Strings for motd\n") { host.motd = NULL; - if (host.motdfile) free(host.motdfile); + if (host.motdfile) + XFREE (MTYPE_TMP, host.motdfile); host.motdfile = NULL; return CMD_SUCCESS; } -- cgit v1.2.3 From 9e92eeab6cc40bc65ed9b1b7950e161fd1434d48 Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 9 Mar 2005 13:39:26 +0000 Subject: 2005-03-09 Paul Jakma * command.c: Undo commit of sign warning fix and hidden command in list_cmd. Sign warning is more subtle. list_cmd on its own will be committed after. --- lib/command.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index cf7f46b9..627be328 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,6 +1,6 @@ /* - $Id: command.c,v 1.41 2005/03/08 16:00:12 paul Exp $ - + $Id: command.c,v 1.42 2005/03/09 13:39:26 paul Exp $ + Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1561,12 +1561,12 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) { static vector cmd_describe_command_real (vector vline, struct vty *vty, int *status) { - unsigned int i; + int i; vector cmd_vector; #define INIT_MATCHVEC_SIZE 10 vector matchvec; struct cmd_element *cmd_element; - unsigned int index; + int index; int ret; enum match_type match; char *command; @@ -1757,12 +1757,12 @@ cmd_lcd (char **matched) static char ** cmd_complete_command_real (vector vline, struct vty *vty, int *status) { - unsigned int i; + 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 = vector_max (vline) - 1; + int index = vector_max (vline) - 1; char **match_str; struct desc *desc; vector descvec; @@ -2483,9 +2483,7 @@ DEFUN (config_list, struct cmd_element *cmd; for (i = 0; i < vector_max (cnode->cmd_vector); i++) - if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL - && !(cmd->attr == CMD_ATTR_DEPRECATED - || cmd->attr == CMD_ATTR_HIDDEN)) + if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL) vty_out (vty, " %s%s", cmd->string, VTY_NEWLINE); return CMD_SUCCESS; -- cgit v1.2.3 From 4275b1de3a54650a81f82999c296b756ee5b5679 Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 9 Mar 2005 13:42:23 +0000 Subject: 2005-03-09 Paul Jakma * command.c: (config_list_cmd) Don't list hidden or deprecated commands, hiding these from tab completion is still to be done. --- lib/command.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 627be328..abd7106e 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.42 2005/03/09 13:39:26 paul Exp $ + $Id: command.c,v 1.43 2005/03/09 13:42:23 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -2483,7 +2483,9 @@ DEFUN (config_list, struct cmd_element *cmd; for (i = 0; i < vector_max (cnode->cmd_vector); i++) - if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL) + 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; -- cgit v1.2.3 From b89614766b083c83f6a84126a02c88311129e12d Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 14 Mar 2005 17:35:52 +0000 Subject: 2005-03-14 Paul Jakma * command.c: (sort_node) use vector_max instead of referencing (struct vector *)->max directly. Test that vector_max is > 0 before using it to calculate an index. Fixup vector loop to make main body conditional on vector slot not being empty. (cmd_cmdsize) Fixup vector loop to make main body conditional on vector slot not being empty. (cmd_filter_by_completion) ditto (cmd_filter_by_string) ditto (is_cmd_ambiguous) ditto (cmd_describe_command_real) Change index integers to unsigned. Test that vector_max is > 0 before using it to calculate an index. Return immediately with CMD_ERR_NO_MATCH if vline has no active slots. Fixup vector loop to make main body conditional on vector slot not being empty. (cmd_complete_command_real) ditto. (cmd_execute_command_strict) Fixup vector loop to be conditional on non-null slot. --- lib/command.c | 80 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 34 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index abd7106e..aae31786 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.43 2005/03/09 13:42:23 paul Exp $ + $Id: command.c,v 1.44 2005/03/14 17:35:52 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -220,14 +220,17 @@ sort_node () if ((cnode = vector_slot (cmdvec, i)) != NULL) { vector cmd_vector = cnode->cmd_vector; - qsort (cmd_vector->index, cmd_vector->max, sizeof (void *), cmp_node); + qsort (cmd_vector->index, vector_max (cmd_vector), + sizeof (void *), cmp_node); for (j = 0; j < vector_max (cmd_vector); j++) - if ((cmd_element = vector_slot (cmd_vector, j)) != NULL) + if ((cmd_element = vector_slot (cmd_vector, j)) != NULL + && vector_max (cmd_element->strvec)) { descvec = vector_slot (cmd_element->strvec, vector_max (cmd_element->strvec) - 1); - qsort (descvec->index, descvec->max, sizeof (void *), cmp_desc); + qsort (descvec->index, vector_max (descvec), + sizeof (void *), cmp_desc); } } } @@ -437,15 +440,14 @@ cmd_cmdsize (vector strvec) unsigned int i; int size = 0; vector descvec; + struct desc *desc; for (i = 0; i < vector_max (strvec); i++) + if ((descvec = vector_slot (strvec, i)) != NULL) { - descvec = vector_slot (strvec, i); - - if (vector_max (descvec) == 1) + if ((vector_max (descvec)) == 1 + && (desc = vector_slot (descvec, 0)) != NULL) { - struct desc *desc = vector_slot (descvec, 0); - if (desc->cmd == NULL || CMD_OPTION (desc->cmd)) return size; else @@ -1137,8 +1139,8 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) descvec = vector_slot (cmd_element->strvec, index); for (j = 0; j < vector_max (descvec); j++) + if ((desc = vector_slot (descvec, j))) { - desc = vector_slot (descvec, j); str = desc->cmd; if (CMD_VARARG (str)) @@ -1254,8 +1256,8 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) descvec = vector_slot (cmd_element->strvec, index); for (j = 0; j < vector_max (descvec); j++) + if ((desc = vector_slot (descvec, j))) { - desc = vector_slot (descvec, j); str = desc->cmd; if (CMD_VARARG (str)) @@ -1353,10 +1355,10 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) descvec = vector_slot (cmd_element->strvec, index); for (j = 0; j < vector_max (descvec); j++) + if ((desc = vector_slot (descvec, j))) { enum match_type ret; - desc = vector_slot (descvec, j); str = desc->cmd; switch (type) @@ -1561,18 +1563,24 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) { static vector cmd_describe_command_real (vector vline, struct vty *vty, int *status) { - int i; + unsigned int i; vector cmd_vector; #define INIT_MATCHVEC_SIZE 10 vector matchvec; struct cmd_element *cmd_element; - int index; + unsigned int index; int ret; enum match_type match; char *command; static struct desc desc_cr = { "", "" }; /* Set index. */ + if (vector_max (vline) == 0) + { + *status = CMD_ERR_NO_MATCH; + return NULL; + } + else index = vector_max (vline) - 1; /* Make copy vector of current node's command vector. */ @@ -1584,8 +1592,8 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) /* 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))) { - command = vector_slot (vline, i); match = cmd_filter_by_completion (command, cmd_vector, i); if (match == vararg_match) @@ -1595,7 +1603,8 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) unsigned int j, k; for (j = 0; j < vector_max (cmd_vector); j++) - if ((cmd_element = vector_slot (cmd_vector, j)) != NULL) + if ((cmd_element = vector_slot (cmd_vector, j)) != NULL + && (vector_max (cmd_element->strvec))) { descvec = vector_slot (cmd_element->strvec, vector_max (cmd_element->strvec) - 1); @@ -1660,8 +1669,8 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) struct desc *desc; for (j = 0; j < vector_max (descvec); j++) + if ((desc = vector_slot (descvec, j))) { - desc = vector_slot (descvec, j); string = cmd_entry_function_desc (command, desc->cmd); if (string) { @@ -1757,26 +1766,33 @@ cmd_lcd (char **matched) static char ** cmd_complete_command_real (vector vline, struct vty *vty, int *status) { - int i; + 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; - int index = vector_max (vline) - 1; + unsigned int index; char **match_str; struct desc *desc; vector descvec; char *command; int lcd; + if (vector_max (vline) == 0) + { + *status = CMD_ERR_NO_MATCH; + return NULL; + } + else + index = vector_max (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; - command = vector_slot (vline, i); - /* First try completion match, if there is exactly match return 1 */ match = cmd_filter_by_completion (command, cmd_vector, i); @@ -1803,7 +1819,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) /* Now we got into completion */ for (i = 0; i < vector_max (cmd_vector); i++) - if ((cmd_element = vector_slot (cmd_vector, i)) != NULL) + if ((cmd_element = vector_slot (cmd_vector, i))) { const char *string; vector strvec = cmd_element->strvec; @@ -1817,10 +1833,10 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) descvec = vector_slot (strvec, index); for (j = 0; j < vector_max (descvec); j++) + if ((desc = vector_slot (descvec, j))) { - desc = vector_slot (descvec, j); - - if ((string = cmd_entry_function (vector_slot (vline, index), + if ((string = + cmd_entry_function (vector_slot (vline, index), desc->cmd))) if (cmd_unique_string (matchvec, string)) vector_set (matchvec, XSTRDUP (MTYPE_TMP, string)); @@ -1963,7 +1979,8 @@ node_parent ( enum node_type node ) /* Execute command by argument vline vector. */ static int -cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd) +cmd_execute_command_real (vector vline, struct vty *vty, + struct cmd_element **cmd) { unsigned int i; unsigned int index; @@ -1981,11 +1998,10 @@ cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cm cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); for (index = 0; index < vector_max (vline); index++) + if ((command = vector_slot (vline, index))) { int ret; - command = vector_slot (vline, index); - match = cmd_filter_by_completion (command, cmd_vector, index); if (match == vararg_match) @@ -2011,10 +2027,8 @@ cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cm incomplete_count = 0; for (i = 0; i < vector_max (cmd_vector); i++) - if (vector_slot (cmd_vector,i) != NULL) + if ((cmd_element = vector_slot (cmd_vector, i))) { - cmd_element = vector_slot (cmd_vector,i); - if (match == vararg_match || index >= cmd_element->cmdsize) { matched_element = cmd_element; @@ -2085,7 +2099,6 @@ cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cm return (*matched_element->func) (matched_element, vty, argc, argv); } - int cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd, int vtysh) { @@ -2164,11 +2177,10 @@ cmd_execute_command_strict (vector vline, struct vty *vty, cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); for (index = 0; index < vector_max (vline); index++) + if ((command = vector_slot (vline, index))) { int ret; - command = vector_slot (vline, index); - match = cmd_filter_by_string (vector_slot (vline, index), cmd_vector, index); -- cgit v1.2.3 From 909a215508fd42473fcbe4f5292a59404e5473af Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 14 Mar 2005 17:41:45 +0000 Subject: 2005-03-14 Paul Jakma * command.c: (various) Fix indentation and other whitespace. --- lib/command.c | 734 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 367 insertions(+), 367 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index aae31786..4586e673 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.44 2005/03/14 17:35:52 paul Exp $ + $Id: command.c,v 1.45 2005/03/14 17:41:45 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1122,11 +1122,11 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) 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_max (v); i++) + for (i = 0; i < vector_max (v); i++) if ((cmd_element = vector_slot (v, i)) != NULL) { if (index >= vector_max (cmd_element->strvec)) @@ -1137,90 +1137,90 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) int matched = 0; descvec = vector_slot (cmd_element->strvec, index); - + for (j = 0; j < vector_max (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++; - } - } + { + 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) + 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; } } @@ -1237,18 +1237,18 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) 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_max (v); i++) + for (i = 0; i < vector_max (v); i++) if ((cmd_element = vector_slot (v, i)) != NULL) { /* If given index is bigger than max string vector of command, - set NULL*/ + set NULL */ if (index >= vector_max (cmd_element->strvec)) vector_slot (v, i) = NULL; - else + else { unsigned int j; int matched = 0; @@ -1257,78 +1257,78 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) for (j = 0; j < vector_max (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++; - } - } + { + 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++; - } - } + 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) + 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; } } @@ -1346,8 +1346,8 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) const char *matched = NULL; vector descvec; struct desc *desc; - - for (i = 0; i < vector_max (v); i++) + + for (i = 0; i < vector_max (v); i++) if ((cmd_element = vector_slot (v, i)) != NULL) { int match = 0; @@ -1356,77 +1356,77 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) for (j = 0; j < vector_max (descvec); j++) if ((desc = vector_slot (descvec, j))) - { - enum match_type ret; - - str = desc->cmd; + { + 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; + switch (type) + { + case exact_match: + if (!(CMD_OPTION (str) || CMD_VARIABLE (str)) + && strcmp (command, str) == 0) match++; - } - break; - case range_match: - if (cmd_range_match (str, command)) - { - if (matched && strcmp (matched, str) != 0) - return 1; - else - matched = str; + 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; -#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. */ - + 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; -#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. */ - + 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 extend_match: - if (CMD_OPTION (str) || CMD_VARIABLE (str)) - match++; - break; - case no_match: - default: - break; - } - } - if (! match) + break; + case no_match: + default: + break; + } + } + if (!match) vector_slot (v, i) = NULL; } return 0; @@ -1581,8 +1581,8 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) return NULL; } else - index = vector_max (vline) - 1; - + index = vector_max (vline) - 1; + /* Make copy vector of current node's command vector. */ cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); @@ -1593,47 +1593,47 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) /* 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; + { + 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_max (cmd_vector); j++) + for (j = 0; j < vector_max (cmd_vector); j++) if ((cmd_element = vector_slot (cmd_vector, j)) != NULL && (vector_max (cmd_element->strvec))) - { - descvec = vector_slot (cmd_element->strvec, - vector_max (cmd_element->strvec) - 1); - for (k = 0; k < vector_max (descvec); k++) - { - struct desc *desc = vector_slot (descvec, k); - vector_set (matchvec, desc); - } - } - - vector_set (matchvec, &desc_cr); - vector_free (cmd_vector); + { + descvec = vector_slot (cmd_element->strvec, + vector_max (cmd_element->strvec) - 1); + for (k = 0; k < vector_max (descvec); k++) + { + struct desc *desc = vector_slot (descvec, k); + vector_set (matchvec, desc); + } + } + + vector_set (matchvec, &desc_cr); + vector_free (cmd_vector); - return matchvec; - } + 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; - } - } + 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); */ @@ -1650,16 +1650,16 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) const char *string = NULL; vector strvec = cmd_element->strvec; - /* if command is NULL, index may be equal to vector_max */ + /* if command is NULL, index may be equal to vector_max */ if (command && index >= vector_max (strvec)) vector_slot (cmd_vector, i) = NULL; else { /* Check if command is completed. */ - if (command == NULL && index == vector_max (strvec)) + if (command == NULL && index == vector_max (strvec)) { string = ""; - if (! desc_unique_string (matchvec, string)) + if (!desc_unique_string (matchvec, string)) vector_set (matchvec, &desc_cr); } else @@ -1670,15 +1670,15 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) for (j = 0; j < vector_max (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); - } - } + { + string = cmd_entry_function_desc (command, desc->cmd); + if (string) + { + /* Uniqueness check */ + if (!desc_unique_string (matchvec, string)) + vector_set (matchvec, desc); + } + } } } } @@ -1687,7 +1687,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) if (vector_slot (matchvec, 0) == NULL) { vector_free (matchvec); - *status= CMD_ERR_NO_MATCH; + *status = CMD_ERR_NO_MATCH; } else *status = CMD_SUCCESS; @@ -1789,31 +1789,31 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) /* 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); + { + enum match_type match; + int ret; - /* 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; - } - */ - } + /* 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); @@ -1823,24 +1823,24 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) { const char *string; vector strvec = cmd_element->strvec; - + /* Check field length */ if (index >= vector_max (strvec)) vector_slot (cmd_vector, i) = NULL; - else + else { unsigned int j; descvec = vector_slot (strvec, index); for (j = 0; j < vector_max (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, XSTRDUP (MTYPE_TMP, string)); - } + desc->cmd))) + if (cmd_unique_string (matchvec, string)) + vector_set (matchvec, XSTRDUP (MTYPE_TMP, string)); + } } } @@ -1880,11 +1880,11 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) if (lcd) { int len = strlen (vector_slot (vline, index)); - + if (len < lcd) { char *lcdstr; - + lcdstr = XMALLOC (MTYPE_TMP, lcd + 1); memcpy (lcdstr, matchvec->index[0], lcd); lcdstr[lcd] = '\0'; @@ -1899,7 +1899,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) } vector_free (matchvec); - /* Make new matchvec. */ + /* Make new matchvec. */ matchvec = vector_init (INIT_MATCHVEC_SIZE); vector_set (matchvec, lcdstr); match_str = (char **) matchvec->index; @@ -1997,36 +1997,36 @@ cmd_execute_command_real (vector vline, struct vty *vty, /* Make copy of command elements. */ cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); - for (index = 0; index < vector_max (vline); index++) + for (index = 0; index < vector_max (vline); index++) if ((command = vector_slot (vline, index))) - { - int ret; - - match = cmd_filter_by_completion (command, cmd_vector, index); + { + int ret; - if (match == vararg_match) - break; + match = cmd_filter_by_completion (command, cmd_vector, index); - ret = is_cmd_ambiguous (command, cmd_vector, index, match); + 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; - } - } + 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_max (cmd_vector); i++) + for (i = 0; i < vector_max (cmd_vector); i++) if ((cmd_element = vector_slot (cmd_vector, i))) { if (match == vararg_match || index >= cmd_element->cmdsize) @@ -2042,12 +2042,12 @@ cmd_execute_command_real (vector vline, struct vty *vty, incomplete_count++; } } - + /* Finish of using cmd_vector. */ vector_free (cmd_vector); - /* To execute command, matched_count must be 1.*/ - if (matched_count == 0) + /* To execute command, matched_count must be 1. */ + if (matched_count == 0) { if (incomplete_count) return CMD_ERR_INCOMPLETE; @@ -2055,7 +2055,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, return CMD_ERR_NO_MATCH; } - if (matched_count > 1) + if (matched_count > 1) return CMD_ERR_AMBIGUOUS; /* Argument treatment */ @@ -2067,7 +2067,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, if (varflag) argv[argc++] = vector_slot (vline, i); else - { + { vector descvec = vector_slot (matched_element->strvec, i); if (vector_max (descvec) == 1) @@ -2158,7 +2158,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd, /* Execute command by argument readline. */ int -cmd_execute_command_strict (vector vline, struct vty *vty, +cmd_execute_command_strict (vector vline, struct vty *vty, struct cmd_element **cmd) { unsigned int i; @@ -2176,39 +2176,39 @@ cmd_execute_command_strict (vector vline, struct vty *vty, /* Make copy of command element */ cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); - for (index = 0; index < vector_max (vline); index++) + for (index = 0; index < vector_max (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; + { + int ret; + + match = cmd_filter_by_string (vector_slot (vline, index), + cmd_vector, index); - 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; - } - } + /* 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_max (cmd_vector); i++) - if (vector_slot (cmd_vector,i) != NULL) + for (i = 0; i < vector_max (cmd_vector); i++) + if (vector_slot (cmd_vector, i) != NULL) { - cmd_element = vector_slot (cmd_vector,i); + cmd_element = vector_slot (cmd_vector, i); if (match == vararg_match || index >= cmd_element->cmdsize) { @@ -2218,12 +2218,12 @@ cmd_execute_command_strict (vector vline, struct vty *vty, else incomplete_count++; } - + /* Finish of using cmd_vector. */ vector_free (cmd_vector); - /* To execute command, matched_count must be 1.*/ - if (matched_count == 0) + /* To execute command, matched_count must be 1. */ + if (matched_count == 0) { if (incomplete_count) return CMD_ERR_INCOMPLETE; @@ -2231,7 +2231,7 @@ cmd_execute_command_strict (vector vline, struct vty *vty, return CMD_ERR_NO_MATCH; } - if (matched_count > 1) + if (matched_count > 1) return CMD_ERR_AMBIGUOUS; /* Argument treatment */ @@ -2243,7 +2243,7 @@ cmd_execute_command_strict (vector vline, struct vty *vty, if (varflag) argv[argc++] = vector_slot (vline, i); else - { + { vector descvec = vector_slot (matched_element->strvec, i); if (vector_max (descvec) == 1) @@ -2252,7 +2252,7 @@ cmd_execute_command_strict (vector vline, struct vty *vty, if (CMD_VARARG (desc->cmd)) varflag = 1; - + if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd)) argv[argc++] = vector_slot (vline, i); } -- cgit v1.2.3 From 55468c86040081320f557b696e509b76ddfd6c83 Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 14 Mar 2005 20:19:01 +0000 Subject: 2005-03-14 Paul Jakma * (global) update all c files to match the lib/vector.h rename of (struct vector).active to max, and vector_max macro to vector_active. * lib/vector.h: Rename to (struct vector).max to slightly less confusing active, for the number of active slots, distinct from allocated or active-and-not-empty. Rename vector_max to vector_active for same reason. --- lib/command.c | 104 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 4586e673..64118103 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.45 2005/03/14 17:41:45 paul Exp $ + $Id: command.c,v 1.46 2005/03/14 20:19:01 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -216,20 +216,20 @@ sort_node () vector descvec; struct cmd_element *cmd_element; - for (i = 0; i < vector_max (cmdvec); i++) + 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_max (cmd_vector), + qsort (cmd_vector->index, vector_active (cmd_vector), sizeof (void *), cmp_node); - for (j = 0; j < vector_max (cmd_vector); j++) + for (j = 0; j < vector_active (cmd_vector); j++) if ((cmd_element = vector_slot (cmd_vector, j)) != NULL - && vector_max (cmd_element->strvec)) + && vector_active (cmd_element->strvec)) { descvec = vector_slot (cmd_element->strvec, - vector_max (cmd_element->strvec) - 1); - qsort (descvec->index, vector_max (descvec), + vector_active (cmd_element->strvec) - 1); + qsort (descvec->index, vector_active (descvec), sizeof (void *), cmp_desc); } } @@ -297,7 +297,7 @@ cmd_free_strvec (vector v) if (!v) return; - for (i = 0; i < vector_max (v); i++) + for (i = 0; i < vector_active (v); i++) if ((cp = vector_slot (v, i)) != NULL) XFREE (MTYPE_STRVEC, cp); @@ -442,10 +442,10 @@ cmd_cmdsize (vector strvec) vector descvec; struct desc *desc; - for (i = 0; i < vector_max (strvec); i++) + for (i = 0; i < vector_active (strvec); i++) if ((descvec = vector_slot (strvec, i)) != NULL) { - if ((vector_max (descvec)) == 1 + if ((vector_active (descvec)) == 1 && (desc = vector_slot (descvec, 0)) != NULL) { if (desc->cmd == NULL || CMD_OPTION (desc->cmd)) @@ -1126,10 +1126,10 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) match_type = no_match; /* If command and cmd_element string does not match set NULL to vector */ - for (i = 0; i < vector_max (v); i++) + for (i = 0; i < vector_active (v); i++) if ((cmd_element = vector_slot (v, i)) != NULL) { - if (index >= vector_max (cmd_element->strvec)) + if (index >= vector_active (cmd_element->strvec)) vector_slot (v, i) = NULL; else { @@ -1138,7 +1138,7 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) descvec = vector_slot (cmd_element->strvec, index); - for (j = 0; j < vector_max (descvec); j++) + for (j = 0; j < vector_active (descvec); j++) if ((desc = vector_slot (descvec, j))) { str = desc->cmd; @@ -1241,12 +1241,12 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) match_type = no_match; /* If command and cmd_element string does not match set NULL to vector */ - for (i = 0; i < vector_max (v); i++) + 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_max (cmd_element->strvec)) + if (index >= vector_active (cmd_element->strvec)) vector_slot (v, i) = NULL; else { @@ -1255,7 +1255,7 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) descvec = vector_slot (cmd_element->strvec, index); - for (j = 0; j < vector_max (descvec); j++) + for (j = 0; j < vector_active (descvec); j++) if ((desc = vector_slot (descvec, j))) { str = desc->cmd; @@ -1347,14 +1347,14 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) vector descvec; struct desc *desc; - for (i = 0; i < vector_max (v); i++) + 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_max (descvec); j++) + for (j = 0; j < vector_active (descvec); j++) if ((desc = vector_slot (descvec, j))) { enum match_type ret; @@ -1525,7 +1525,7 @@ cmd_unique_string (vector v, const char *str) unsigned int i; char *match; - for (i = 0; i < vector_max (v); i++) + for (i = 0; i < vector_active (v); i++) if ((match = vector_slot (v, i)) != NULL) if (strcmp (match, str) == 0) return 0; @@ -1540,7 +1540,7 @@ desc_unique_string (vector v, const char *str) unsigned int i; struct desc *desc; - for (i = 0; i < vector_max (v); i++) + for (i = 0; i < vector_active (v); i++) if ((desc = vector_slot (v, i)) != NULL) if (strcmp (desc->cmd, str) == 0) return 1; @@ -1575,13 +1575,13 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) static struct desc desc_cr = { "", "" }; /* Set index. */ - if (vector_max (vline) == 0) + if (vector_active (vline) == 0) { *status = CMD_ERR_NO_MATCH; return NULL; } else - index = vector_max (vline) - 1; + index = vector_active (vline) - 1; /* Make copy vector of current node's command vector. */ cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); @@ -1602,13 +1602,13 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) vector descvec; unsigned int j, k; - for (j = 0; j < vector_max (cmd_vector); j++) + for (j = 0; j < vector_active (cmd_vector); j++) if ((cmd_element = vector_slot (cmd_vector, j)) != NULL - && (vector_max (cmd_element->strvec))) + && (vector_active (cmd_element->strvec))) { descvec = vector_slot (cmd_element->strvec, - vector_max (cmd_element->strvec) - 1); - for (k = 0; k < vector_max (descvec); k++) + 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); @@ -1644,19 +1644,19 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) match = cmd_filter_by_completion (command, cmd_vector, index); /* Make description vector. */ - for (i = 0; i < vector_max (cmd_vector); i++) + 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_max */ - if (command && index >= vector_max (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_max (strvec)) + if (command == NULL && index == vector_active (strvec)) { string = ""; if (!desc_unique_string (matchvec, string)) @@ -1668,7 +1668,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) vector descvec = vector_slot (strvec, index); struct desc *desc; - for (j = 0; j < vector_max (descvec); j++) + for (j = 0; j < vector_active (descvec); j++) if ((desc = vector_slot (descvec, j))) { string = cmd_entry_function_desc (command, desc->cmd); @@ -1712,7 +1712,7 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) shifted_vline = vector_init (vector_count(vline)); /* use memcpy? */ - for (index = 1; index < vector_max (vline); index++) + for (index = 1; index < vector_active (vline); index++) { vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); } @@ -1778,13 +1778,13 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) char *command; int lcd; - if (vector_max (vline) == 0) + if (vector_active (vline) == 0) { *status = CMD_ERR_NO_MATCH; return NULL; } else - index = vector_max (vline) - 1; + index = vector_active (vline) - 1; /* First, filter by preceeding command string */ for (i = 0; i < index; i++) @@ -1818,21 +1818,21 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) matchvec = vector_init (INIT_MATCHVEC_SIZE); /* Now we got into completion */ - for (i = 0; i < vector_max (cmd_vector); i++) + 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_max (strvec)) + 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_max (descvec); j++) + for (j = 0; j < vector_active (descvec); j++) if ((desc = vector_slot (descvec, j))) { if ((string = @@ -1892,7 +1892,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) /* match_str = (char **) &lcdstr; */ /* Free matchvec. */ - for (i = 0; i < vector_max (matchvec); i++) + for (i = 0; i < vector_active (matchvec); i++) { if (vector_slot (matchvec, i)) XFREE (MTYPE_TMP, vector_slot (matchvec, i)); @@ -1934,7 +1934,7 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) shifted_vline = vector_init (vector_count(vline)); /* use memcpy? */ - for (index = 1; index < vector_max (vline); index++) + for (index = 1; index < vector_active (vline); index++) { vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); } @@ -1997,7 +1997,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, /* Make copy of command elements. */ cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); - for (index = 0; index < vector_max (vline); index++) + for (index = 0; index < vector_active (vline); index++) if ((command = vector_slot (vline, index))) { int ret; @@ -2026,7 +2026,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, matched_count = 0; incomplete_count = 0; - for (i = 0; i < vector_max (cmd_vector); i++) + 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) @@ -2062,7 +2062,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, varflag = 0; argc = 0; - for (i = 0; i < vector_max (vline); i++) + for (i = 0; i < vector_active (vline); i++) { if (varflag) argv[argc++] = vector_slot (vline, i); @@ -2070,7 +2070,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, { vector descvec = vector_slot (matched_element->strvec, i); - if (vector_max (descvec) == 1) + if (vector_active (descvec) == 1) { struct desc *desc = vector_slot (descvec, 0); @@ -2117,7 +2117,7 @@ cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd, shifted_vline = vector_init (vector_count(vline)); /* use memcpy? */ - for (index = 1; index < vector_max (vline); index++) + for (index = 1; index < vector_active (vline); index++) { vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); } @@ -2176,7 +2176,7 @@ cmd_execute_command_strict (vector vline, struct vty *vty, /* Make copy of command element */ cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); - for (index = 0; index < vector_max (vline); index++) + for (index = 0; index < vector_active (vline); index++) if ((command = vector_slot (vline, index))) { int ret; @@ -2205,7 +2205,7 @@ cmd_execute_command_strict (vector vline, struct vty *vty, matched_element = NULL; matched_count = 0; incomplete_count = 0; - for (i = 0; i < vector_max (cmd_vector); i++) + for (i = 0; i < vector_active (cmd_vector); i++) if (vector_slot (cmd_vector, i) != NULL) { cmd_element = vector_slot (cmd_vector, i); @@ -2238,7 +2238,7 @@ cmd_execute_command_strict (vector vline, struct vty *vty, varflag = 0; argc = 0; - for (i = 0; i < vector_max (vline); i++) + for (i = 0; i < vector_active (vline); i++) { if (varflag) argv[argc++] = vector_slot (vline, i); @@ -2246,7 +2246,7 @@ cmd_execute_command_strict (vector vline, struct vty *vty, { vector descvec = vector_slot (matched_element->strvec, i); - if (vector_max (descvec) == 1) + if (vector_active (descvec) == 1) { struct desc *desc = vector_slot (descvec, 0); @@ -2494,7 +2494,7 @@ DEFUN (config_list, struct cmd_node *cnode = vector_slot (cmdvec, vty->node); struct cmd_element *cmd; - for (i = 0; i < vector_max (cnode->cmd_vector); i++) + 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)) @@ -2558,7 +2558,7 @@ DEFUN (config_write_file, vty_time_print (file_vty, 1); vty_out (file_vty, "!\n"); - for (i = 0; i < vector_max (cmdvec); i++) + for (i = 0; i < vector_active (cmdvec); i++) if ((node = vector_slot (cmdvec, i)) && node->func) { if ((*node->func) (file_vty)) @@ -2652,7 +2652,7 @@ DEFUN (config_write_terminal, if (vty->type == VTY_SHELL_SERV) { - for (i = 0; i < vector_max (cmdvec); i++) + for (i = 0; i < vector_active (cmdvec); i++) if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh) { if ((*node->func) (vty)) @@ -2665,7 +2665,7 @@ DEFUN (config_write_terminal, VTY_NEWLINE); vty_out (vty, "!%s", VTY_NEWLINE); - for (i = 0; i < vector_max (cmdvec); i++) + for (i = 0; i < vector_active (cmdvec); i++) if ((node = vector_slot (cmdvec, i)) && node->func) { if ((*node->func) (vty)) -- cgit v1.2.3 From 354d119a6569b2c6335ae9309e4606e5cccedb6a Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 25 Apr 2005 16:26:42 +0000 Subject: 2005-04-25 Paul Jakma * workqueue.{c,h}: Helper API for setting up and running queues via background threads. * command.c: install the 'show workqueues' command * memtypes.c: Add work queue mtypes, and a rib-queue type for a zebra rib work queue. * memtypes.h: Updated to match memtypes.c * Makefile.am: Add new workqueue files to build. --- lib/command.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 64118103..9b5f75f2 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.46 2005/03/14 20:19:01 paul Exp $ + $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 @@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */ #include "vector.h" #include "vty.h" #include "command.h" +#include "workqueue.h" /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -3578,8 +3579,10 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &service_terminal_length_cmd); install_element (CONFIG_NODE, &no_service_terminal_length_cmd); - install_element(VIEW_NODE, &show_thread_cpu_cmd); - install_element(ENABLE_NODE, &show_thread_cpu_cmd); + install_element (VIEW_NODE, &show_thread_cpu_cmd); + install_element (ENABLE_NODE, &show_thread_cpu_cmd); + install_element (VIEW_NODE, &show_work_queues_cmd); + install_element (ENABLE_NODE, &show_work_queues_cmd); } srand(time(NULL)); } -- cgit v1.2.3 From 8cc4198f9fabe5f10f5a773de1503d82f33a01fb Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 6 May 2005 21:25:49 +0000 Subject: 2005-05-06 Paul Jakma * (general) extern and static'ification of functions in code and header. Cleanup any definitions with unspecified arguments. Add casts for callback assignments where the callback is defined, typically, as passing void *, but the function being assigned has some other pointer type defined as its argument, as gcc complains about casts from void * to X* via function arguments. Fix some old K&R style function argument definitions. Add noreturn gcc attribute to some functions, as appropriate. Add unused gcc attribute to some functions (eg ones meant to help while debugging) Add guard defines to headers which were missing them. * command.c: (install_node) add const qualifier, still doesnt shut up the warning though, because of the double pointer. (cmp_node) ditto * keychain.c: (key_str2time) Add GET_LONG_RANGE() macro, derived fromn vty.h ones to fix some of the (long) < 0 warnings. * thread.c: (various) use thread_empty (cpu_record_hash_key) should cast to uintptr_t, a stdint.h type * vty.h: Add VTY_GET_IPV4_ADDRESS and VTY_GET_IPV4_PREFIX so they removed from ospfd/ospf_vty.h * zebra.h: Move definition of ZEBRA_PORT to here, to remove dependence of lib on zebra/zserv.h --- lib/command.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 9b5f75f2..83b8a956 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.47 2005/04/25 16:26:42 paul Exp $ + $Id: command.c,v 1.48 2005/05/06 21:25:49 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -193,8 +193,8 @@ install_node (struct cmd_node *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; + const struct cmd_element *a = *(struct cmd_element **)p; + const struct cmd_element *b = *(struct cmd_element **)q; return strcmp (a->string, b->string); } @@ -202,8 +202,8 @@ cmp_node (const void *p, const void *q) static int cmp_desc (const void *p, const void *q) { - struct desc *a = *(struct desc **)p; - struct desc *b = *(struct desc **)q; + const struct desc *a = *(struct desc **)p; + const struct desc *b = *(struct desc **)q; return strcmp (a->cmd, b->cmd); } -- cgit v1.2.3 From 1e83659026e5b9c5876273c83e86fd229dd98c88 Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 22 Aug 2005 22:39:56 +0000 Subject: 2005-08-22 Hugo Santos * command.h: (enum node_type) Add BGP_IPV6M_NODE * command.c: (node_parent) Handle BGP_IPV6M_NODE node (config_exit, config_end) ditto * vty.c: (vty_end_config) Handle BGP_IPV6M_NODE node --- lib/command.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 83b8a956..f6423595 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.48 2005/05/06 21:25:49 paul Exp $ + $Id: command.c,v 1.49 2005/08/22 22:39:56 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1966,6 +1966,7 @@ node_parent ( enum node_type node ) case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: ret = BGP_NODE; break; case KEYCHAIN_KEY_NODE: @@ -2391,6 +2392,7 @@ DEFUN (config_exit, case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: vty->node = BGP_NODE; break; case KEYCHAIN_KEY_NODE: @@ -2430,6 +2432,7 @@ DEFUN (config_end, case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: case RMAP_NODE: case OSPF_NODE: case OSPF6_NODE: -- cgit v1.2.3 From eb820afe3b53321624317cfa6b426ecae1392f24 Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 5 Sep 2005 11:54:13 +0000 Subject: 2005-09-05 Paul Jakma * command.c: (install_element) be more robust. Eg, cmd_init need not have been called, some applications may use other library subsystems, which call install_element, without the application wanting commands and hence not calling cmd_init. --- lib/command.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index f6423595..2b7ca9ad 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.49 2005/08/22 22:39:56 paul Exp $ + $Id: command.c,v 1.50 2005/09/05 11:54:13 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */ /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ -vector cmdvec; +vector cmdvec = NULL; /* Host information structure. */ struct host host; @@ -475,7 +475,11 @@ void install_element (enum node_type ntype, struct cmd_element *cmd) { struct cmd_node *cnode; - + + /* cmd_init hasn't been called */ + if (!cmdvec) + return; + cnode = vector_slot (cmdvec, ntype); if (cnode == NULL) -- cgit v1.2.3 From 05865c90ab0bc95b8ca1a54c794809891666cdce Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 26 Oct 2005 05:49:54 +0000 Subject: 2005-10-26 Paul Jakma * command.c: Use MTYPE_HOST, MTYPE_STRVEC. Some other fixups, including fixing some likely leaks in config_write_file. * vty.c: memory macro usage fixes. (vty_read_config) fix leak where relative config file is specified. --- lib/command.c | 114 +++++++++++++++++++++++++++------------------------------- 1 file changed, 52 insertions(+), 62 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 2b7ca9ad..ac3516c3 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.50 2005/09/05 11:54:13 paul Exp $ + $Id: command.c,v 1.51 2005/10/26 05:49:54 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1890,7 +1890,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) { char *lcdstr; - lcdstr = XMALLOC (MTYPE_TMP, lcd + 1); + lcdstr = XMALLOC (MTYPE_STRVEC, lcd + 1); memcpy (lcdstr, matchvec->index[0], lcd); lcdstr[lcd] = '\0'; @@ -1900,7 +1900,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) for (i = 0; i < vector_active (matchvec); i++) { if (vector_slot (matchvec, i)) - XFREE (MTYPE_TMP, vector_slot (matchvec, i)); + XFREE (MTYPE_STRVEC, vector_slot (matchvec, i)); } vector_free (matchvec); @@ -2524,6 +2524,7 @@ DEFUN (config_write_file, char *config_file; char *config_file_tmp = NULL; char *config_file_sav = NULL; + int ret = CMD_WARNING; struct vty *file_vty; /* Check and see if we are operating under vtysh configuration */ @@ -2537,12 +2538,13 @@ DEFUN (config_write_file, /* Get filename. */ config_file = host.config; - config_file_sav = malloc (strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1); + config_file_sav = + XMALLOC (MTYPE_TMP, strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1); strcpy (config_file_sav, config_file); strcat (config_file_sav, CONF_BACKUP_EXT); - config_file_tmp = malloc (strlen (config_file) + 8); + config_file_tmp = XMALLOC (MTYPE_TMP, strlen (config_file) + 8); sprintf (config_file_tmp, "%s.XXXXXX", config_file); /* Open file to configuration write. */ @@ -2551,9 +2553,7 @@ DEFUN (config_write_file, { vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp, VTY_NEWLINE); - free (config_file_tmp); - free (config_file_sav); - return CMD_WARNING; + goto finished; } /* Make vty for configuration file. */ @@ -2579,55 +2579,45 @@ DEFUN (config_write_file, { vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav, VTY_NEWLINE); - free (config_file_sav); - free (config_file_tmp); - unlink (config_file_tmp); - return CMD_WARNING; + goto finished; } if (link (config_file, config_file_sav) != 0) { vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav, VTY_NEWLINE); - free (config_file_sav); - free (config_file_tmp); - unlink (config_file_tmp); - return CMD_WARNING; + goto finished; } sync (); if (unlink (config_file) != 0) { vty_out (vty, "Can't unlink configuration file %s.%s", config_file, VTY_NEWLINE); - free (config_file_sav); - free (config_file_tmp); - unlink (config_file_tmp); - return CMD_WARNING; + goto finished; } if (link (config_file_tmp, config_file) != 0) { vty_out (vty, "Can't save configuration file %s.%s", config_file, VTY_NEWLINE); - free (config_file_sav); - free (config_file_tmp); - unlink (config_file_tmp); - return CMD_WARNING; + goto finished; } - unlink (config_file_tmp); sync (); - free (config_file_sav); - free (config_file_tmp); - if (chmod (config_file, CONFIGFILE_MASK) != 0) { vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s", config_file, safe_strerror(errno), errno, VTY_NEWLINE); - return CMD_WARNING; + goto finished; } vty_out (vty, "Configuration saved to %s%s", config_file, VTY_NEWLINE); - return CMD_SUCCESS; + ret = CMD_SUCCESS; + +finished: + unlink (config_file_tmp); + XFREE (MTYPE_TMP, config_file_tmp); + XFREE (MTYPE_TMP, config_file_sav); + return ret; } ALIAS (config_write_file, @@ -2739,9 +2729,9 @@ DEFUN (config_hostname, } if (host.name) - XFREE (0, host.name); + XFREE (MTYPE_HOST, host.name); - host.name = strdup (argv[0]); + host.name = XSTRDUP (MTYPE_HOST, argv[0]); return CMD_SUCCESS; } @@ -2753,7 +2743,7 @@ DEFUN (config_no_hostname, "Host name of this router\n") { if (host.name) - XFREE (0, host.name); + XFREE (MTYPE_HOST, host.name); host.name = NULL; return CMD_SUCCESS; } @@ -2778,11 +2768,11 @@ DEFUN (config_password, password_cmd, if (*argv[0] == '8') { if (host.password) - XFREE (0, host.password); + XFREE (MTYPE_HOST, host.password); host.password = NULL; if (host.password_encrypt) - XFREE (0, host.password_encrypt); - host.password_encrypt = XSTRDUP (0, strdup (argv[1])); + XFREE (MTYPE_HOST, host.password_encrypt); + host.password_encrypt = XSTRDUP (MTYPE_HOST, argv[1]); return CMD_SUCCESS; } else @@ -2800,17 +2790,17 @@ DEFUN (config_password, password_cmd, } if (host.password) - XFREE (0, host.password); + XFREE (MTYPE_HOST, host.password); host.password = NULL; if (host.encrypt) { if (host.password_encrypt) - XFREE (0, host.password_encrypt); - host.password_encrypt = XSTRDUP (0, zencrypt (argv[0])); + XFREE (MTYPE_HOST, host.password_encrypt); + host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[0])); } else - host.password = XSTRDUP (0, argv[0]); + host.password = XSTRDUP (MTYPE_HOST, argv[0]); return CMD_SUCCESS; } @@ -2842,12 +2832,12 @@ DEFUN (config_enable_password, enable_password_cmd, if (*argv[0] == '8') { if (host.enable) - XFREE (0, host.enable); + XFREE (MTYPE_HOST, host.enable); host.enable = NULL; if (host.enable_encrypt) - XFREE (0, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (0, argv[1]); + XFREE (MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = XSTRDUP (MTYPE_HOST, argv[1]); return CMD_SUCCESS; } @@ -2866,18 +2856,18 @@ DEFUN (config_enable_password, enable_password_cmd, } if (host.enable) - XFREE (0, host.enable); + XFREE (MTYPE_HOST, host.enable); host.enable = NULL; /* Plain password input. */ if (host.encrypt) { if (host.enable_encrypt) - XFREE (0, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (0, zencrypt (argv[0])); + XFREE (MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[0])); } else - host.enable = XSTRDUP (0, argv[0]); + host.enable = XSTRDUP (MTYPE_HOST, argv[0]); return CMD_SUCCESS; } @@ -2897,11 +2887,11 @@ DEFUN (no_config_enable_password, no_enable_password_cmd, "Assign the privileged level password\n") { if (host.enable) - XFREE (0, host.enable); + XFREE (MTYPE_HOST, host.enable); host.enable = NULL; if (host.enable_encrypt) - XFREE (0, host.enable_encrypt); + XFREE (MTYPE_HOST, host.enable_encrypt); host.enable_encrypt = NULL; return CMD_SUCCESS; @@ -2921,14 +2911,14 @@ DEFUN (service_password_encrypt, if (host.password) { if (host.password_encrypt) - XFREE (0, host.password_encrypt); - host.password_encrypt = XSTRDUP (0, zencrypt (host.password)); + XFREE (MTYPE_HOST, host.password_encrypt); + host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.password)); } if (host.enable) { if (host.enable_encrypt) - XFREE (0, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (0, zencrypt (host.enable)); + XFREE (MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.enable)); } return CMD_SUCCESS; @@ -2947,11 +2937,11 @@ DEFUN (no_service_password_encrypt, host.encrypt = 0; if (host.password_encrypt) - XFREE (0, host.password_encrypt); + XFREE (MTYPE_HOST, host.password_encrypt); host.password_encrypt = NULL; if (host.enable_encrypt) - XFREE (0, host.enable_encrypt); + XFREE (MTYPE_HOST, host.enable_encrypt); host.enable_encrypt = NULL; return CMD_SUCCESS; @@ -3220,9 +3210,9 @@ set_log_file(struct vty *vty, const char *fname, int loglevel) } if (host.logfile) - XFREE (MTYPE_TMP, host.logfile); + XFREE (MTYPE_HOST, host.logfile); - host.logfile = XSTRDUP (MTYPE_TMP, fname); + host.logfile = XSTRDUP (MTYPE_HOST, fname); return CMD_SUCCESS; } @@ -3263,7 +3253,7 @@ DEFUN (no_config_log_file, zlog_reset_file (NULL); if (host.logfile) - XFREE (MTYPE_TMP, host.logfile); + XFREE (MTYPE_HOST, host.logfile); host.logfile = NULL; @@ -3432,8 +3422,8 @@ DEFUN (banner_motd_file, "Filename\n") { if (host.motdfile) - XFREE (MTYPE_TMP, host.motdfile); - host.motdfile = XSTRDUP (MTYPE_TMP, argv[0]); + XFREE (MTYPE_HOST, host.motdfile); + host.motdfile = XSTRDUP (MTYPE_HOST, argv[0]); return CMD_SUCCESS; } @@ -3458,7 +3448,7 @@ DEFUN (no_banner_motd, { host.motd = NULL; if (host.motdfile) - XFREE (MTYPE_TMP, host.motdfile); + XFREE (MTYPE_HOST, host.motdfile); host.motdfile = NULL; return CMD_SUCCESS; } @@ -3467,7 +3457,7 @@ DEFUN (no_banner_motd, void host_config_set (char *filename) { - host.config = strdup (filename); + host.config = XSTRDUP (MTYPE_HOST, filename); } void -- cgit v1.2.3 From 149202fd98596d43aba8f717cb508774b96b2e12 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 12 May 2006 23:19:37 +0000 Subject: [lib] CID #37, fix error case leak, cmd_complete_command_real 2006-05-12 Paul Jakma * command.c: (cmd_complete_command_real) Fix leak of cmd_vector in error case, Coverity CID #37. --- lib/command.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index ac3516c3..1c277b38 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.51 2005/10/26 05:49:54 paul Exp $ + $Id: command.c,v 1.52 2006/05/12 23:19:37 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1785,6 +1785,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) if (vector_active (vline) == 0) { + vector_free (cmd_vector); *status = CMD_ERR_NO_MATCH; return NULL; } -- cgit v1.2.3 From 56544a59d15fc36954726d72fec02795002750fb Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 12 May 2006 23:24:09 +0000 Subject: [lib] CID #55, fix return of freed pointer, cmd_describe_command_real 2006-05-12 Paul Jakma * command.c: (cmd_describe_command_real) Fix return of freed pointer when no-match, CID #55. --- lib/command.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 1c277b38..07297eff 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.52 2006/05/12 23:19:37 paul Exp $ + $Id: command.c,v 1.53 2006/05/12 23:24:09 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1693,10 +1693,10 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) { vector_free (matchvec); *status = CMD_ERR_NO_MATCH; + return NULL; } - else - *status = CMD_SUCCESS; + *status = CMD_SUCCESS; return matchvec; } -- cgit v1.2.3 From 50831caf3d37ac4971d173102d91f3634d2b6f70 Mon Sep 17 00:00:00 2001 From: paul Date: Thu, 15 Jun 2006 12:25:55 +0000 Subject: [lib] Fix vector leak in error path in command.c, CID #38 2006-06-15 Paul Jakma * command.c: (cmd_describe_command_real) Fix leak, CID #38. --- lib/command.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index 07297eff..b8d60f2e 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.53 2006/05/12 23:24:09 paul Exp $ + $Id: command.c,v 1.54 2006/06/15 12:25:55 paul Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -1629,12 +1629,14 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1) { vector_free (cmd_vector); + vector_free (matchvec); *status = CMD_ERR_AMBIGUOUS; return NULL; } else if (ret == 2) { vector_free (cmd_vector); + vector_free (matchvec); *status = CMD_ERR_NO_MATCH; return NULL; } -- cgit v1.2.3 From 870a1b5e5b7a25411fdb9c66d3a90ff463d8535e Mon Sep 17 00:00:00 2001 From: ajs Date: Sat, 28 Apr 2007 22:14:10 +0000 Subject: [logging] Add new "log timestamp precision" command for subsecond timestamps 2007-04-28 Andrew J. Schorr * command.c: (config_write_host) Save "log timestamp precision" if not default value. (show_logging) Show configured timestamp precision. (config_log_timestamp_precision) Enable configuration of timestamp precision. (no_config_log_timestamp_precision) Restore default timestamp precision. (cmd_init) Install new timestamp precision commands. * log.h: (struct zlog) New timestamp_precision field. (quagga_timestamp) New function to generate a timestamp with the desired precision. (struct timestamp_control) Declare a structure for use in avoiding repeated duplicate calls to quagga_timestamp. * log.c: (quagga_timestamp) New function to generate a timestamp of the desired precision. (time_print) Call quagga_timestamp if the time hasn't already been calculated. (vzlog) Initialize a timestamp_control structure and pass it to time_print and vty_log. (zlog_backtrace) Fix 64-bit problem: cannot print size_t with %u. * vty.h: Must now include "log.h". (vty_log) Takes an additional struct timestamp_control argument. * vty.c: (vty_log_out) Use new struct timestamp_control and new quagga_timestamp function to print timestamps of the desired precision. (vty_time_print) Use new quagga_timestamp function. (vty_log) Accept new struct timestamp_control argument and pass it down to vty_log_out. --- lib/command.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'lib/command.c') diff --git a/lib/command.c b/lib/command.c index b8d60f2e..270bf0d3 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,5 +1,5 @@ /* - $Id: command.c,v 1.54 2006/06/15 12:25:55 paul Exp $ + $Id: command.c,v 1.55 2007/04/28 22:14:10 ajs Exp $ Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro @@ -594,6 +594,10 @@ config_write_host (struct vty *vty) if (zlog_default->record_priority == 1) vty_out (vty, "log record-priority%s", VTY_NEWLINE); + if (zlog_default->timestamp_precision > 0) + vty_out (vty, "log timestamp precision %d%s", + zlog_default->timestamp_precision, VTY_NEWLINE); + if (host.advanced) vty_out (vty, "service advanced-vty%s", VTY_NEWLINE); @@ -3092,6 +3096,8 @@ DEFUN (show_logging, zlog_proto_names[zl->protocol], VTY_NEWLINE); vty_out (vty, "Record priority: %s%s", (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE); + vty_out (vty, "Timestamp precision: %d%s", + zl->timestamp_precision, VTY_NEWLINE); return CMD_SUCCESS; } @@ -3416,6 +3422,37 @@ DEFUN (no_config_log_record_priority, return CMD_SUCCESS; } +DEFUN (config_log_timestamp_precision, + config_log_timestamp_precision_cmd, + "log timestamp precision <0-6>", + "Logging control\n" + "Timestamp configuration\n" + "Set the timestamp precision\n" + "Number of subsecond digits\n") +{ + if (argc != 1) + { + vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE); + return CMD_WARNING; + } + + VTY_GET_INTEGER_RANGE("Timestamp Precision", + zlog_default->timestamp_precision, argv[0], 0, 6); + return CMD_SUCCESS; +} + +DEFUN (no_config_log_timestamp_precision, + no_config_log_timestamp_precision_cmd, + "no log timestamp precision", + NO_STR + "Logging control\n" + "Timestamp configuration\n" + "Reset the timestamp precision to the default value of 0\n") +{ + zlog_default->timestamp_precision = 0 ; + return CMD_SUCCESS; +} + DEFUN (banner_motd_file, banner_motd_file_cmd, "banner motd file [FILE]", @@ -3571,6 +3608,8 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &no_config_log_trap_cmd); install_element (CONFIG_NODE, &config_log_record_priority_cmd); install_element (CONFIG_NODE, &no_config_log_record_priority_cmd); + install_element (CONFIG_NODE, &config_log_timestamp_precision_cmd); + install_element (CONFIG_NODE, &no_config_log_timestamp_precision_cmd); install_element (CONFIG_NODE, &service_password_encrypt_cmd); install_element (CONFIG_NODE, &no_service_password_encrypt_cmd); install_element (CONFIG_NODE, &banner_motd_default_cmd); -- cgit v1.2.3