📄 command.c
字号:
/* Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro IshiguroThis file is part of GNU Zebra. GNU Zebra is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as publishedby the Free Software Foundation; either version 2, or (at youroption) any later version.GNU Zebra is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Zebra; see the file COPYING. If not, write to theFree Software Foundation, Inc., 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */#include <zebra.h>#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. */voidinstall_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 (). */intcmp_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);}intcmp_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. */voidsort_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. */vectorcmd_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. */voidcmd_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. */vectorcmd_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. */intcmd_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. */voidinstall_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";voidto64(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);}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. */intconfig_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"); 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); 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. */vectorcmd_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 */intcmd_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -