Annotation of embedaddon/quagga/lib/command.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    Command interpreter routine for virtual terminal [aka TeletYpe]
        !             3:    Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
        !             4: 
        !             5: This file is part of GNU Zebra.
        !             6:  
        !             7: GNU Zebra is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published
        !             9: by the Free Software Foundation; either version 2, or (at your
        !            10: option) any later version.
        !            11: 
        !            12: GNU Zebra is distributed in the hope that it will be useful, but
        !            13: WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15: General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU Zebra; see the file COPYING.  If not, write to the
        !            19: Free Software Foundation, Inc., 59 Temple Place - Suite 330,
        !            20: Boston, MA 02111-1307, USA.  */
        !            21: 
        !            22: #include <zebra.h>
        !            23: 
        !            24: 
        !            25: #include "memory.h"
        !            26: #include "log.h"
        !            27: #include <lib/version.h>
        !            28: #include "thread.h"
        !            29: #include "vector.h"
        !            30: #include "vty.h"
        !            31: #include "command.h"
        !            32: #include "workqueue.h"
        !            33: 
        !            34: /* Command vector which includes some level of command lists. Normally
        !            35:    each daemon maintains each own cmdvec. */
        !            36: vector cmdvec = NULL;
        !            37: 
        !            38: struct desc desc_cr;
        !            39: char *command_cr = NULL;
        !            40: 
        !            41: /* Host information structure. */
        !            42: struct host host;
        !            43: 
        !            44: /* Standard command node structures. */
        !            45: static struct cmd_node auth_node =
        !            46: {
        !            47:   AUTH_NODE,
        !            48:   "Password: ",
        !            49: };
        !            50: 
        !            51: static struct cmd_node view_node =
        !            52: {
        !            53:   VIEW_NODE,
        !            54:   "%s> ",
        !            55: };
        !            56: 
        !            57: static struct cmd_node restricted_node =
        !            58: {
        !            59:   RESTRICTED_NODE,
        !            60:   "%s$ ",
        !            61: };
        !            62: 
        !            63: static struct cmd_node auth_enable_node =
        !            64: {
        !            65:   AUTH_ENABLE_NODE,
        !            66:   "Password: ",
        !            67: };
        !            68: 
        !            69: static struct cmd_node enable_node =
        !            70: {
        !            71:   ENABLE_NODE,
        !            72:   "%s# ",
        !            73: };
        !            74: 
        !            75: static struct cmd_node config_node =
        !            76: {
        !            77:   CONFIG_NODE,
        !            78:   "%s(config)# ",
        !            79:   1
        !            80: };
        !            81: 
        !            82: /* Default motd string. */
        !            83: static const char *default_motd =
        !            84: "\r\n\
        !            85: Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
        !            86: " QUAGGA_COPYRIGHT "\r\n\
        !            87: \r\n";
        !            88: 
        !            89: 
        !            90: static const struct facility_map {
        !            91:   int facility;
        !            92:   const char *name;
        !            93:   size_t match;
        !            94: } syslog_facilities[] = 
        !            95:   {
        !            96:     { LOG_KERN, "kern", 1 },
        !            97:     { LOG_USER, "user", 2 },
        !            98:     { LOG_MAIL, "mail", 1 },
        !            99:     { LOG_DAEMON, "daemon", 1 },
        !           100:     { LOG_AUTH, "auth", 1 },
        !           101:     { LOG_SYSLOG, "syslog", 1 },
        !           102:     { LOG_LPR, "lpr", 2 },
        !           103:     { LOG_NEWS, "news", 1 },
        !           104:     { LOG_UUCP, "uucp", 2 },
        !           105:     { LOG_CRON, "cron", 1 },
        !           106: #ifdef LOG_FTP
        !           107:     { LOG_FTP, "ftp", 1 },
        !           108: #endif
        !           109:     { LOG_LOCAL0, "local0", 6 },
        !           110:     { LOG_LOCAL1, "local1", 6 },
        !           111:     { LOG_LOCAL2, "local2", 6 },
        !           112:     { LOG_LOCAL3, "local3", 6 },
        !           113:     { LOG_LOCAL4, "local4", 6 },
        !           114:     { LOG_LOCAL5, "local5", 6 },
        !           115:     { LOG_LOCAL6, "local6", 6 },
        !           116:     { LOG_LOCAL7, "local7", 6 },
        !           117:     { 0, NULL, 0 },
        !           118:   };
        !           119: 
        !           120: static const char *
        !           121: facility_name(int facility)
        !           122: {
        !           123:   const struct facility_map *fm;
        !           124: 
        !           125:   for (fm = syslog_facilities; fm->name; fm++)
        !           126:     if (fm->facility == facility)
        !           127:       return fm->name;
        !           128:   return "";
        !           129: }
        !           130: 
        !           131: static int
        !           132: facility_match(const char *str)
        !           133: {
        !           134:   const struct facility_map *fm;
        !           135: 
        !           136:   for (fm = syslog_facilities; fm->name; fm++)
        !           137:     if (!strncmp(str,fm->name,fm->match))
        !           138:       return fm->facility;
        !           139:   return -1;
        !           140: }
        !           141: 
        !           142: static int
        !           143: level_match(const char *s)
        !           144: {
        !           145:   int level ;
        !           146:   
        !           147:   for ( level = 0 ; zlog_priority [level] != NULL ; level ++ )
        !           148:     if (!strncmp (s, zlog_priority[level], 2))
        !           149:       return level;
        !           150:   return ZLOG_DISABLED;
        !           151: }
        !           152: 
        !           153: /* This is called from main when a daemon is invoked with -v or --version. */
        !           154: void
        !           155: print_version (const char *progname)
        !           156: {
        !           157:   printf ("%s version %s\n", progname, QUAGGA_VERSION);
        !           158:   printf ("%s\n", QUAGGA_COPYRIGHT);
        !           159: }
        !           160: 
        !           161: 
        !           162: /* Utility function to concatenate argv argument into a single string
        !           163:    with inserting ' ' character between each argument.  */
        !           164: char *
        !           165: argv_concat (const char **argv, int argc, int shift)
        !           166: {
        !           167:   int i;
        !           168:   size_t len;
        !           169:   char *str;
        !           170:   char *p;
        !           171: 
        !           172:   len = 0;
        !           173:   for (i = shift; i < argc; i++)
        !           174:     len += strlen(argv[i])+1;
        !           175:   if (!len)
        !           176:     return NULL;
        !           177:   p = str = XMALLOC(MTYPE_TMP, len);
        !           178:   for (i = shift; i < argc; i++)
        !           179:     {
        !           180:       size_t arglen;
        !           181:       memcpy(p, argv[i], (arglen = strlen(argv[i])));
        !           182:       p += arglen;
        !           183:       *p++ = ' ';
        !           184:     }
        !           185:   *(p-1) = '\0';
        !           186:   return str;
        !           187: }
        !           188: 
        !           189: /* Install top node of command vector. */
        !           190: void
        !           191: install_node (struct cmd_node *node, 
        !           192:              int (*func) (struct vty *))
        !           193: {
        !           194:   vector_set_index (cmdvec, node->node, node);
        !           195:   node->func = func;
        !           196:   node->cmd_vector = vector_init (VECTOR_MIN_SIZE);
        !           197: }
        !           198: 
        !           199: /* Compare two command's string.  Used in sort_node (). */
        !           200: static int
        !           201: cmp_node (const void *p, const void *q)
        !           202: {
        !           203:   const struct cmd_element *a = *(struct cmd_element * const *)p;
        !           204:   const struct cmd_element *b = *(struct cmd_element * const *)q;
        !           205: 
        !           206:   return strcmp (a->string, b->string);
        !           207: }
        !           208: 
        !           209: static int
        !           210: cmp_desc (const void *p, const void *q)
        !           211: {
        !           212:   const struct desc *a = *(struct desc * const *)p;
        !           213:   const struct desc *b = *(struct desc * const *)q;
        !           214: 
        !           215:   return strcmp (a->cmd, b->cmd);
        !           216: }
        !           217: 
        !           218: /* Sort each node's command element according to command string. */
        !           219: void
        !           220: sort_node ()
        !           221: {
        !           222:   unsigned int i, j;
        !           223:   struct cmd_node *cnode;
        !           224:   vector descvec;
        !           225:   struct cmd_element *cmd_element;
        !           226: 
        !           227:   for (i = 0; i < vector_active (cmdvec); i++)
        !           228:     if ((cnode = vector_slot (cmdvec, i)) != NULL)
        !           229:       {        
        !           230:        vector cmd_vector = cnode->cmd_vector;
        !           231:        qsort (cmd_vector->index, vector_active (cmd_vector), 
        !           232:               sizeof (void *), cmp_node);
        !           233: 
        !           234:        for (j = 0; j < vector_active (cmd_vector); j++)
        !           235:          if ((cmd_element = vector_slot (cmd_vector, j)) != NULL
        !           236:              && vector_active (cmd_element->strvec))
        !           237:            {
        !           238:              descvec = vector_slot (cmd_element->strvec,
        !           239:                                     vector_active (cmd_element->strvec) - 1);
        !           240:              qsort (descvec->index, vector_active (descvec), 
        !           241:                     sizeof (void *), cmp_desc);
        !           242:            }
        !           243:       }
        !           244: }
        !           245: 
        !           246: /* Breaking up string into each command piece. I assume given
        !           247:    character is separated by a space character. Return value is a
        !           248:    vector which includes char ** data element. */
        !           249: vector
        !           250: cmd_make_strvec (const char *string)
        !           251: {
        !           252:   const char *cp, *start;
        !           253:   char *token;
        !           254:   int strlen;
        !           255:   vector strvec;
        !           256:   
        !           257:   if (string == NULL)
        !           258:     return NULL;
        !           259:   
        !           260:   cp = string;
        !           261: 
        !           262:   /* Skip white spaces. */
        !           263:   while (isspace ((int) *cp) && *cp != '\0')
        !           264:     cp++;
        !           265: 
        !           266:   /* Return if there is only white spaces */
        !           267:   if (*cp == '\0')
        !           268:     return NULL;
        !           269: 
        !           270:   if (*cp == '!' || *cp == '#')
        !           271:     return NULL;
        !           272: 
        !           273:   /* Prepare return vector. */
        !           274:   strvec = vector_init (VECTOR_MIN_SIZE);
        !           275: 
        !           276:   /* Copy each command piece and set into vector. */
        !           277:   while (1) 
        !           278:     {
        !           279:       start = cp;
        !           280:       while (!(isspace ((int) *cp) || *cp == '\r' || *cp == '\n') &&
        !           281:             *cp != '\0')
        !           282:        cp++;
        !           283:       strlen = cp - start;
        !           284:       token = XMALLOC (MTYPE_STRVEC, strlen + 1);
        !           285:       memcpy (token, start, strlen);
        !           286:       *(token + strlen) = '\0';
        !           287:       vector_set (strvec, token);
        !           288: 
        !           289:       while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r') &&
        !           290:             *cp != '\0')
        !           291:        cp++;
        !           292: 
        !           293:       if (*cp == '\0')
        !           294:        return strvec;
        !           295:     }
        !           296: }
        !           297: 
        !           298: /* Free allocated string vector. */
        !           299: void
        !           300: cmd_free_strvec (vector v)
        !           301: {
        !           302:   unsigned int i;
        !           303:   char *cp;
        !           304: 
        !           305:   if (!v)
        !           306:     return;
        !           307: 
        !           308:   for (i = 0; i < vector_active (v); i++)
        !           309:     if ((cp = vector_slot (v, i)) != NULL)
        !           310:       XFREE (MTYPE_STRVEC, cp);
        !           311: 
        !           312:   vector_free (v);
        !           313: }
        !           314: 
        !           315: /* Fetch next description.  Used in cmd_make_descvec(). */
        !           316: static char *
        !           317: cmd_desc_str (const char **string)
        !           318: {
        !           319:   const char *cp, *start;
        !           320:   char *token;
        !           321:   int strlen;
        !           322:   
        !           323:   cp = *string;
        !           324: 
        !           325:   if (cp == NULL)
        !           326:     return NULL;
        !           327: 
        !           328:   /* Skip white spaces. */
        !           329:   while (isspace ((int) *cp) && *cp != '\0')
        !           330:     cp++;
        !           331: 
        !           332:   /* Return if there is only white spaces */
        !           333:   if (*cp == '\0')
        !           334:     return NULL;
        !           335: 
        !           336:   start = cp;
        !           337: 
        !           338:   while (!(*cp == '\r' || *cp == '\n') && *cp != '\0')
        !           339:     cp++;
        !           340: 
        !           341:   strlen = cp - start;
        !           342:   token = XMALLOC (MTYPE_STRVEC, strlen + 1);
        !           343:   memcpy (token, start, strlen);
        !           344:   *(token + strlen) = '\0';
        !           345: 
        !           346:   *string = cp;
        !           347: 
        !           348:   return token;
        !           349: }
        !           350: 
        !           351: /* New string vector. */
        !           352: static vector
        !           353: cmd_make_descvec (const char *string, const char *descstr)
        !           354: {
        !           355:   int multiple = 0;
        !           356:   const char *sp;
        !           357:   char *token;
        !           358:   int len;
        !           359:   const char *cp;
        !           360:   const char *dp;
        !           361:   vector allvec;
        !           362:   vector strvec = NULL;
        !           363:   struct desc *desc;
        !           364: 
        !           365:   cp = string;
        !           366:   dp = descstr;
        !           367: 
        !           368:   if (cp == NULL)
        !           369:     return NULL;
        !           370: 
        !           371:   allvec = vector_init (VECTOR_MIN_SIZE);
        !           372: 
        !           373:   while (1)
        !           374:     {
        !           375:       while (isspace ((int) *cp) && *cp != '\0')
        !           376:        cp++;
        !           377: 
        !           378:       if (*cp == '(')
        !           379:        {
        !           380:          multiple = 1;
        !           381:          cp++;
        !           382:        }
        !           383:       if (*cp == ')')
        !           384:        {
        !           385:          multiple = 0;
        !           386:          cp++;
        !           387:        }
        !           388:       if (*cp == '|')
        !           389:        {
        !           390:          if (! multiple)
        !           391:            {
        !           392:              fprintf (stderr, "Command parse error!: %s\n", string);
        !           393:              exit (1);
        !           394:            }
        !           395:          cp++;
        !           396:        }
        !           397:       
        !           398:       while (isspace ((int) *cp) && *cp != '\0')
        !           399:        cp++;
        !           400: 
        !           401:       if (*cp == '(')
        !           402:        {
        !           403:          multiple = 1;
        !           404:          cp++;
        !           405:        }
        !           406: 
        !           407:       if (*cp == '\0') 
        !           408:        return allvec;
        !           409: 
        !           410:       sp = cp;
        !           411: 
        !           412:       while (! (isspace ((int) *cp) || *cp == '\r' || *cp == '\n' || *cp == ')' || *cp == '|') && *cp != '\0')
        !           413:        cp++;
        !           414: 
        !           415:       len = cp - sp;
        !           416: 
        !           417:       token = XMALLOC (MTYPE_STRVEC, len + 1);
        !           418:       memcpy (token, sp, len);
        !           419:       *(token + len) = '\0';
        !           420: 
        !           421:       desc = XCALLOC (MTYPE_DESC, sizeof (struct desc));
        !           422:       desc->cmd = token;
        !           423:       desc->str = cmd_desc_str (&dp);
        !           424: 
        !           425:       if (multiple)
        !           426:        {
        !           427:          if (multiple == 1)
        !           428:            {
        !           429:              strvec = vector_init (VECTOR_MIN_SIZE);
        !           430:              vector_set (allvec, strvec);
        !           431:            }
        !           432:          multiple++;
        !           433:        }
        !           434:       else
        !           435:        {
        !           436:          strvec = vector_init (VECTOR_MIN_SIZE);
        !           437:          vector_set (allvec, strvec);
        !           438:        }
        !           439:       vector_set (strvec, desc);
        !           440:     }
        !           441: }
        !           442: 
        !           443: /* Count mandantory string vector size.  This is to determine inputed
        !           444:    command has enough command length. */
        !           445: static int
        !           446: cmd_cmdsize (vector strvec)
        !           447: {
        !           448:   unsigned int i;
        !           449:   int size = 0;
        !           450:   vector descvec;
        !           451:   struct desc *desc;
        !           452: 
        !           453:   for (i = 0; i < vector_active (strvec); i++)
        !           454:     if ((descvec = vector_slot (strvec, i)) != NULL)
        !           455:     {
        !           456:       if ((vector_active (descvec)) == 1
        !           457:         && (desc = vector_slot (descvec, 0)) != NULL)
        !           458:        {
        !           459:          if (desc->cmd == NULL || CMD_OPTION (desc->cmd))
        !           460:            return size;
        !           461:          else
        !           462:            size++;
        !           463:        }
        !           464:       else
        !           465:        size++;
        !           466:     }
        !           467:   return size;
        !           468: }
        !           469: 
        !           470: /* Return prompt character of specified node. */
        !           471: const char *
        !           472: cmd_prompt (enum node_type node)
        !           473: {
        !           474:   struct cmd_node *cnode;
        !           475: 
        !           476:   cnode = vector_slot (cmdvec, node);
        !           477:   return cnode->prompt;
        !           478: }
        !           479: 
        !           480: /* Install a command into a node. */
        !           481: void
        !           482: install_element (enum node_type ntype, struct cmd_element *cmd)
        !           483: {
        !           484:   struct cmd_node *cnode;
        !           485:   
        !           486:   /* cmd_init hasn't been called */
        !           487:   if (!cmdvec)
        !           488:     return;
        !           489:   
        !           490:   cnode = vector_slot (cmdvec, ntype);
        !           491: 
        !           492:   if (cnode == NULL) 
        !           493:     {
        !           494:       fprintf (stderr, "Command node %d doesn't exist, please check it\n",
        !           495:               ntype);
        !           496:       exit (1);
        !           497:     }
        !           498: 
        !           499:   vector_set (cnode->cmd_vector, cmd);
        !           500: 
        !           501:   if (cmd->strvec == NULL)
        !           502:     cmd->strvec = cmd_make_descvec (cmd->string, cmd->doc);
        !           503: 
        !           504:   cmd->cmdsize = cmd_cmdsize (cmd->strvec);
        !           505: }
        !           506: 
        !           507: static const unsigned char itoa64[] =
        !           508: "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        !           509: 
        !           510: static void
        !           511: to64(char *s, long v, int n)
        !           512: {
        !           513:   while (--n >= 0) 
        !           514:     {
        !           515:       *s++ = itoa64[v&0x3f];
        !           516:       v >>= 6;
        !           517:     }
        !           518: }
        !           519: 
        !           520: static char *
        !           521: zencrypt (const char *passwd)
        !           522: {
        !           523:   char salt[6];
        !           524:   struct timeval tv;
        !           525:   char *crypt (const char *, const char *);
        !           526: 
        !           527:   gettimeofday(&tv,0);
        !           528:   
        !           529:   to64(&salt[0], random(), 3);
        !           530:   to64(&salt[3], tv.tv_usec, 3);
        !           531:   salt[5] = '\0';
        !           532: 
        !           533:   return crypt (passwd, salt);
        !           534: }
        !           535: 
        !           536: /* This function write configuration of this host. */
        !           537: static int
        !           538: config_write_host (struct vty *vty)
        !           539: {
        !           540:   if (host.name)
        !           541:     vty_out (vty, "hostname %s%s", host.name, VTY_NEWLINE);
        !           542: 
        !           543:   if (host.encrypt)
        !           544:     {
        !           545:       if (host.password_encrypt)
        !           546:         vty_out (vty, "password 8 %s%s", host.password_encrypt, VTY_NEWLINE); 
        !           547:       if (host.enable_encrypt)
        !           548:         vty_out (vty, "enable password 8 %s%s", host.enable_encrypt, VTY_NEWLINE); 
        !           549:     }
        !           550:   else
        !           551:     {
        !           552:       if (host.password)
        !           553:         vty_out (vty, "password %s%s", host.password, VTY_NEWLINE);
        !           554:       if (host.enable)
        !           555:         vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE);
        !           556:     }
        !           557: 
        !           558:   if (zlog_default->default_lvl != LOG_DEBUG)
        !           559:     {
        !           560:       vty_out (vty, "! N.B. The 'log trap' command is deprecated.%s",
        !           561:               VTY_NEWLINE);
        !           562:       vty_out (vty, "log trap %s%s",
        !           563:               zlog_priority[zlog_default->default_lvl], VTY_NEWLINE);
        !           564:     }
        !           565: 
        !           566:   if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED))
        !           567:     {
        !           568:       vty_out (vty, "log file %s", host.logfile);
        !           569:       if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl)
        !           570:        vty_out (vty, " %s",
        !           571:                 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]);
        !           572:       vty_out (vty, "%s", VTY_NEWLINE);
        !           573:     }
        !           574: 
        !           575:   if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED)
        !           576:     {
        !           577:       vty_out (vty, "log stdout");
        !           578:       if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl)
        !           579:        vty_out (vty, " %s",
        !           580:                 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]);
        !           581:       vty_out (vty, "%s", VTY_NEWLINE);
        !           582:     }
        !           583: 
        !           584:   if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
        !           585:     vty_out(vty,"no log monitor%s",VTY_NEWLINE);
        !           586:   else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] != zlog_default->default_lvl)
        !           587:     vty_out(vty,"log monitor %s%s",
        !           588:            zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],VTY_NEWLINE);
        !           589: 
        !           590:   if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED)
        !           591:     {
        !           592:       vty_out (vty, "log syslog");
        !           593:       if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl)
        !           594:        vty_out (vty, " %s",
        !           595:                 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]);
        !           596:       vty_out (vty, "%s", VTY_NEWLINE);
        !           597:     }
        !           598: 
        !           599:   if (zlog_default->facility != LOG_DAEMON)
        !           600:     vty_out (vty, "log facility %s%s",
        !           601:             facility_name(zlog_default->facility), VTY_NEWLINE);
        !           602: 
        !           603:   if (zlog_default->record_priority == 1)
        !           604:     vty_out (vty, "log record-priority%s", VTY_NEWLINE);
        !           605: 
        !           606:   if (zlog_default->timestamp_precision > 0)
        !           607:     vty_out (vty, "log timestamp precision %d%s",
        !           608:             zlog_default->timestamp_precision, VTY_NEWLINE);
        !           609: 
        !           610:   if (host.advanced)
        !           611:     vty_out (vty, "service advanced-vty%s", VTY_NEWLINE);
        !           612: 
        !           613:   if (host.encrypt)
        !           614:     vty_out (vty, "service password-encryption%s", VTY_NEWLINE);
        !           615: 
        !           616:   if (host.lines >= 0)
        !           617:     vty_out (vty, "service terminal-length %d%s", host.lines,
        !           618:             VTY_NEWLINE);
        !           619: 
        !           620:   if (host.motdfile)
        !           621:     vty_out (vty, "banner motd file %s%s", host.motdfile, VTY_NEWLINE);
        !           622:   else if (! host.motd)
        !           623:     vty_out (vty, "no banner motd%s", VTY_NEWLINE);
        !           624: 
        !           625:   return 1;
        !           626: }
        !           627: 
        !           628: /* Utility function for getting command vector. */
        !           629: static vector
        !           630: cmd_node_vector (vector v, enum node_type ntype)
        !           631: {
        !           632:   struct cmd_node *cnode = vector_slot (v, ntype);
        !           633:   return cnode->cmd_vector;
        !           634: }
        !           635: 
        !           636: #if 0
        !           637: /* Filter command vector by symbol.  This function is not actually used;
        !           638:  * should it be deleted? */
        !           639: static int
        !           640: cmd_filter_by_symbol (char *command, char *symbol)
        !           641: {
        !           642:   int i, lim;
        !           643: 
        !           644:   if (strcmp (symbol, "IPV4_ADDRESS") == 0)
        !           645:     {
        !           646:       i = 0;
        !           647:       lim = strlen (command);
        !           648:       while (i < lim)
        !           649:        {
        !           650:          if (! (isdigit ((int) command[i]) || command[i] == '.' || command[i] == '/'))
        !           651:            return 1;
        !           652:          i++;
        !           653:        }
        !           654:       return 0;
        !           655:     }
        !           656:   if (strcmp (symbol, "STRING") == 0)
        !           657:     {
        !           658:       i = 0;
        !           659:       lim = strlen (command);
        !           660:       while (i < lim)
        !           661:        {
        !           662:          if (! (isalpha ((int) command[i]) || command[i] == '_' || command[i] == '-'))
        !           663:            return 1;
        !           664:          i++;
        !           665:        }
        !           666:       return 0;
        !           667:     }
        !           668:   if (strcmp (symbol, "IFNAME") == 0)
        !           669:     {
        !           670:       i = 0;
        !           671:       lim = strlen (command);
        !           672:       while (i < lim)
        !           673:        {
        !           674:          if (! isalnum ((int) command[i]))
        !           675:            return 1;
        !           676:          i++;
        !           677:        }
        !           678:       return 0;
        !           679:     }
        !           680:   return 0;
        !           681: }
        !           682: #endif
        !           683: 
        !           684: /* Completion match types. */
        !           685: enum match_type 
        !           686: {
        !           687:   no_match,
        !           688:   extend_match,
        !           689:   ipv4_prefix_match,
        !           690:   ipv4_match,
        !           691:   ipv6_prefix_match,
        !           692:   ipv6_match,
        !           693:   range_match,
        !           694:   vararg_match,
        !           695:   partly_match,
        !           696:   exact_match 
        !           697: };
        !           698: 
        !           699: static enum match_type
        !           700: cmd_ipv4_match (const char *str)
        !           701: {
        !           702:   const char *sp;
        !           703:   int dots = 0, nums = 0;
        !           704:   char buf[4];
        !           705: 
        !           706:   if (str == NULL)
        !           707:     return partly_match;
        !           708: 
        !           709:   for (;;)
        !           710:     {
        !           711:       memset (buf, 0, sizeof (buf));
        !           712:       sp = str;
        !           713:       while (*str != '\0')
        !           714:        {
        !           715:          if (*str == '.')
        !           716:            {
        !           717:              if (dots >= 3)
        !           718:                return no_match;
        !           719: 
        !           720:              if (*(str + 1) == '.')
        !           721:                return no_match;
        !           722: 
        !           723:              if (*(str + 1) == '\0')
        !           724:                return partly_match;
        !           725: 
        !           726:              dots++;
        !           727:              break;
        !           728:            }
        !           729:          if (!isdigit ((int) *str))
        !           730:            return no_match;
        !           731: 
        !           732:          str++;
        !           733:        }
        !           734: 
        !           735:       if (str - sp > 3)
        !           736:        return no_match;
        !           737: 
        !           738:       strncpy (buf, sp, str - sp);
        !           739:       if (atoi (buf) > 255)
        !           740:        return no_match;
        !           741: 
        !           742:       nums++;
        !           743: 
        !           744:       if (*str == '\0')
        !           745:        break;
        !           746: 
        !           747:       str++;
        !           748:     }
        !           749: 
        !           750:   if (nums < 4)
        !           751:     return partly_match;
        !           752: 
        !           753:   return exact_match;
        !           754: }
        !           755: 
        !           756: static enum match_type
        !           757: cmd_ipv4_prefix_match (const char *str)
        !           758: {
        !           759:   const char *sp;
        !           760:   int dots = 0;
        !           761:   char buf[4];
        !           762: 
        !           763:   if (str == NULL)
        !           764:     return partly_match;
        !           765: 
        !           766:   for (;;)
        !           767:     {
        !           768:       memset (buf, 0, sizeof (buf));
        !           769:       sp = str;
        !           770:       while (*str != '\0' && *str != '/')
        !           771:        {
        !           772:          if (*str == '.')
        !           773:            {
        !           774:              if (dots == 3)
        !           775:                return no_match;
        !           776: 
        !           777:              if (*(str + 1) == '.' || *(str + 1) == '/')
        !           778:                return no_match;
        !           779: 
        !           780:              if (*(str + 1) == '\0')
        !           781:                return partly_match;
        !           782: 
        !           783:              dots++;
        !           784:              break;
        !           785:            }
        !           786: 
        !           787:          if (!isdigit ((int) *str))
        !           788:            return no_match;
        !           789: 
        !           790:          str++;
        !           791:        }
        !           792: 
        !           793:       if (str - sp > 3)
        !           794:        return no_match;
        !           795: 
        !           796:       strncpy (buf, sp, str - sp);
        !           797:       if (atoi (buf) > 255)
        !           798:        return no_match;
        !           799: 
        !           800:       if (dots == 3)
        !           801:        {
        !           802:          if (*str == '/')
        !           803:            {
        !           804:              if (*(str + 1) == '\0')
        !           805:                return partly_match;
        !           806: 
        !           807:              str++;
        !           808:              break;
        !           809:            }
        !           810:          else if (*str == '\0')
        !           811:            return partly_match;
        !           812:        }
        !           813: 
        !           814:       if (*str == '\0')
        !           815:        return partly_match;
        !           816: 
        !           817:       str++;
        !           818:     }
        !           819: 
        !           820:   sp = str;
        !           821:   while (*str != '\0')
        !           822:     {
        !           823:       if (!isdigit ((int) *str))
        !           824:        return no_match;
        !           825: 
        !           826:       str++;
        !           827:     }
        !           828: 
        !           829:   if (atoi (sp) > 32)
        !           830:     return no_match;
        !           831: 
        !           832:   return exact_match;
        !           833: }
        !           834: 
        !           835: #define IPV6_ADDR_STR          "0123456789abcdefABCDEF:.%"
        !           836: #define IPV6_PREFIX_STR                "0123456789abcdefABCDEF:.%/"
        !           837: #define STATE_START            1
        !           838: #define STATE_COLON            2
        !           839: #define STATE_DOUBLE           3
        !           840: #define STATE_ADDR             4
        !           841: #define STATE_DOT               5
        !           842: #define STATE_SLASH            6
        !           843: #define STATE_MASK             7
        !           844: 
        !           845: #ifdef HAVE_IPV6
        !           846: 
        !           847: static enum match_type
        !           848: cmd_ipv6_match (const char *str)
        !           849: {
        !           850:   int state = STATE_START;
        !           851:   int colons = 0, nums = 0, double_colon = 0;
        !           852:   const char *sp = NULL;
        !           853:   struct sockaddr_in6 sin6_dummy;
        !           854:   int ret;
        !           855: 
        !           856:   if (str == NULL)
        !           857:     return partly_match;
        !           858: 
        !           859:   if (strspn (str, IPV6_ADDR_STR) != strlen (str))
        !           860:     return no_match;
        !           861: 
        !           862:   /* use inet_pton that has a better support,
        !           863:    * for example inet_pton can support the automatic addresses:
        !           864:    *  ::1.2.3.4
        !           865:    */
        !           866:   ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
        !           867:    
        !           868:   if (ret == 1)
        !           869:     return exact_match;
        !           870: 
        !           871:   while (*str != '\0')
        !           872:     {
        !           873:       switch (state)
        !           874:        {
        !           875:        case STATE_START:
        !           876:          if (*str == ':')
        !           877:            {
        !           878:              if (*(str + 1) != ':' && *(str + 1) != '\0')
        !           879:                return no_match;
        !           880:              colons--;
        !           881:              state = STATE_COLON;
        !           882:            }
        !           883:          else
        !           884:            {
        !           885:              sp = str;
        !           886:              state = STATE_ADDR;
        !           887:            }
        !           888: 
        !           889:          continue;
        !           890:        case STATE_COLON:
        !           891:          colons++;
        !           892:          if (*(str + 1) == ':')
        !           893:            state = STATE_DOUBLE;
        !           894:          else
        !           895:            {
        !           896:              sp = str + 1;
        !           897:              state = STATE_ADDR;
        !           898:            }
        !           899:          break;
        !           900:        case STATE_DOUBLE:
        !           901:          if (double_colon)
        !           902:            return no_match;
        !           903: 
        !           904:          if (*(str + 1) == ':')
        !           905:            return no_match;
        !           906:          else
        !           907:            {
        !           908:              if (*(str + 1) != '\0')
        !           909:                colons++;
        !           910:              sp = str + 1;
        !           911:              state = STATE_ADDR;
        !           912:            }
        !           913: 
        !           914:          double_colon++;
        !           915:          nums++;
        !           916:          break;
        !           917:        case STATE_ADDR:
        !           918:          if (*(str + 1) == ':' || *(str + 1) == '\0')
        !           919:            {
        !           920:              if (str - sp > 3)
        !           921:                return no_match;
        !           922: 
        !           923:              nums++;
        !           924:              state = STATE_COLON;
        !           925:            }
        !           926:          if (*(str + 1) == '.')
        !           927:            state = STATE_DOT;
        !           928:          break;
        !           929:        case STATE_DOT:
        !           930:          state = STATE_ADDR;
        !           931:          break;
        !           932:        default:
        !           933:          break;
        !           934:        }
        !           935: 
        !           936:       if (nums > 8)
        !           937:        return no_match;
        !           938: 
        !           939:       if (colons > 7)
        !           940:        return no_match;
        !           941: 
        !           942:       str++;
        !           943:     }
        !           944: 
        !           945: #if 0
        !           946:   if (nums < 11)
        !           947:     return partly_match;
        !           948: #endif /* 0 */
        !           949: 
        !           950:   return exact_match;
        !           951: }
        !           952: 
        !           953: static enum match_type
        !           954: cmd_ipv6_prefix_match (const char *str)
        !           955: {
        !           956:   int state = STATE_START;
        !           957:   int colons = 0, nums = 0, double_colon = 0;
        !           958:   int mask;
        !           959:   const char *sp = NULL;
        !           960:   char *endptr = NULL;
        !           961: 
        !           962:   if (str == NULL)
        !           963:     return partly_match;
        !           964: 
        !           965:   if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
        !           966:     return no_match;
        !           967: 
        !           968:   while (*str != '\0' && state != STATE_MASK)
        !           969:     {
        !           970:       switch (state)
        !           971:        {
        !           972:        case STATE_START:
        !           973:          if (*str == ':')
        !           974:            {
        !           975:              if (*(str + 1) != ':' && *(str + 1) != '\0')
        !           976:                return no_match;
        !           977:              colons--;
        !           978:              state = STATE_COLON;
        !           979:            }
        !           980:          else
        !           981:            {
        !           982:              sp = str;
        !           983:              state = STATE_ADDR;
        !           984:            }
        !           985: 
        !           986:          continue;
        !           987:        case STATE_COLON:
        !           988:          colons++;
        !           989:          if (*(str + 1) == '/')
        !           990:            return no_match;
        !           991:          else if (*(str + 1) == ':')
        !           992:            state = STATE_DOUBLE;
        !           993:          else
        !           994:            {
        !           995:              sp = str + 1;
        !           996:              state = STATE_ADDR;
        !           997:            }
        !           998:          break;
        !           999:        case STATE_DOUBLE:
        !          1000:          if (double_colon)
        !          1001:            return no_match;
        !          1002: 
        !          1003:          if (*(str + 1) == ':')
        !          1004:            return no_match;
        !          1005:          else
        !          1006:            {
        !          1007:              if (*(str + 1) != '\0' && *(str + 1) != '/')
        !          1008:                colons++;
        !          1009:              sp = str + 1;
        !          1010: 
        !          1011:              if (*(str + 1) == '/')
        !          1012:                state = STATE_SLASH;
        !          1013:              else
        !          1014:                state = STATE_ADDR;
        !          1015:            }
        !          1016: 
        !          1017:          double_colon++;
        !          1018:          nums += 1;
        !          1019:          break;
        !          1020:        case STATE_ADDR:
        !          1021:          if (*(str + 1) == ':' || *(str + 1) == '.'
        !          1022:              || *(str + 1) == '\0' || *(str + 1) == '/')
        !          1023:            {
        !          1024:              if (str - sp > 3)
        !          1025:                return no_match;
        !          1026: 
        !          1027:              for (; sp <= str; sp++)
        !          1028:                if (*sp == '/')
        !          1029:                  return no_match;
        !          1030: 
        !          1031:              nums++;
        !          1032: 
        !          1033:              if (*(str + 1) == ':')
        !          1034:                state = STATE_COLON;
        !          1035:              else if (*(str + 1) == '.')
        !          1036:                state = STATE_DOT;
        !          1037:              else if (*(str + 1) == '/')
        !          1038:                state = STATE_SLASH;
        !          1039:            }
        !          1040:          break;
        !          1041:        case STATE_DOT:
        !          1042:          state = STATE_ADDR;
        !          1043:          break;
        !          1044:        case STATE_SLASH:
        !          1045:          if (*(str + 1) == '\0')
        !          1046:            return partly_match;
        !          1047: 
        !          1048:          state = STATE_MASK;
        !          1049:          break;
        !          1050:        default:
        !          1051:          break;
        !          1052:        }
        !          1053: 
        !          1054:       if (nums > 11)
        !          1055:        return no_match;
        !          1056: 
        !          1057:       if (colons > 7)
        !          1058:        return no_match;
        !          1059: 
        !          1060:       str++;
        !          1061:     }
        !          1062: 
        !          1063:   if (state < STATE_MASK)
        !          1064:     return partly_match;
        !          1065: 
        !          1066:   mask = strtol (str, &endptr, 10);
        !          1067:   if (*endptr != '\0')
        !          1068:     return no_match;
        !          1069: 
        !          1070:   if (mask < 0 || mask > 128)
        !          1071:     return no_match;
        !          1072:   
        !          1073: /* I don't know why mask < 13 makes command match partly.
        !          1074:    Forgive me to make this comments. I Want to set static default route
        !          1075:    because of lack of function to originate default in ospf6d; sorry
        !          1076:        yasu
        !          1077:   if (mask < 13)
        !          1078:     return partly_match;
        !          1079: */
        !          1080: 
        !          1081:   return exact_match;
        !          1082: }
        !          1083: 
        !          1084: #endif /* HAVE_IPV6  */
        !          1085: 
        !          1086: #define DECIMAL_STRLEN_MAX 10
        !          1087: 
        !          1088: static int
        !          1089: cmd_range_match (const char *range, const char *str)
        !          1090: {
        !          1091:   char *p;
        !          1092:   char buf[DECIMAL_STRLEN_MAX + 1];
        !          1093:   char *endptr = NULL;
        !          1094:   unsigned long min, max, val;
        !          1095: 
        !          1096:   if (str == NULL)
        !          1097:     return 1;
        !          1098: 
        !          1099:   val = strtoul (str, &endptr, 10);
        !          1100:   if (*endptr != '\0')
        !          1101:     return 0;
        !          1102: 
        !          1103:   range++;
        !          1104:   p = strchr (range, '-');
        !          1105:   if (p == NULL)
        !          1106:     return 0;
        !          1107:   if (p - range > DECIMAL_STRLEN_MAX)
        !          1108:     return 0;
        !          1109:   strncpy (buf, range, p - range);
        !          1110:   buf[p - range] = '\0';
        !          1111:   min = strtoul (buf, &endptr, 10);
        !          1112:   if (*endptr != '\0')
        !          1113:     return 0;
        !          1114: 
        !          1115:   range = p + 1;
        !          1116:   p = strchr (range, '>');
        !          1117:   if (p == NULL)
        !          1118:     return 0;
        !          1119:   if (p - range > DECIMAL_STRLEN_MAX)
        !          1120:     return 0;
        !          1121:   strncpy (buf, range, p - range);
        !          1122:   buf[p - range] = '\0';
        !          1123:   max = strtoul (buf, &endptr, 10);
        !          1124:   if (*endptr != '\0')
        !          1125:     return 0;
        !          1126: 
        !          1127:   if (val < min || val > max)
        !          1128:     return 0;
        !          1129: 
        !          1130:   return 1;
        !          1131: }
        !          1132: 
        !          1133: /* Make completion match and return match type flag. */
        !          1134: static enum match_type
        !          1135: cmd_filter_by_completion (char *command, vector v, unsigned int index)
        !          1136: {
        !          1137:   unsigned int i;
        !          1138:   const char *str;
        !          1139:   struct cmd_element *cmd_element;
        !          1140:   enum match_type match_type;
        !          1141:   vector descvec;
        !          1142:   struct desc *desc;
        !          1143: 
        !          1144:   match_type = no_match;
        !          1145: 
        !          1146:   /* If command and cmd_element string does not match set NULL to vector */
        !          1147:   for (i = 0; i < vector_active (v); i++)
        !          1148:     if ((cmd_element = vector_slot (v, i)) != NULL)
        !          1149:       {
        !          1150:        if (index >= vector_active (cmd_element->strvec))
        !          1151:          vector_slot (v, i) = NULL;
        !          1152:        else
        !          1153:          {
        !          1154:            unsigned int j;
        !          1155:            int matched = 0;
        !          1156: 
        !          1157:            descvec = vector_slot (cmd_element->strvec, index);
        !          1158: 
        !          1159:            for (j = 0; j < vector_active (descvec); j++)
        !          1160:              if ((desc = vector_slot (descvec, j)))
        !          1161:                {
        !          1162:                  str = desc->cmd;
        !          1163:                  
        !          1164:                  if (CMD_VARARG (str))
        !          1165:                    {
        !          1166:                      if (match_type < vararg_match)
        !          1167:                        match_type = vararg_match;
        !          1168:                      matched++;
        !          1169:                    }
        !          1170:                  else if (CMD_RANGE (str))
        !          1171:                    {
        !          1172:                      if (cmd_range_match (str, command))
        !          1173:                        {
        !          1174:                          if (match_type < range_match)
        !          1175:                            match_type = range_match;
        !          1176: 
        !          1177:                          matched++;
        !          1178:                        }
        !          1179:                    }
        !          1180: #ifdef HAVE_IPV6
        !          1181:                  else if (CMD_IPV6 (str))
        !          1182:                    {
        !          1183:                      if (cmd_ipv6_match (command))
        !          1184:                        {
        !          1185:                          if (match_type < ipv6_match)
        !          1186:                            match_type = ipv6_match;
        !          1187: 
        !          1188:                          matched++;
        !          1189:                        }
        !          1190:                    }
        !          1191:                  else if (CMD_IPV6_PREFIX (str))
        !          1192:                    {
        !          1193:                      if (cmd_ipv6_prefix_match (command))
        !          1194:                        {
        !          1195:                          if (match_type < ipv6_prefix_match)
        !          1196:                            match_type = ipv6_prefix_match;
        !          1197: 
        !          1198:                          matched++;
        !          1199:                        }
        !          1200:                    }
        !          1201: #endif /* HAVE_IPV6  */
        !          1202:                  else if (CMD_IPV4 (str))
        !          1203:                    {
        !          1204:                      if (cmd_ipv4_match (command))
        !          1205:                        {
        !          1206:                          if (match_type < ipv4_match)
        !          1207:                            match_type = ipv4_match;
        !          1208: 
        !          1209:                          matched++;
        !          1210:                        }
        !          1211:                    }
        !          1212:                  else if (CMD_IPV4_PREFIX (str))
        !          1213:                    {
        !          1214:                      if (cmd_ipv4_prefix_match (command))
        !          1215:                        {
        !          1216:                          if (match_type < ipv4_prefix_match)
        !          1217:                            match_type = ipv4_prefix_match;
        !          1218:                          matched++;
        !          1219:                        }
        !          1220:                    }
        !          1221:                  else
        !          1222:                    /* Check is this point's argument optional ? */
        !          1223:                  if (CMD_OPTION (str) || CMD_VARIABLE (str))
        !          1224:                    {
        !          1225:                      if (match_type < extend_match)
        !          1226:                        match_type = extend_match;
        !          1227:                      matched++;
        !          1228:                    }
        !          1229:                  else if (strncmp (command, str, strlen (command)) == 0)
        !          1230:                    {
        !          1231:                      if (strcmp (command, str) == 0)
        !          1232:                        match_type = exact_match;
        !          1233:                      else
        !          1234:                        {
        !          1235:                          if (match_type < partly_match)
        !          1236:                            match_type = partly_match;
        !          1237:                        }
        !          1238:                      matched++;
        !          1239:                    }
        !          1240:                }
        !          1241:            if (!matched)
        !          1242:              vector_slot (v, i) = NULL;
        !          1243:          }
        !          1244:       }
        !          1245:   return match_type;
        !          1246: }
        !          1247: 
        !          1248: /* Filter vector by command character with index. */
        !          1249: static enum match_type
        !          1250: cmd_filter_by_string (char *command, vector v, unsigned int index)
        !          1251: {
        !          1252:   unsigned int i;
        !          1253:   const char *str;
        !          1254:   struct cmd_element *cmd_element;
        !          1255:   enum match_type match_type;
        !          1256:   vector descvec;
        !          1257:   struct desc *desc;
        !          1258: 
        !          1259:   match_type = no_match;
        !          1260: 
        !          1261:   /* If command and cmd_element string does not match set NULL to vector */
        !          1262:   for (i = 0; i < vector_active (v); i++)
        !          1263:     if ((cmd_element = vector_slot (v, i)) != NULL)
        !          1264:       {
        !          1265:        /* If given index is bigger than max string vector of command,
        !          1266:           set NULL */
        !          1267:        if (index >= vector_active (cmd_element->strvec))
        !          1268:          vector_slot (v, i) = NULL;
        !          1269:        else
        !          1270:          {
        !          1271:            unsigned int j;
        !          1272:            int matched = 0;
        !          1273: 
        !          1274:            descvec = vector_slot (cmd_element->strvec, index);
        !          1275: 
        !          1276:            for (j = 0; j < vector_active (descvec); j++)
        !          1277:              if ((desc = vector_slot (descvec, j)))
        !          1278:                {
        !          1279:                  str = desc->cmd;
        !          1280: 
        !          1281:                  if (CMD_VARARG (str))
        !          1282:                    {
        !          1283:                      if (match_type < vararg_match)
        !          1284:                        match_type = vararg_match;
        !          1285:                      matched++;
        !          1286:                    }
        !          1287:                  else if (CMD_RANGE (str))
        !          1288:                    {
        !          1289:                      if (cmd_range_match (str, command))
        !          1290:                        {
        !          1291:                          if (match_type < range_match)
        !          1292:                            match_type = range_match;
        !          1293:                          matched++;
        !          1294:                        }
        !          1295:                    }
        !          1296: #ifdef HAVE_IPV6
        !          1297:                  else if (CMD_IPV6 (str))
        !          1298:                    {
        !          1299:                      if (cmd_ipv6_match (command) == exact_match)
        !          1300:                        {
        !          1301:                          if (match_type < ipv6_match)
        !          1302:                            match_type = ipv6_match;
        !          1303:                          matched++;
        !          1304:                        }
        !          1305:                    }
        !          1306:                  else if (CMD_IPV6_PREFIX (str))
        !          1307:                    {
        !          1308:                      if (cmd_ipv6_prefix_match (command) == exact_match)
        !          1309:                        {
        !          1310:                          if (match_type < ipv6_prefix_match)
        !          1311:                            match_type = ipv6_prefix_match;
        !          1312:                          matched++;
        !          1313:                        }
        !          1314:                    }
        !          1315: #endif /* HAVE_IPV6  */
        !          1316:                  else if (CMD_IPV4 (str))
        !          1317:                    {
        !          1318:                      if (cmd_ipv4_match (command) == exact_match)
        !          1319:                        {
        !          1320:                          if (match_type < ipv4_match)
        !          1321:                            match_type = ipv4_match;
        !          1322:                          matched++;
        !          1323:                        }
        !          1324:                    }
        !          1325:                  else if (CMD_IPV4_PREFIX (str))
        !          1326:                    {
        !          1327:                      if (cmd_ipv4_prefix_match (command) == exact_match)
        !          1328:                        {
        !          1329:                          if (match_type < ipv4_prefix_match)
        !          1330:                            match_type = ipv4_prefix_match;
        !          1331:                          matched++;
        !          1332:                        }
        !          1333:                    }
        !          1334:                  else if (CMD_OPTION (str) || CMD_VARIABLE (str))
        !          1335:                    {
        !          1336:                      if (match_type < extend_match)
        !          1337:                        match_type = extend_match;
        !          1338:                      matched++;
        !          1339:                    }
        !          1340:                  else
        !          1341:                    {
        !          1342:                      if (strcmp (command, str) == 0)
        !          1343:                        {
        !          1344:                          match_type = exact_match;
        !          1345:                          matched++;
        !          1346:                        }
        !          1347:                    }
        !          1348:                }
        !          1349:            if (!matched)
        !          1350:              vector_slot (v, i) = NULL;
        !          1351:          }
        !          1352:       }
        !          1353:   return match_type;
        !          1354: }
        !          1355: 
        !          1356: /* Check ambiguous match */
        !          1357: static int
        !          1358: is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
        !          1359: {
        !          1360:   unsigned int i;
        !          1361:   unsigned int j;
        !          1362:   const char *str = NULL;
        !          1363:   struct cmd_element *cmd_element;
        !          1364:   const char *matched = NULL;
        !          1365:   vector descvec;
        !          1366:   struct desc *desc;
        !          1367: 
        !          1368:   for (i = 0; i < vector_active (v); i++)
        !          1369:     if ((cmd_element = vector_slot (v, i)) != NULL)
        !          1370:       {
        !          1371:        int match = 0;
        !          1372: 
        !          1373:        descvec = vector_slot (cmd_element->strvec, index);
        !          1374: 
        !          1375:        for (j = 0; j < vector_active (descvec); j++)
        !          1376:          if ((desc = vector_slot (descvec, j)))
        !          1377:            {
        !          1378:              enum match_type ret;
        !          1379:              
        !          1380:              str = desc->cmd;
        !          1381: 
        !          1382:              switch (type)
        !          1383:                {
        !          1384:                case exact_match:
        !          1385:                  if (!(CMD_OPTION (str) || CMD_VARIABLE (str))
        !          1386:                      && strcmp (command, str) == 0)
        !          1387:                    match++;
        !          1388:                  break;
        !          1389:                case partly_match:
        !          1390:                  if (!(CMD_OPTION (str) || CMD_VARIABLE (str))
        !          1391:                      && strncmp (command, str, strlen (command)) == 0)
        !          1392:                    {
        !          1393:                      if (matched && strcmp (matched, str) != 0)
        !          1394:                        return 1;       /* There is ambiguous match. */
        !          1395:                      else
        !          1396:                        matched = str;
        !          1397:                      match++;
        !          1398:                    }
        !          1399:                  break;
        !          1400:                case range_match:
        !          1401:                  if (cmd_range_match (str, command))
        !          1402:                    {
        !          1403:                      if (matched && strcmp (matched, str) != 0)
        !          1404:                        return 1;
        !          1405:                      else
        !          1406:                        matched = str;
        !          1407:                      match++;
        !          1408:                    }
        !          1409:                  break;
        !          1410: #ifdef HAVE_IPV6
        !          1411:                case ipv6_match:
        !          1412:                  if (CMD_IPV6 (str))
        !          1413:                    match++;
        !          1414:                  break;
        !          1415:                case ipv6_prefix_match:
        !          1416:                  if ((ret = cmd_ipv6_prefix_match (command)) != no_match)
        !          1417:                    {
        !          1418:                      if (ret == partly_match)
        !          1419:                        return 2;       /* There is incomplete match. */
        !          1420: 
        !          1421:                      match++;
        !          1422:                    }
        !          1423:                  break;
        !          1424: #endif /* HAVE_IPV6 */
        !          1425:                case ipv4_match:
        !          1426:                  if (CMD_IPV4 (str))
        !          1427:                    match++;
        !          1428:                  break;
        !          1429:                case ipv4_prefix_match:
        !          1430:                  if ((ret = cmd_ipv4_prefix_match (command)) != no_match)
        !          1431:                    {
        !          1432:                      if (ret == partly_match)
        !          1433:                        return 2;       /* There is incomplete match. */
        !          1434: 
        !          1435:                      match++;
        !          1436:                    }
        !          1437:                  break;
        !          1438:                case extend_match:
        !          1439:                  if (CMD_OPTION (str) || CMD_VARIABLE (str))
        !          1440:                    match++;
        !          1441:                  break;
        !          1442:                case no_match:
        !          1443:                default:
        !          1444:                  break;
        !          1445:                }
        !          1446:            }
        !          1447:        if (!match)
        !          1448:          vector_slot (v, i) = NULL;
        !          1449:       }
        !          1450:   return 0;
        !          1451: }
        !          1452: 
        !          1453: /* If src matches dst return dst string, otherwise return NULL */
        !          1454: static const char *
        !          1455: cmd_entry_function (const char *src, const char *dst)
        !          1456: {
        !          1457:   /* Skip variable arguments. */
        !          1458:   if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) ||
        !          1459:       CMD_IPV4 (dst) || CMD_IPV4_PREFIX (dst) || CMD_RANGE (dst))
        !          1460:     return NULL;
        !          1461: 
        !          1462:   /* In case of 'command \t', given src is NULL string. */
        !          1463:   if (src == NULL)
        !          1464:     return dst;
        !          1465: 
        !          1466:   /* Matched with input string. */
        !          1467:   if (strncmp (src, dst, strlen (src)) == 0)
        !          1468:     return dst;
        !          1469: 
        !          1470:   return NULL;
        !          1471: }
        !          1472: 
        !          1473: /* If src matches dst return dst string, otherwise return NULL */
        !          1474: /* This version will return the dst string always if it is
        !          1475:    CMD_VARIABLE for '?' key processing */
        !          1476: static const char *
        !          1477: cmd_entry_function_desc (const char *src, const char *dst)
        !          1478: {
        !          1479:   if (CMD_VARARG (dst))
        !          1480:     return dst;
        !          1481: 
        !          1482:   if (CMD_RANGE (dst))
        !          1483:     {
        !          1484:       if (cmd_range_match (dst, src))
        !          1485:        return dst;
        !          1486:       else
        !          1487:        return NULL;
        !          1488:     }
        !          1489: 
        !          1490: #ifdef HAVE_IPV6
        !          1491:   if (CMD_IPV6 (dst))
        !          1492:     {
        !          1493:       if (cmd_ipv6_match (src))
        !          1494:        return dst;
        !          1495:       else
        !          1496:        return NULL;
        !          1497:     }
        !          1498: 
        !          1499:   if (CMD_IPV6_PREFIX (dst))
        !          1500:     {
        !          1501:       if (cmd_ipv6_prefix_match (src))
        !          1502:        return dst;
        !          1503:       else
        !          1504:        return NULL;
        !          1505:     }
        !          1506: #endif /* HAVE_IPV6 */
        !          1507: 
        !          1508:   if (CMD_IPV4 (dst))
        !          1509:     {
        !          1510:       if (cmd_ipv4_match (src))
        !          1511:        return dst;
        !          1512:       else
        !          1513:        return NULL;
        !          1514:     }
        !          1515: 
        !          1516:   if (CMD_IPV4_PREFIX (dst))
        !          1517:     {
        !          1518:       if (cmd_ipv4_prefix_match (src))
        !          1519:        return dst;
        !          1520:       else
        !          1521:        return NULL;
        !          1522:     }
        !          1523: 
        !          1524:   /* Optional or variable commands always match on '?' */
        !          1525:   if (CMD_OPTION (dst) || CMD_VARIABLE (dst))
        !          1526:     return dst;
        !          1527: 
        !          1528:   /* In case of 'command \t', given src is NULL string. */
        !          1529:   if (src == NULL)
        !          1530:     return dst;
        !          1531: 
        !          1532:   if (strncmp (src, dst, strlen (src)) == 0)
        !          1533:     return dst;
        !          1534:   else
        !          1535:     return NULL;
        !          1536: }
        !          1537: 
        !          1538: /* Check same string element existence.  If it isn't there return
        !          1539:     1. */
        !          1540: static int
        !          1541: cmd_unique_string (vector v, const char *str)
        !          1542: {
        !          1543:   unsigned int i;
        !          1544:   char *match;
        !          1545: 
        !          1546:   for (i = 0; i < vector_active (v); i++)
        !          1547:     if ((match = vector_slot (v, i)) != NULL)
        !          1548:       if (strcmp (match, str) == 0)
        !          1549:        return 0;
        !          1550:   return 1;
        !          1551: }
        !          1552: 
        !          1553: /* Compare string to description vector.  If there is same string
        !          1554:    return 1 else return 0. */
        !          1555: static int
        !          1556: desc_unique_string (vector v, const char *str)
        !          1557: {
        !          1558:   unsigned int i;
        !          1559:   struct desc *desc;
        !          1560: 
        !          1561:   for (i = 0; i < vector_active (v); i++)
        !          1562:     if ((desc = vector_slot (v, i)) != NULL)
        !          1563:       if (strcmp (desc->cmd, str) == 0)
        !          1564:        return 1;
        !          1565:   return 0;
        !          1566: }
        !          1567: 
        !          1568: static int 
        !          1569: cmd_try_do_shortcut (enum node_type node, char* first_word) {
        !          1570:   if ( first_word != NULL &&
        !          1571:        node != AUTH_NODE &&
        !          1572:        node != VIEW_NODE &&
        !          1573:        node != AUTH_ENABLE_NODE &&
        !          1574:        node != ENABLE_NODE &&
        !          1575:        node != RESTRICTED_NODE &&
        !          1576:        0 == strcmp( "do", first_word ) )
        !          1577:     return 1;
        !          1578:   return 0;
        !          1579: }
        !          1580: 
        !          1581: /* '?' describe command support. */
        !          1582: static vector
        !          1583: cmd_describe_command_real (vector vline, struct vty *vty, int *status)
        !          1584: {
        !          1585:   unsigned int i;
        !          1586:   vector cmd_vector;
        !          1587: #define INIT_MATCHVEC_SIZE 10
        !          1588:   vector matchvec;
        !          1589:   struct cmd_element *cmd_element;
        !          1590:   unsigned int index;
        !          1591:   int ret;
        !          1592:   enum match_type match;
        !          1593:   char *command;
        !          1594: 
        !          1595:   /* Set index. */
        !          1596:   if (vector_active (vline) == 0)
        !          1597:     {
        !          1598:       *status = CMD_ERR_NO_MATCH;
        !          1599:       return NULL;
        !          1600:     }
        !          1601:   else
        !          1602:     index = vector_active (vline) - 1;
        !          1603:   
        !          1604:   /* Make copy vector of current node's command vector. */
        !          1605:   cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
        !          1606: 
        !          1607:   /* Prepare match vector */
        !          1608:   matchvec = vector_init (INIT_MATCHVEC_SIZE);
        !          1609: 
        !          1610:   /* Filter commands. */
        !          1611:   /* Only words precedes current word will be checked in this loop. */
        !          1612:   for (i = 0; i < index; i++)
        !          1613:     if ((command = vector_slot (vline, i)))
        !          1614:       {
        !          1615:        match = cmd_filter_by_completion (command, cmd_vector, i);
        !          1616:        
        !          1617:        if (match == vararg_match)
        !          1618:          {
        !          1619:            struct cmd_element *cmd_element;
        !          1620:            vector descvec;
        !          1621:            unsigned int j, k;
        !          1622: 
        !          1623:            for (j = 0; j < vector_active (cmd_vector); j++)
        !          1624:              if ((cmd_element = vector_slot (cmd_vector, j)) != NULL
        !          1625:                  && (vector_active (cmd_element->strvec)))
        !          1626:                {
        !          1627:                  descvec = vector_slot (cmd_element->strvec,
        !          1628:                                         vector_active (cmd_element->strvec) - 1);
        !          1629:                  for (k = 0; k < vector_active (descvec); k++)
        !          1630:                    {
        !          1631:                      struct desc *desc = vector_slot (descvec, k);
        !          1632:                      vector_set (matchvec, desc);
        !          1633:                    }
        !          1634:                }
        !          1635:             
        !          1636:            vector_set (matchvec, &desc_cr);
        !          1637:            vector_free (cmd_vector);
        !          1638: 
        !          1639:            return matchvec;
        !          1640:          }
        !          1641: 
        !          1642:        if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
        !          1643:          {
        !          1644:            vector_free (cmd_vector);
        !          1645:            vector_free (matchvec);
        !          1646:            *status = CMD_ERR_AMBIGUOUS;
        !          1647:            return NULL;
        !          1648:          }
        !          1649:        else if (ret == 2)
        !          1650:          {
        !          1651:            vector_free (cmd_vector);
        !          1652:            vector_free (matchvec);
        !          1653:            *status = CMD_ERR_NO_MATCH;
        !          1654:            return NULL;
        !          1655:          }
        !          1656:       }
        !          1657: 
        !          1658:   /* Prepare match vector */
        !          1659:   /*  matchvec = vector_init (INIT_MATCHVEC_SIZE); */
        !          1660: 
        !          1661:   /* Make sure that cmd_vector is filtered based on current word */
        !          1662:   command = vector_slot (vline, index);
        !          1663:   if (command)
        !          1664:     match = cmd_filter_by_completion (command, cmd_vector, index);
        !          1665: 
        !          1666:   /* Make description vector. */
        !          1667:   for (i = 0; i < vector_active (cmd_vector); i++)
        !          1668:     if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
        !          1669:       {
        !          1670:        vector strvec = cmd_element->strvec;
        !          1671: 
        !          1672:        /* if command is NULL, index may be equal to vector_active */
        !          1673:        if (command && index >= vector_active (strvec))
        !          1674:          vector_slot (cmd_vector, i) = NULL;
        !          1675:        else
        !          1676:          {
        !          1677:            /* Check if command is completed. */
        !          1678:            if (command == NULL && index == vector_active (strvec))
        !          1679:              {
        !          1680:                if (!desc_unique_string (matchvec, command_cr))
        !          1681:                  vector_set (matchvec, &desc_cr);
        !          1682:              }
        !          1683:            else
        !          1684:              {
        !          1685:                unsigned int j;
        !          1686:                vector descvec = vector_slot (strvec, index);
        !          1687:                struct desc *desc;
        !          1688: 
        !          1689:                for (j = 0; j < vector_active (descvec); j++)
        !          1690:                  if ((desc = vector_slot (descvec, j)))
        !          1691:                    {
        !          1692:                      const char *string;
        !          1693: 
        !          1694:                      string = cmd_entry_function_desc (command, desc->cmd);
        !          1695:                      if (string)
        !          1696:                        {
        !          1697:                          /* Uniqueness check */
        !          1698:                          if (!desc_unique_string (matchvec, string))
        !          1699:                            vector_set (matchvec, desc);
        !          1700:                        }
        !          1701:                    }
        !          1702:              }
        !          1703:          }
        !          1704:       }
        !          1705:   vector_free (cmd_vector);
        !          1706: 
        !          1707:   if (vector_slot (matchvec, 0) == NULL)
        !          1708:     {
        !          1709:       vector_free (matchvec);
        !          1710:       *status = CMD_ERR_NO_MATCH;
        !          1711:       return NULL;
        !          1712:     }
        !          1713: 
        !          1714:   *status = CMD_SUCCESS;
        !          1715:   return matchvec;
        !          1716: }
        !          1717: 
        !          1718: vector
        !          1719: cmd_describe_command (vector vline, struct vty *vty, int *status)
        !          1720: {
        !          1721:   vector ret;
        !          1722: 
        !          1723:   if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
        !          1724:     {
        !          1725:       enum node_type onode;
        !          1726:       vector shifted_vline;
        !          1727:       unsigned int index;
        !          1728: 
        !          1729:       onode = vty->node;
        !          1730:       vty->node = ENABLE_NODE;
        !          1731:       /* We can try it on enable node, cos' the vty is authenticated */
        !          1732: 
        !          1733:       shifted_vline = vector_init (vector_count(vline));
        !          1734:       /* use memcpy? */
        !          1735:       for (index = 1; index < vector_active (vline); index++) 
        !          1736:        {
        !          1737:          vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
        !          1738:        }
        !          1739: 
        !          1740:       ret = cmd_describe_command_real (shifted_vline, vty, status);
        !          1741: 
        !          1742:       vector_free(shifted_vline);
        !          1743:       vty->node = onode;
        !          1744:       return ret;
        !          1745:   }
        !          1746: 
        !          1747: 
        !          1748:   return cmd_describe_command_real (vline, vty, status);
        !          1749: }
        !          1750: 
        !          1751: 
        !          1752: /* Check LCD of matched command. */
        !          1753: static int
        !          1754: cmd_lcd (char **matched)
        !          1755: {
        !          1756:   int i;
        !          1757:   int j;
        !          1758:   int lcd = -1;
        !          1759:   char *s1, *s2;
        !          1760:   char c1, c2;
        !          1761: 
        !          1762:   if (matched[0] == NULL || matched[1] == NULL)
        !          1763:     return 0;
        !          1764: 
        !          1765:   for (i = 1; matched[i] != NULL; i++)
        !          1766:     {
        !          1767:       s1 = matched[i - 1];
        !          1768:       s2 = matched[i];
        !          1769: 
        !          1770:       for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++)
        !          1771:        if (c1 != c2)
        !          1772:          break;
        !          1773: 
        !          1774:       if (lcd < 0)
        !          1775:        lcd = j;
        !          1776:       else
        !          1777:        {
        !          1778:          if (lcd > j)
        !          1779:            lcd = j;
        !          1780:        }
        !          1781:     }
        !          1782:   return lcd;
        !          1783: }
        !          1784: 
        !          1785: /* Command line completion support. */
        !          1786: static char **
        !          1787: cmd_complete_command_real (vector vline, struct vty *vty, int *status)
        !          1788: {
        !          1789:   unsigned int i;
        !          1790:   vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
        !          1791: #define INIT_MATCHVEC_SIZE 10
        !          1792:   vector matchvec;
        !          1793:   struct cmd_element *cmd_element;
        !          1794:   unsigned int index;
        !          1795:   char **match_str;
        !          1796:   struct desc *desc;
        !          1797:   vector descvec;
        !          1798:   char *command;
        !          1799:   int lcd;
        !          1800: 
        !          1801:   if (vector_active (vline) == 0)
        !          1802:     {
        !          1803:       vector_free (cmd_vector);
        !          1804:       *status = CMD_ERR_NO_MATCH;
        !          1805:       return NULL;
        !          1806:     }
        !          1807:   else
        !          1808:     index = vector_active (vline) - 1;
        !          1809: 
        !          1810:   /* First, filter by preceeding command string */
        !          1811:   for (i = 0; i < index; i++)
        !          1812:     if ((command = vector_slot (vline, i)))
        !          1813:       {
        !          1814:        enum match_type match;
        !          1815:        int ret;
        !          1816: 
        !          1817:        /* First try completion match, if there is exactly match return 1 */
        !          1818:        match = cmd_filter_by_completion (command, cmd_vector, i);
        !          1819: 
        !          1820:        /* If there is exact match then filter ambiguous match else check
        !          1821:           ambiguousness. */
        !          1822:        if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
        !          1823:          {
        !          1824:            vector_free (cmd_vector);
        !          1825:            *status = CMD_ERR_AMBIGUOUS;
        !          1826:            return NULL;
        !          1827:          }
        !          1828:        /*
        !          1829:           else if (ret == 2)
        !          1830:           {
        !          1831:           vector_free (cmd_vector);
        !          1832:           *status = CMD_ERR_NO_MATCH;
        !          1833:           return NULL;
        !          1834:           }
        !          1835:         */
        !          1836:       }
        !          1837:   
        !          1838:   /* Prepare match vector. */
        !          1839:   matchvec = vector_init (INIT_MATCHVEC_SIZE);
        !          1840: 
        !          1841:   /* Now we got into completion */
        !          1842:   for (i = 0; i < vector_active (cmd_vector); i++)
        !          1843:     if ((cmd_element = vector_slot (cmd_vector, i)))
        !          1844:       {
        !          1845:        const char *string;
        !          1846:        vector strvec = cmd_element->strvec;
        !          1847: 
        !          1848:        /* Check field length */
        !          1849:        if (index >= vector_active (strvec))
        !          1850:          vector_slot (cmd_vector, i) = NULL;
        !          1851:        else
        !          1852:          {
        !          1853:            unsigned int j;
        !          1854: 
        !          1855:            descvec = vector_slot (strvec, index);
        !          1856:            for (j = 0; j < vector_active (descvec); j++)
        !          1857:              if ((desc = vector_slot (descvec, j)))
        !          1858:                {
        !          1859:                  if ((string = 
        !          1860:                       cmd_entry_function (vector_slot (vline, index),
        !          1861:                                           desc->cmd)))
        !          1862:                    if (cmd_unique_string (matchvec, string))
        !          1863:                      vector_set (matchvec, XSTRDUP (MTYPE_TMP, string));
        !          1864:                }
        !          1865:          }
        !          1866:       }
        !          1867: 
        !          1868:   /* We don't need cmd_vector any more. */
        !          1869:   vector_free (cmd_vector);
        !          1870: 
        !          1871:   /* No matched command */
        !          1872:   if (vector_slot (matchvec, 0) == NULL)
        !          1873:     {
        !          1874:       vector_free (matchvec);
        !          1875: 
        !          1876:       /* In case of 'command \t' pattern.  Do you need '?' command at
        !          1877:          the end of the line. */
        !          1878:       if (vector_slot (vline, index) == '\0')
        !          1879:        *status = CMD_ERR_NOTHING_TODO;
        !          1880:       else
        !          1881:        *status = CMD_ERR_NO_MATCH;
        !          1882:       return NULL;
        !          1883:     }
        !          1884: 
        !          1885:   /* Only one matched */
        !          1886:   if (vector_slot (matchvec, 1) == NULL)
        !          1887:     {
        !          1888:       match_str = (char **) matchvec->index;
        !          1889:       vector_only_wrapper_free (matchvec);
        !          1890:       *status = CMD_COMPLETE_FULL_MATCH;
        !          1891:       return match_str;
        !          1892:     }
        !          1893:   /* Make it sure last element is NULL. */
        !          1894:   vector_set (matchvec, NULL);
        !          1895: 
        !          1896:   /* Check LCD of matched strings. */
        !          1897:   if (vector_slot (vline, index) != NULL)
        !          1898:     {
        !          1899:       lcd = cmd_lcd ((char **) matchvec->index);
        !          1900: 
        !          1901:       if (lcd)
        !          1902:        {
        !          1903:          int len = strlen (vector_slot (vline, index));
        !          1904: 
        !          1905:          if (len < lcd)
        !          1906:            {
        !          1907:              char *lcdstr;
        !          1908: 
        !          1909:              lcdstr = XMALLOC (MTYPE_STRVEC, lcd + 1);
        !          1910:              memcpy (lcdstr, matchvec->index[0], lcd);
        !          1911:              lcdstr[lcd] = '\0';
        !          1912: 
        !          1913:              /* match_str = (char **) &lcdstr; */
        !          1914: 
        !          1915:              /* Free matchvec. */
        !          1916:              for (i = 0; i < vector_active (matchvec); i++)
        !          1917:                {
        !          1918:                  if (vector_slot (matchvec, i))
        !          1919:                    XFREE (MTYPE_STRVEC, vector_slot (matchvec, i));
        !          1920:                }
        !          1921:              vector_free (matchvec);
        !          1922: 
        !          1923:              /* Make new matchvec. */
        !          1924:              matchvec = vector_init (INIT_MATCHVEC_SIZE);
        !          1925:              vector_set (matchvec, lcdstr);
        !          1926:              match_str = (char **) matchvec->index;
        !          1927:              vector_only_wrapper_free (matchvec);
        !          1928: 
        !          1929:              *status = CMD_COMPLETE_MATCH;
        !          1930:              return match_str;
        !          1931:            }
        !          1932:        }
        !          1933:     }
        !          1934: 
        !          1935:   match_str = (char **) matchvec->index;
        !          1936:   vector_only_wrapper_free (matchvec);
        !          1937:   *status = CMD_COMPLETE_LIST_MATCH;
        !          1938:   return match_str;
        !          1939: }
        !          1940: 
        !          1941: char **
        !          1942: cmd_complete_command (vector vline, struct vty *vty, int *status)
        !          1943: {
        !          1944:   char **ret;
        !          1945: 
        !          1946:   if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
        !          1947:     {
        !          1948:       enum node_type onode;
        !          1949:       vector shifted_vline;
        !          1950:       unsigned int index;
        !          1951: 
        !          1952:       onode = vty->node;
        !          1953:       vty->node = ENABLE_NODE;
        !          1954:       /* We can try it on enable node, cos' the vty is authenticated */
        !          1955: 
        !          1956:       shifted_vline = vector_init (vector_count(vline));
        !          1957:       /* use memcpy? */
        !          1958:       for (index = 1; index < vector_active (vline); index++) 
        !          1959:        {
        !          1960:          vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
        !          1961:        }
        !          1962: 
        !          1963:       ret = cmd_complete_command_real (shifted_vline, vty, status);
        !          1964: 
        !          1965:       vector_free(shifted_vline);
        !          1966:       vty->node = onode;
        !          1967:       return ret;
        !          1968:   }
        !          1969: 
        !          1970: 
        !          1971:   return cmd_complete_command_real (vline, vty, status);
        !          1972: }
        !          1973: 
        !          1974: /* return parent node */
        !          1975: /* MUST eventually converge on CONFIG_NODE */
        !          1976: enum node_type
        !          1977: node_parent ( enum node_type node )
        !          1978: {
        !          1979:   enum node_type ret;
        !          1980: 
        !          1981:   assert (node > CONFIG_NODE);
        !          1982: 
        !          1983:   switch (node)
        !          1984:     {
        !          1985:     case BGP_VPNV4_NODE:
        !          1986:     case BGP_IPV4_NODE:
        !          1987:     case BGP_IPV4M_NODE:
        !          1988:     case BGP_IPV6_NODE:
        !          1989:     case BGP_IPV6M_NODE:
        !          1990:       ret = BGP_NODE;
        !          1991:       break;
        !          1992:     case KEYCHAIN_KEY_NODE:
        !          1993:       ret = KEYCHAIN_NODE;
        !          1994:       break;
        !          1995:     default:
        !          1996:       ret = CONFIG_NODE;
        !          1997:     }
        !          1998: 
        !          1999:   return ret;
        !          2000: }
        !          2001: 
        !          2002: /* Execute command by argument vline vector. */
        !          2003: static int
        !          2004: cmd_execute_command_real (vector vline, struct vty *vty,
        !          2005:                          struct cmd_element **cmd)
        !          2006: {
        !          2007:   unsigned int i;
        !          2008:   unsigned int index;
        !          2009:   vector cmd_vector;
        !          2010:   struct cmd_element *cmd_element;
        !          2011:   struct cmd_element *matched_element;
        !          2012:   unsigned int matched_count, incomplete_count;
        !          2013:   int argc;
        !          2014:   const char *argv[CMD_ARGC_MAX];
        !          2015:   enum match_type match = 0;
        !          2016:   int varflag;
        !          2017:   char *command;
        !          2018: 
        !          2019:   /* Make copy of command elements. */
        !          2020:   cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
        !          2021: 
        !          2022:   for (index = 0; index < vector_active (vline); index++)
        !          2023:     if ((command = vector_slot (vline, index)))
        !          2024:       {
        !          2025:        int ret;
        !          2026: 
        !          2027:        match = cmd_filter_by_completion (command, cmd_vector, index);
        !          2028: 
        !          2029:        if (match == vararg_match)
        !          2030:          break;
        !          2031:         
        !          2032:        ret = is_cmd_ambiguous (command, cmd_vector, index, match);
        !          2033: 
        !          2034:        if (ret == 1)
        !          2035:          {
        !          2036:            vector_free (cmd_vector);
        !          2037:            return CMD_ERR_AMBIGUOUS;
        !          2038:          }
        !          2039:        else if (ret == 2)
        !          2040:          {
        !          2041:            vector_free (cmd_vector);
        !          2042:            return CMD_ERR_NO_MATCH;
        !          2043:          }
        !          2044:       }
        !          2045: 
        !          2046:   /* Check matched count. */
        !          2047:   matched_element = NULL;
        !          2048:   matched_count = 0;
        !          2049:   incomplete_count = 0;
        !          2050: 
        !          2051:   for (i = 0; i < vector_active (cmd_vector); i++)
        !          2052:     if ((cmd_element = vector_slot (cmd_vector, i)))
        !          2053:       {
        !          2054:        if (match == vararg_match || index >= cmd_element->cmdsize)
        !          2055:          {
        !          2056:            matched_element = cmd_element;
        !          2057: #if 0
        !          2058:            printf ("DEBUG: %s\n", cmd_element->string);
        !          2059: #endif
        !          2060:            matched_count++;
        !          2061:          }
        !          2062:        else
        !          2063:          {
        !          2064:            incomplete_count++;
        !          2065:          }
        !          2066:       }
        !          2067: 
        !          2068:   /* Finish of using cmd_vector. */
        !          2069:   vector_free (cmd_vector);
        !          2070: 
        !          2071:   /* To execute command, matched_count must be 1. */
        !          2072:   if (matched_count == 0)
        !          2073:     {
        !          2074:       if (incomplete_count)
        !          2075:        return CMD_ERR_INCOMPLETE;
        !          2076:       else
        !          2077:        return CMD_ERR_NO_MATCH;
        !          2078:     }
        !          2079: 
        !          2080:   if (matched_count > 1)
        !          2081:     return CMD_ERR_AMBIGUOUS;
        !          2082: 
        !          2083:   /* Argument treatment */
        !          2084:   varflag = 0;
        !          2085:   argc = 0;
        !          2086: 
        !          2087:   for (i = 0; i < vector_active (vline); i++)
        !          2088:     {
        !          2089:       if (varflag)
        !          2090:        argv[argc++] = vector_slot (vline, i);
        !          2091:       else
        !          2092:        {
        !          2093:          vector descvec = vector_slot (matched_element->strvec, i);
        !          2094: 
        !          2095:          if (vector_active (descvec) == 1)
        !          2096:            {
        !          2097:              struct desc *desc = vector_slot (descvec, 0);
        !          2098: 
        !          2099:              if (CMD_VARARG (desc->cmd))
        !          2100:                varflag = 1;
        !          2101: 
        !          2102:              if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd))
        !          2103:                argv[argc++] = vector_slot (vline, i);
        !          2104:            }
        !          2105:          else
        !          2106:            argv[argc++] = vector_slot (vline, i);
        !          2107:        }
        !          2108: 
        !          2109:       if (argc >= CMD_ARGC_MAX)
        !          2110:        return CMD_ERR_EXEED_ARGC_MAX;
        !          2111:     }
        !          2112: 
        !          2113:   /* For vtysh execution. */
        !          2114:   if (cmd)
        !          2115:     *cmd = matched_element;
        !          2116: 
        !          2117:   if (matched_element->daemon)
        !          2118:     return CMD_SUCCESS_DAEMON;
        !          2119: 
        !          2120:   /* Execute matched command. */
        !          2121:   return (*matched_element->func) (matched_element, vty, argc, argv);
        !          2122: }
        !          2123: 
        !          2124: int
        !          2125: cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd,
        !          2126:                     int vtysh) {
        !          2127:   int ret, saved_ret, tried = 0;
        !          2128:   enum node_type onode, try_node;
        !          2129: 
        !          2130:   onode = try_node = vty->node;
        !          2131: 
        !          2132:   if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
        !          2133:     {
        !          2134:       vector shifted_vline;
        !          2135:       unsigned int index;
        !          2136: 
        !          2137:       vty->node = ENABLE_NODE;
        !          2138:       /* We can try it on enable node, cos' the vty is authenticated */
        !          2139: 
        !          2140:       shifted_vline = vector_init (vector_count(vline));
        !          2141:       /* use memcpy? */
        !          2142:       for (index = 1; index < vector_active (vline); index++) 
        !          2143:        {
        !          2144:          vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
        !          2145:        }
        !          2146: 
        !          2147:       ret = cmd_execute_command_real (shifted_vline, vty, cmd);
        !          2148: 
        !          2149:       vector_free(shifted_vline);
        !          2150:       vty->node = onode;
        !          2151:       return ret;
        !          2152:   }
        !          2153: 
        !          2154: 
        !          2155:   saved_ret = ret = cmd_execute_command_real (vline, vty, cmd);
        !          2156: 
        !          2157:   if (vtysh)
        !          2158:     return saved_ret;
        !          2159: 
        !          2160:   /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
        !          2161:   while ( ret != CMD_SUCCESS && ret != CMD_WARNING 
        !          2162:          && vty->node > CONFIG_NODE )
        !          2163:     {
        !          2164:       try_node = node_parent(try_node);
        !          2165:       vty->node = try_node;
        !          2166:       ret = cmd_execute_command_real (vline, vty, cmd);
        !          2167:       tried = 1;
        !          2168:       if (ret == CMD_SUCCESS || ret == CMD_WARNING)
        !          2169:        {
        !          2170:          /* succesfull command, leave the node as is */
        !          2171:          return ret;
        !          2172:        }
        !          2173:     }
        !          2174:   /* no command succeeded, reset the vty to the original node and
        !          2175:      return the error for this node */
        !          2176:   if ( tried )
        !          2177:     vty->node = onode;
        !          2178:   return saved_ret;
        !          2179: }
        !          2180: 
        !          2181: /* Execute command by argument readline. */
        !          2182: int
        !          2183: cmd_execute_command_strict (vector vline, struct vty *vty,
        !          2184:                            struct cmd_element **cmd)
        !          2185: {
        !          2186:   unsigned int i;
        !          2187:   unsigned int index;
        !          2188:   vector cmd_vector;
        !          2189:   struct cmd_element *cmd_element;
        !          2190:   struct cmd_element *matched_element;
        !          2191:   unsigned int matched_count, incomplete_count;
        !          2192:   int argc;
        !          2193:   const char *argv[CMD_ARGC_MAX];
        !          2194:   int varflag;
        !          2195:   enum match_type match = 0;
        !          2196:   char *command;
        !          2197: 
        !          2198:   /* Make copy of command element */
        !          2199:   cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
        !          2200: 
        !          2201:   for (index = 0; index < vector_active (vline); index++)
        !          2202:     if ((command = vector_slot (vline, index)))
        !          2203:       {
        !          2204:        int ret;
        !          2205:        
        !          2206:        match = cmd_filter_by_string (vector_slot (vline, index),
        !          2207:                                      cmd_vector, index);
        !          2208: 
        !          2209:        /* If command meets '.VARARG' then finish matching. */
        !          2210:        if (match == vararg_match)
        !          2211:          break;
        !          2212:         
        !          2213:        ret = is_cmd_ambiguous (command, cmd_vector, index, match);
        !          2214:        if (ret == 1)
        !          2215:          {
        !          2216:            vector_free (cmd_vector);
        !          2217:            return CMD_ERR_AMBIGUOUS;
        !          2218:          }
        !          2219:        if (ret == 2)
        !          2220:          {
        !          2221:            vector_free (cmd_vector);
        !          2222:            return CMD_ERR_NO_MATCH;
        !          2223:          }
        !          2224:       }
        !          2225: 
        !          2226:   /* Check matched count. */
        !          2227:   matched_element = NULL;
        !          2228:   matched_count = 0;
        !          2229:   incomplete_count = 0;
        !          2230:   for (i = 0; i < vector_active (cmd_vector); i++)
        !          2231:     if (vector_slot (cmd_vector, i) != NULL)
        !          2232:       {
        !          2233:        cmd_element = vector_slot (cmd_vector, i);
        !          2234: 
        !          2235:        if (match == vararg_match || index >= cmd_element->cmdsize)
        !          2236:          {
        !          2237:            matched_element = cmd_element;
        !          2238:            matched_count++;
        !          2239:          }
        !          2240:        else
        !          2241:          incomplete_count++;
        !          2242:       }
        !          2243: 
        !          2244:   /* Finish of using cmd_vector. */
        !          2245:   vector_free (cmd_vector);
        !          2246: 
        !          2247:   /* To execute command, matched_count must be 1. */
        !          2248:   if (matched_count == 0)
        !          2249:     {
        !          2250:       if (incomplete_count)
        !          2251:        return CMD_ERR_INCOMPLETE;
        !          2252:       else
        !          2253:        return CMD_ERR_NO_MATCH;
        !          2254:     }
        !          2255: 
        !          2256:   if (matched_count > 1)
        !          2257:     return CMD_ERR_AMBIGUOUS;
        !          2258: 
        !          2259:   /* Argument treatment */
        !          2260:   varflag = 0;
        !          2261:   argc = 0;
        !          2262: 
        !          2263:   for (i = 0; i < vector_active (vline); i++)
        !          2264:     {
        !          2265:       if (varflag)
        !          2266:        argv[argc++] = vector_slot (vline, i);
        !          2267:       else
        !          2268:        {
        !          2269:          vector descvec = vector_slot (matched_element->strvec, i);
        !          2270: 
        !          2271:          if (vector_active (descvec) == 1)
        !          2272:            {
        !          2273:              struct desc *desc = vector_slot (descvec, 0);
        !          2274: 
        !          2275:              if (CMD_VARARG (desc->cmd))
        !          2276:                varflag = 1;
        !          2277: 
        !          2278:              if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd))
        !          2279:                argv[argc++] = vector_slot (vline, i);
        !          2280:            }
        !          2281:          else
        !          2282:            argv[argc++] = vector_slot (vline, i);
        !          2283:        }
        !          2284: 
        !          2285:       if (argc >= CMD_ARGC_MAX)
        !          2286:        return CMD_ERR_EXEED_ARGC_MAX;
        !          2287:     }
        !          2288: 
        !          2289:   /* For vtysh execution. */
        !          2290:   if (cmd)
        !          2291:     *cmd = matched_element;
        !          2292: 
        !          2293:   if (matched_element->daemon)
        !          2294:     return CMD_SUCCESS_DAEMON;
        !          2295: 
        !          2296:   /* Now execute matched command */
        !          2297:   return (*matched_element->func) (matched_element, vty, argc, argv);
        !          2298: }
        !          2299: 
        !          2300: /* Configration make from file. */
        !          2301: int
        !          2302: config_from_file (struct vty *vty, FILE *fp)
        !          2303: {
        !          2304:   int ret;
        !          2305:   vector vline;
        !          2306: 
        !          2307:   while (fgets (vty->buf, VTY_BUFSIZ, fp))
        !          2308:     {
        !          2309:       vline = cmd_make_strvec (vty->buf);
        !          2310: 
        !          2311:       /* In case of comment line */
        !          2312:       if (vline == NULL)
        !          2313:        continue;
        !          2314:       /* Execute configuration command : this is strict match */
        !          2315:       ret = cmd_execute_command_strict (vline, vty, NULL);
        !          2316: 
        !          2317:       /* Try again with setting node to CONFIG_NODE */
        !          2318:       while (ret != CMD_SUCCESS && ret != CMD_WARNING
        !          2319:             && ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE)
        !          2320:        {
        !          2321:          vty->node = node_parent(vty->node);
        !          2322:          ret = cmd_execute_command_strict (vline, vty, NULL);
        !          2323:        }
        !          2324: 
        !          2325:       cmd_free_strvec (vline);
        !          2326: 
        !          2327:       if (ret != CMD_SUCCESS && ret != CMD_WARNING
        !          2328:          && ret != CMD_ERR_NOTHING_TODO)
        !          2329:        return ret;
        !          2330:     }
        !          2331:   return CMD_SUCCESS;
        !          2332: }
        !          2333: 
        !          2334: /* Configration from terminal */
        !          2335: DEFUN (config_terminal,
        !          2336:        config_terminal_cmd,
        !          2337:        "configure terminal",
        !          2338:        "Configuration from vty interface\n"
        !          2339:        "Configuration terminal\n")
        !          2340: {
        !          2341:   if (vty_config_lock (vty))
        !          2342:     vty->node = CONFIG_NODE;
        !          2343:   else
        !          2344:     {
        !          2345:       vty_out (vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE);
        !          2346:       return CMD_WARNING;
        !          2347:     }
        !          2348:   return CMD_SUCCESS;
        !          2349: }
        !          2350: 
        !          2351: /* Enable command */
        !          2352: DEFUN (enable, 
        !          2353:        config_enable_cmd,
        !          2354:        "enable",
        !          2355:        "Turn on privileged mode command\n")
        !          2356: {
        !          2357:   /* If enable password is NULL, change to ENABLE_NODE */
        !          2358:   if ((host.enable == NULL && host.enable_encrypt == NULL) ||
        !          2359:       vty->type == VTY_SHELL_SERV)
        !          2360:     vty->node = ENABLE_NODE;
        !          2361:   else
        !          2362:     vty->node = AUTH_ENABLE_NODE;
        !          2363: 
        !          2364:   return CMD_SUCCESS;
        !          2365: }
        !          2366: 
        !          2367: /* Disable command */
        !          2368: DEFUN (disable, 
        !          2369:        config_disable_cmd,
        !          2370:        "disable",
        !          2371:        "Turn off privileged mode command\n")
        !          2372: {
        !          2373:   if (vty->node == ENABLE_NODE)
        !          2374:     vty->node = VIEW_NODE;
        !          2375:   return CMD_SUCCESS;
        !          2376: }
        !          2377: 
        !          2378: /* Down vty node level. */
        !          2379: DEFUN (config_exit,
        !          2380:        config_exit_cmd,
        !          2381:        "exit",
        !          2382:        "Exit current mode and down to previous mode\n")
        !          2383: {
        !          2384:   switch (vty->node)
        !          2385:     {
        !          2386:     case VIEW_NODE:
        !          2387:     case ENABLE_NODE:
        !          2388:     case RESTRICTED_NODE:
        !          2389:       if (vty_shell (vty))
        !          2390:        exit (0);
        !          2391:       else
        !          2392:        vty->status = VTY_CLOSE;
        !          2393:       break;
        !          2394:     case CONFIG_NODE:
        !          2395:       vty->node = ENABLE_NODE;
        !          2396:       vty_config_unlock (vty);
        !          2397:       break;
        !          2398:     case INTERFACE_NODE:
        !          2399:     case ZEBRA_NODE:
        !          2400:     case BGP_NODE:
        !          2401:     case RIP_NODE:
        !          2402:     case RIPNG_NODE:
        !          2403:     case OSPF_NODE:
        !          2404:     case OSPF6_NODE:
        !          2405:     case ISIS_NODE:
        !          2406:     case KEYCHAIN_NODE:
        !          2407:     case MASC_NODE:
        !          2408:     case RMAP_NODE:
        !          2409:     case VTY_NODE:
        !          2410:       vty->node = CONFIG_NODE;
        !          2411:       break;
        !          2412:     case BGP_VPNV4_NODE:
        !          2413:     case BGP_IPV4_NODE:
        !          2414:     case BGP_IPV4M_NODE:
        !          2415:     case BGP_IPV6_NODE:
        !          2416:     case BGP_IPV6M_NODE:
        !          2417:       vty->node = BGP_NODE;
        !          2418:       break;
        !          2419:     case KEYCHAIN_KEY_NODE:
        !          2420:       vty->node = KEYCHAIN_NODE;
        !          2421:       break;
        !          2422:     default:
        !          2423:       break;
        !          2424:     }
        !          2425:   return CMD_SUCCESS;
        !          2426: }
        !          2427: 
        !          2428: /* quit is alias of exit. */
        !          2429: ALIAS (config_exit,
        !          2430:        config_quit_cmd,
        !          2431:        "quit",
        !          2432:        "Exit current mode and down to previous mode\n")
        !          2433:        
        !          2434: /* End of configuration. */
        !          2435: DEFUN (config_end,
        !          2436:        config_end_cmd,
        !          2437:        "end",
        !          2438:        "End current mode and change to enable mode.")
        !          2439: {
        !          2440:   switch (vty->node)
        !          2441:     {
        !          2442:     case VIEW_NODE:
        !          2443:     case ENABLE_NODE:
        !          2444:     case RESTRICTED_NODE:
        !          2445:       /* Nothing to do. */
        !          2446:       break;
        !          2447:     case CONFIG_NODE:
        !          2448:     case INTERFACE_NODE:
        !          2449:     case ZEBRA_NODE:
        !          2450:     case RIP_NODE:
        !          2451:     case RIPNG_NODE:
        !          2452:     case BGP_NODE:
        !          2453:     case BGP_VPNV4_NODE:
        !          2454:     case BGP_IPV4_NODE:
        !          2455:     case BGP_IPV4M_NODE:
        !          2456:     case BGP_IPV6_NODE:
        !          2457:     case BGP_IPV6M_NODE:
        !          2458:     case RMAP_NODE:
        !          2459:     case OSPF_NODE:
        !          2460:     case OSPF6_NODE:
        !          2461:     case ISIS_NODE:
        !          2462:     case KEYCHAIN_NODE:
        !          2463:     case KEYCHAIN_KEY_NODE:
        !          2464:     case MASC_NODE:
        !          2465:     case VTY_NODE:
        !          2466:       vty_config_unlock (vty);
        !          2467:       vty->node = ENABLE_NODE;
        !          2468:       break;
        !          2469:     default:
        !          2470:       break;
        !          2471:     }
        !          2472:   return CMD_SUCCESS;
        !          2473: }
        !          2474: 
        !          2475: /* Show version. */
        !          2476: DEFUN (show_version,
        !          2477:        show_version_cmd,
        !          2478:        "show version",
        !          2479:        SHOW_STR
        !          2480:        "Displays zebra version\n")
        !          2481: {
        !          2482:   vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name?host.name:"",
        !          2483:           VTY_NEWLINE);
        !          2484:   vty_out (vty, "%s%s", QUAGGA_COPYRIGHT, VTY_NEWLINE);
        !          2485: 
        !          2486:   return CMD_SUCCESS;
        !          2487: }
        !          2488: 
        !          2489: /* Help display function for all node. */
        !          2490: DEFUN (config_help,
        !          2491:        config_help_cmd,
        !          2492:        "help",
        !          2493:        "Description of the interactive help system\n")
        !          2494: {
        !          2495:   vty_out (vty, 
        !          2496:           "Quagga VTY provides advanced help feature.  When you need help,%s\
        !          2497: anytime at the command line please press '?'.%s\
        !          2498: %s\
        !          2499: If nothing matches, the help list will be empty and you must backup%s\
        !          2500:  until entering a '?' shows the available options.%s\
        !          2501: Two styles of help are provided:%s\
        !          2502: 1. Full help is available when you are ready to enter a%s\
        !          2503: command argument (e.g. 'show ?') and describes each possible%s\
        !          2504: argument.%s\
        !          2505: 2. Partial help is provided when an abbreviated argument is entered%s\
        !          2506:    and you want to know what arguments match the input%s\
        !          2507:    (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
        !          2508:           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
        !          2509:           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
        !          2510:   return CMD_SUCCESS;
        !          2511: }
        !          2512: 
        !          2513: /* Help display function for all node. */
        !          2514: DEFUN (config_list,
        !          2515:        config_list_cmd,
        !          2516:        "list",
        !          2517:        "Print command list\n")
        !          2518: {
        !          2519:   unsigned int i;
        !          2520:   struct cmd_node *cnode = vector_slot (cmdvec, vty->node);
        !          2521:   struct cmd_element *cmd;
        !          2522: 
        !          2523:   for (i = 0; i < vector_active (cnode->cmd_vector); i++)
        !          2524:     if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL
        !          2525:         && !(cmd->attr == CMD_ATTR_DEPRECATED
        !          2526:              || cmd->attr == CMD_ATTR_HIDDEN))
        !          2527:       vty_out (vty, "  %s%s", cmd->string,
        !          2528:               VTY_NEWLINE);
        !          2529:   return CMD_SUCCESS;
        !          2530: }
        !          2531: 
        !          2532: /* Write current configuration into file. */
        !          2533: DEFUN (config_write_file, 
        !          2534:        config_write_file_cmd,
        !          2535:        "write file",  
        !          2536:        "Write running configuration to memory, network, or terminal\n"
        !          2537:        "Write to configuration file\n")
        !          2538: {
        !          2539:   unsigned int i;
        !          2540:   int fd;
        !          2541:   struct cmd_node *node;
        !          2542:   char *config_file;
        !          2543:   char *config_file_tmp = NULL;
        !          2544:   char *config_file_sav = NULL;
        !          2545:   int ret = CMD_WARNING;
        !          2546:   struct vty *file_vty;
        !          2547: 
        !          2548:   /* Check and see if we are operating under vtysh configuration */
        !          2549:   if (host.config == NULL)
        !          2550:     {
        !          2551:       vty_out (vty, "Can't save to configuration file, using vtysh.%s",
        !          2552:               VTY_NEWLINE);
        !          2553:       return CMD_WARNING;
        !          2554:     }
        !          2555: 
        !          2556:   /* Get filename. */
        !          2557:   config_file = host.config;
        !          2558:   
        !          2559:   config_file_sav =
        !          2560:     XMALLOC (MTYPE_TMP, strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1);
        !          2561:   strcpy (config_file_sav, config_file);
        !          2562:   strcat (config_file_sav, CONF_BACKUP_EXT);
        !          2563: 
        !          2564: 
        !          2565:   config_file_tmp = XMALLOC (MTYPE_TMP, strlen (config_file) + 8);
        !          2566:   sprintf (config_file_tmp, "%s.XXXXXX", config_file);
        !          2567:   
        !          2568:   /* Open file to configuration write. */
        !          2569:   fd = mkstemp (config_file_tmp);
        !          2570:   if (fd < 0)
        !          2571:     {
        !          2572:       vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp,
        !          2573:               VTY_NEWLINE);
        !          2574:       goto finished;
        !          2575:     }
        !          2576:   
        !          2577:   /* Make vty for configuration file. */
        !          2578:   file_vty = vty_new ();
        !          2579:   file_vty->fd = fd;
        !          2580:   file_vty->type = VTY_FILE;
        !          2581: 
        !          2582:   /* Config file header print. */
        !          2583:   vty_out (file_vty, "!\n! Zebra configuration saved from vty\n!   ");
        !          2584:   vty_time_print (file_vty, 1);
        !          2585:   vty_out (file_vty, "!\n");
        !          2586: 
        !          2587:   for (i = 0; i < vector_active (cmdvec); i++)
        !          2588:     if ((node = vector_slot (cmdvec, i)) && node->func)
        !          2589:       {
        !          2590:        if ((*node->func) (file_vty))
        !          2591:          vty_out (file_vty, "!\n");
        !          2592:       }
        !          2593:   vty_close (file_vty);
        !          2594: 
        !          2595:   if (unlink (config_file_sav) != 0)
        !          2596:     if (errno != ENOENT)
        !          2597:       {
        !          2598:        vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav,
        !          2599:                 VTY_NEWLINE);
        !          2600:         goto finished;
        !          2601:       }
        !          2602:   if (link (config_file, config_file_sav) != 0)
        !          2603:     {
        !          2604:       vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
        !          2605:                VTY_NEWLINE);
        !          2606:       goto finished;
        !          2607:     }
        !          2608:   sync ();
        !          2609:   if (unlink (config_file) != 0)
        !          2610:     {
        !          2611:       vty_out (vty, "Can't unlink configuration file %s.%s", config_file,
        !          2612:                VTY_NEWLINE);
        !          2613:       goto finished;
        !          2614:     }
        !          2615:   if (link (config_file_tmp, config_file) != 0)
        !          2616:     {
        !          2617:       vty_out (vty, "Can't save configuration file %s.%s", config_file,
        !          2618:               VTY_NEWLINE);
        !          2619:       goto finished;
        !          2620:     }
        !          2621:   sync ();
        !          2622:   
        !          2623:   if (chmod (config_file, CONFIGFILE_MASK) != 0)
        !          2624:     {
        !          2625:       vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s", 
        !          2626:        config_file, safe_strerror(errno), errno, VTY_NEWLINE);
        !          2627:       goto finished;
        !          2628:     }
        !          2629: 
        !          2630:   vty_out (vty, "Configuration saved to %s%s", config_file,
        !          2631:           VTY_NEWLINE);
        !          2632:   ret = CMD_SUCCESS;
        !          2633: 
        !          2634: finished:
        !          2635:   unlink (config_file_tmp);
        !          2636:   XFREE (MTYPE_TMP, config_file_tmp);
        !          2637:   XFREE (MTYPE_TMP, config_file_sav);
        !          2638:   return ret;
        !          2639: }
        !          2640: 
        !          2641: ALIAS (config_write_file, 
        !          2642:        config_write_cmd,
        !          2643:        "write",  
        !          2644:        "Write running configuration to memory, network, or terminal\n")
        !          2645: 
        !          2646: ALIAS (config_write_file, 
        !          2647:        config_write_memory_cmd,
        !          2648:        "write memory",  
        !          2649:        "Write running configuration to memory, network, or terminal\n"
        !          2650:        "Write configuration to the file (same as write file)\n")
        !          2651: 
        !          2652: ALIAS (config_write_file, 
        !          2653:        copy_runningconfig_startupconfig_cmd,
        !          2654:        "copy running-config startup-config",  
        !          2655:        "Copy configuration\n"
        !          2656:        "Copy running config to... \n"
        !          2657:        "Copy running config to startup config (same as write file)\n")
        !          2658: 
        !          2659: /* Write current configuration into the terminal. */
        !          2660: DEFUN (config_write_terminal,
        !          2661:        config_write_terminal_cmd,
        !          2662:        "write terminal",
        !          2663:        "Write running configuration to memory, network, or terminal\n"
        !          2664:        "Write to terminal\n")
        !          2665: {
        !          2666:   unsigned int i;
        !          2667:   struct cmd_node *node;
        !          2668: 
        !          2669:   if (vty->type == VTY_SHELL_SERV)
        !          2670:     {
        !          2671:       for (i = 0; i < vector_active (cmdvec); i++)
        !          2672:        if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh)
        !          2673:          {
        !          2674:            if ((*node->func) (vty))
        !          2675:              vty_out (vty, "!%s", VTY_NEWLINE);
        !          2676:          }
        !          2677:     }
        !          2678:   else
        !          2679:     {
        !          2680:       vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
        !          2681:               VTY_NEWLINE);
        !          2682:       vty_out (vty, "!%s", VTY_NEWLINE);
        !          2683: 
        !          2684:       for (i = 0; i < vector_active (cmdvec); i++)
        !          2685:        if ((node = vector_slot (cmdvec, i)) && node->func)
        !          2686:          {
        !          2687:            if ((*node->func) (vty))
        !          2688:              vty_out (vty, "!%s", VTY_NEWLINE);
        !          2689:          }
        !          2690:       vty_out (vty, "end%s",VTY_NEWLINE);
        !          2691:     }
        !          2692:   return CMD_SUCCESS;
        !          2693: }
        !          2694: 
        !          2695: /* Write current configuration into the terminal. */
        !          2696: ALIAS (config_write_terminal,
        !          2697:        show_running_config_cmd,
        !          2698:        "show running-config",
        !          2699:        SHOW_STR
        !          2700:        "running configuration\n")
        !          2701: 
        !          2702: /* Write startup configuration into the terminal. */
        !          2703: DEFUN (show_startup_config,
        !          2704:        show_startup_config_cmd,
        !          2705:        "show startup-config",
        !          2706:        SHOW_STR
        !          2707:        "Contentes of startup configuration\n")
        !          2708: {
        !          2709:   char buf[BUFSIZ];
        !          2710:   FILE *confp;
        !          2711: 
        !          2712:   confp = fopen (host.config, "r");
        !          2713:   if (confp == NULL)
        !          2714:     {
        !          2715:       vty_out (vty, "Can't open configuration file [%s]%s",
        !          2716:               host.config, VTY_NEWLINE);
        !          2717:       return CMD_WARNING;
        !          2718:     }
        !          2719: 
        !          2720:   while (fgets (buf, BUFSIZ, confp))
        !          2721:     {
        !          2722:       char *cp = buf;
        !          2723: 
        !          2724:       while (*cp != '\r' && *cp != '\n' && *cp != '\0')
        !          2725:        cp++;
        !          2726:       *cp = '\0';
        !          2727: 
        !          2728:       vty_out (vty, "%s%s", buf, VTY_NEWLINE);
        !          2729:     }
        !          2730: 
        !          2731:   fclose (confp);
        !          2732: 
        !          2733:   return CMD_SUCCESS;
        !          2734: }
        !          2735: 
        !          2736: /* Hostname configuration */
        !          2737: DEFUN (config_hostname, 
        !          2738:        hostname_cmd,
        !          2739:        "hostname WORD",
        !          2740:        "Set system's network name\n"
        !          2741:        "This system's network name\n")
        !          2742: {
        !          2743:   if (!isalpha((int) *argv[0]))
        !          2744:     {
        !          2745:       vty_out (vty, "Please specify string starting with alphabet%s", VTY_NEWLINE);
        !          2746:       return CMD_WARNING;
        !          2747:     }
        !          2748: 
        !          2749:   if (host.name)
        !          2750:     XFREE (MTYPE_HOST, host.name);
        !          2751:     
        !          2752:   host.name = XSTRDUP (MTYPE_HOST, argv[0]);
        !          2753:   return CMD_SUCCESS;
        !          2754: }
        !          2755: 
        !          2756: DEFUN (config_no_hostname, 
        !          2757:        no_hostname_cmd,
        !          2758:        "no hostname [HOSTNAME]",
        !          2759:        NO_STR
        !          2760:        "Reset system's network name\n"
        !          2761:        "Host name of this router\n")
        !          2762: {
        !          2763:   if (host.name)
        !          2764:     XFREE (MTYPE_HOST, host.name);
        !          2765:   host.name = NULL;
        !          2766:   return CMD_SUCCESS;
        !          2767: }
        !          2768: 
        !          2769: /* VTY interface password set. */
        !          2770: DEFUN (config_password, password_cmd,
        !          2771:        "password (8|) WORD",
        !          2772:        "Assign the terminal connection password\n"
        !          2773:        "Specifies a HIDDEN password will follow\n"
        !          2774:        "dummy string \n"
        !          2775:        "The HIDDEN line password string\n")
        !          2776: {
        !          2777:   /* Argument check. */
        !          2778:   if (argc == 0)
        !          2779:     {
        !          2780:       vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
        !          2781:       return CMD_WARNING;
        !          2782:     }
        !          2783: 
        !          2784:   if (argc == 2)
        !          2785:     {
        !          2786:       if (*argv[0] == '8')
        !          2787:        {
        !          2788:          if (host.password)
        !          2789:            XFREE (MTYPE_HOST, host.password);
        !          2790:          host.password = NULL;
        !          2791:          if (host.password_encrypt)
        !          2792:            XFREE (MTYPE_HOST, host.password_encrypt);
        !          2793:          host.password_encrypt = XSTRDUP (MTYPE_HOST, argv[1]);
        !          2794:          return CMD_SUCCESS;
        !          2795:        }
        !          2796:       else
        !          2797:        {
        !          2798:          vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
        !          2799:          return CMD_WARNING;
        !          2800:        }
        !          2801:     }
        !          2802: 
        !          2803:   if (!isalnum ((int) *argv[0]))
        !          2804:     {
        !          2805:       vty_out (vty, 
        !          2806:               "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
        !          2807:       return CMD_WARNING;
        !          2808:     }
        !          2809: 
        !          2810:   if (host.password)
        !          2811:     XFREE (MTYPE_HOST, host.password);
        !          2812:   host.password = NULL;
        !          2813: 
        !          2814:   if (host.encrypt)
        !          2815:     {
        !          2816:       if (host.password_encrypt)
        !          2817:        XFREE (MTYPE_HOST, host.password_encrypt);
        !          2818:       host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[0]));
        !          2819:     }
        !          2820:   else
        !          2821:     host.password = XSTRDUP (MTYPE_HOST, argv[0]);
        !          2822: 
        !          2823:   return CMD_SUCCESS;
        !          2824: }
        !          2825: 
        !          2826: ALIAS (config_password, password_text_cmd,
        !          2827:        "password LINE",
        !          2828:        "Assign the terminal connection password\n"
        !          2829:        "The UNENCRYPTED (cleartext) line password\n")
        !          2830: 
        !          2831: /* VTY enable password set. */
        !          2832: DEFUN (config_enable_password, enable_password_cmd,
        !          2833:        "enable password (8|) WORD",
        !          2834:        "Modify enable password parameters\n"
        !          2835:        "Assign the privileged level password\n"
        !          2836:        "Specifies a HIDDEN password will follow\n"
        !          2837:        "dummy string \n"
        !          2838:        "The HIDDEN 'enable' password string\n")
        !          2839: {
        !          2840:   /* Argument check. */
        !          2841:   if (argc == 0)
        !          2842:     {
        !          2843:       vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
        !          2844:       return CMD_WARNING;
        !          2845:     }
        !          2846: 
        !          2847:   /* Crypt type is specified. */
        !          2848:   if (argc == 2)
        !          2849:     {
        !          2850:       if (*argv[0] == '8')
        !          2851:        {
        !          2852:          if (host.enable)
        !          2853:            XFREE (MTYPE_HOST, host.enable);
        !          2854:          host.enable = NULL;
        !          2855: 
        !          2856:          if (host.enable_encrypt)
        !          2857:            XFREE (MTYPE_HOST, host.enable_encrypt);
        !          2858:          host.enable_encrypt = XSTRDUP (MTYPE_HOST, argv[1]);
        !          2859: 
        !          2860:          return CMD_SUCCESS;
        !          2861:        }
        !          2862:       else
        !          2863:        {
        !          2864:          vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
        !          2865:          return CMD_WARNING;
        !          2866:        }
        !          2867:     }
        !          2868: 
        !          2869:   if (!isalnum ((int) *argv[0]))
        !          2870:     {
        !          2871:       vty_out (vty, 
        !          2872:               "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
        !          2873:       return CMD_WARNING;
        !          2874:     }
        !          2875: 
        !          2876:   if (host.enable)
        !          2877:     XFREE (MTYPE_HOST, host.enable);
        !          2878:   host.enable = NULL;
        !          2879: 
        !          2880:   /* Plain password input. */
        !          2881:   if (host.encrypt)
        !          2882:     {
        !          2883:       if (host.enable_encrypt)
        !          2884:        XFREE (MTYPE_HOST, host.enable_encrypt);
        !          2885:       host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[0]));
        !          2886:     }
        !          2887:   else
        !          2888:     host.enable = XSTRDUP (MTYPE_HOST, argv[0]);
        !          2889: 
        !          2890:   return CMD_SUCCESS;
        !          2891: }
        !          2892: 
        !          2893: ALIAS (config_enable_password,
        !          2894:        enable_password_text_cmd,
        !          2895:        "enable password LINE",
        !          2896:        "Modify enable password parameters\n"
        !          2897:        "Assign the privileged level password\n"
        !          2898:        "The UNENCRYPTED (cleartext) 'enable' password\n")
        !          2899: 
        !          2900: /* VTY enable password delete. */
        !          2901: DEFUN (no_config_enable_password, no_enable_password_cmd,
        !          2902:        "no enable password",
        !          2903:        NO_STR
        !          2904:        "Modify enable password parameters\n"
        !          2905:        "Assign the privileged level password\n")
        !          2906: {
        !          2907:   if (host.enable)
        !          2908:     XFREE (MTYPE_HOST, host.enable);
        !          2909:   host.enable = NULL;
        !          2910: 
        !          2911:   if (host.enable_encrypt)
        !          2912:     XFREE (MTYPE_HOST, host.enable_encrypt);
        !          2913:   host.enable_encrypt = NULL;
        !          2914: 
        !          2915:   return CMD_SUCCESS;
        !          2916: }
        !          2917:        
        !          2918: DEFUN (service_password_encrypt,
        !          2919:        service_password_encrypt_cmd,
        !          2920:        "service password-encryption",
        !          2921:        "Set up miscellaneous service\n"
        !          2922:        "Enable encrypted passwords\n")
        !          2923: {
        !          2924:   if (host.encrypt)
        !          2925:     return CMD_SUCCESS;
        !          2926: 
        !          2927:   host.encrypt = 1;
        !          2928: 
        !          2929:   if (host.password)
        !          2930:     {
        !          2931:       if (host.password_encrypt)
        !          2932:        XFREE (MTYPE_HOST, host.password_encrypt);
        !          2933:       host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.password));
        !          2934:     }
        !          2935:   if (host.enable)
        !          2936:     {
        !          2937:       if (host.enable_encrypt)
        !          2938:        XFREE (MTYPE_HOST, host.enable_encrypt);
        !          2939:       host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.enable));
        !          2940:     }
        !          2941: 
        !          2942:   return CMD_SUCCESS;
        !          2943: }
        !          2944: 
        !          2945: DEFUN (no_service_password_encrypt,
        !          2946:        no_service_password_encrypt_cmd,
        !          2947:        "no service password-encryption",
        !          2948:        NO_STR
        !          2949:        "Set up miscellaneous service\n"
        !          2950:        "Enable encrypted passwords\n")
        !          2951: {
        !          2952:   if (! host.encrypt)
        !          2953:     return CMD_SUCCESS;
        !          2954: 
        !          2955:   host.encrypt = 0;
        !          2956: 
        !          2957:   if (host.password_encrypt)
        !          2958:     XFREE (MTYPE_HOST, host.password_encrypt);
        !          2959:   host.password_encrypt = NULL;
        !          2960: 
        !          2961:   if (host.enable_encrypt)
        !          2962:     XFREE (MTYPE_HOST, host.enable_encrypt);
        !          2963:   host.enable_encrypt = NULL;
        !          2964: 
        !          2965:   return CMD_SUCCESS;
        !          2966: }
        !          2967: 
        !          2968: DEFUN (config_terminal_length, config_terminal_length_cmd,
        !          2969:        "terminal length <0-512>",
        !          2970:        "Set terminal line parameters\n"
        !          2971:        "Set number of lines on a screen\n"
        !          2972:        "Number of lines on screen (0 for no pausing)\n")
        !          2973: {
        !          2974:   int lines;
        !          2975:   char *endptr = NULL;
        !          2976: 
        !          2977:   lines = strtol (argv[0], &endptr, 10);
        !          2978:   if (lines < 0 || lines > 512 || *endptr != '\0')
        !          2979:     {
        !          2980:       vty_out (vty, "length is malformed%s", VTY_NEWLINE);
        !          2981:       return CMD_WARNING;
        !          2982:     }
        !          2983:   vty->lines = lines;
        !          2984: 
        !          2985:   return CMD_SUCCESS;
        !          2986: }
        !          2987: 
        !          2988: DEFUN (config_terminal_no_length, config_terminal_no_length_cmd,
        !          2989:        "terminal no length",
        !          2990:        "Set terminal line parameters\n"
        !          2991:        NO_STR
        !          2992:        "Set number of lines on a screen\n")
        !          2993: {
        !          2994:   vty->lines = -1;
        !          2995:   return CMD_SUCCESS;
        !          2996: }
        !          2997: 
        !          2998: DEFUN (service_terminal_length, service_terminal_length_cmd,
        !          2999:        "service terminal-length <0-512>",
        !          3000:        "Set up miscellaneous service\n"
        !          3001:        "System wide terminal length configuration\n"
        !          3002:        "Number of lines of VTY (0 means no line control)\n")
        !          3003: {
        !          3004:   int lines;
        !          3005:   char *endptr = NULL;
        !          3006: 
        !          3007:   lines = strtol (argv[0], &endptr, 10);
        !          3008:   if (lines < 0 || lines > 512 || *endptr != '\0')
        !          3009:     {
        !          3010:       vty_out (vty, "length is malformed%s", VTY_NEWLINE);
        !          3011:       return CMD_WARNING;
        !          3012:     }
        !          3013:   host.lines = lines;
        !          3014: 
        !          3015:   return CMD_SUCCESS;
        !          3016: }
        !          3017: 
        !          3018: DEFUN (no_service_terminal_length, no_service_terminal_length_cmd,
        !          3019:        "no service terminal-length [<0-512>]",
        !          3020:        NO_STR
        !          3021:        "Set up miscellaneous service\n"
        !          3022:        "System wide terminal length configuration\n"
        !          3023:        "Number of lines of VTY (0 means no line control)\n")
        !          3024: {
        !          3025:   host.lines = -1;
        !          3026:   return CMD_SUCCESS;
        !          3027: }
        !          3028: 
        !          3029: DEFUN_HIDDEN (do_echo,
        !          3030:              echo_cmd,
        !          3031:              "echo .MESSAGE",
        !          3032:              "Echo a message back to the vty\n"
        !          3033:              "The message to echo\n")
        !          3034: {
        !          3035:   char *message;
        !          3036: 
        !          3037:   vty_out (vty, "%s%s", ((message = argv_concat(argv, argc, 0)) ? message : ""),
        !          3038:           VTY_NEWLINE);
        !          3039:   if (message)
        !          3040:     XFREE(MTYPE_TMP, message);
        !          3041:   return CMD_SUCCESS;
        !          3042: }
        !          3043: 
        !          3044: DEFUN (config_logmsg,
        !          3045:        config_logmsg_cmd,
        !          3046:        "logmsg "LOG_LEVELS" .MESSAGE",
        !          3047:        "Send a message to enabled logging destinations\n"
        !          3048:        LOG_LEVEL_DESC
        !          3049:        "The message to send\n")
        !          3050: {
        !          3051:   int level;
        !          3052:   char *message;
        !          3053: 
        !          3054:   if ((level = level_match(argv[0])) == ZLOG_DISABLED)
        !          3055:     return CMD_ERR_NO_MATCH;
        !          3056: 
        !          3057:   zlog(NULL, level, "%s", ((message = argv_concat(argv, argc, 1)) ? message : ""));
        !          3058:   if (message)
        !          3059:     XFREE(MTYPE_TMP, message);
        !          3060:   return CMD_SUCCESS;
        !          3061: }
        !          3062: 
        !          3063: DEFUN (show_logging,
        !          3064:        show_logging_cmd,
        !          3065:        "show logging",
        !          3066:        SHOW_STR
        !          3067:        "Show current logging configuration\n")
        !          3068: {
        !          3069:   struct zlog *zl = zlog_default;
        !          3070: 
        !          3071:   vty_out (vty, "Syslog logging: ");
        !          3072:   if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED)
        !          3073:     vty_out (vty, "disabled");
        !          3074:   else
        !          3075:     vty_out (vty, "level %s, facility %s, ident %s",
        !          3076:             zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]],
        !          3077:             facility_name(zl->facility), zl->ident);
        !          3078:   vty_out (vty, "%s", VTY_NEWLINE);
        !          3079: 
        !          3080:   vty_out (vty, "Stdout logging: ");
        !          3081:   if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED)
        !          3082:     vty_out (vty, "disabled");
        !          3083:   else
        !          3084:     vty_out (vty, "level %s",
        !          3085:             zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]);
        !          3086:   vty_out (vty, "%s", VTY_NEWLINE);
        !          3087: 
        !          3088:   vty_out (vty, "Monitor logging: ");
        !          3089:   if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
        !          3090:     vty_out (vty, "disabled");
        !          3091:   else
        !          3092:     vty_out (vty, "level %s",
        !          3093:             zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]);
        !          3094:   vty_out (vty, "%s", VTY_NEWLINE);
        !          3095: 
        !          3096:   vty_out (vty, "File logging: ");
        !          3097:   if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) ||
        !          3098:       !zl->fp)
        !          3099:     vty_out (vty, "disabled");
        !          3100:   else
        !          3101:     vty_out (vty, "level %s, filename %s",
        !          3102:             zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]],
        !          3103:             zl->filename);
        !          3104:   vty_out (vty, "%s", VTY_NEWLINE);
        !          3105: 
        !          3106:   vty_out (vty, "Protocol name: %s%s",
        !          3107:           zlog_proto_names[zl->protocol], VTY_NEWLINE);
        !          3108:   vty_out (vty, "Record priority: %s%s",
        !          3109:           (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE);
        !          3110:   vty_out (vty, "Timestamp precision: %d%s",
        !          3111:           zl->timestamp_precision, VTY_NEWLINE);
        !          3112: 
        !          3113:   return CMD_SUCCESS;
        !          3114: }
        !          3115: 
        !          3116: DEFUN (config_log_stdout,
        !          3117:        config_log_stdout_cmd,
        !          3118:        "log stdout",
        !          3119:        "Logging control\n"
        !          3120:        "Set stdout logging level\n")
        !          3121: {
        !          3122:   zlog_set_level (NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl);
        !          3123:   return CMD_SUCCESS;
        !          3124: }
        !          3125: 
        !          3126: DEFUN (config_log_stdout_level,
        !          3127:        config_log_stdout_level_cmd,
        !          3128:        "log stdout "LOG_LEVELS,
        !          3129:        "Logging control\n"
        !          3130:        "Set stdout logging level\n"
        !          3131:        LOG_LEVEL_DESC)
        !          3132: {
        !          3133:   int level;
        !          3134: 
        !          3135:   if ((level = level_match(argv[0])) == ZLOG_DISABLED)
        !          3136:     return CMD_ERR_NO_MATCH;
        !          3137:   zlog_set_level (NULL, ZLOG_DEST_STDOUT, level);
        !          3138:   return CMD_SUCCESS;
        !          3139: }
        !          3140: 
        !          3141: DEFUN (no_config_log_stdout,
        !          3142:        no_config_log_stdout_cmd,
        !          3143:        "no log stdout [LEVEL]",
        !          3144:        NO_STR
        !          3145:        "Logging control\n"
        !          3146:        "Cancel logging to stdout\n"
        !          3147:        "Logging level\n")
        !          3148: {
        !          3149:   zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
        !          3150:   return CMD_SUCCESS;
        !          3151: }
        !          3152: 
        !          3153: DEFUN (config_log_monitor,
        !          3154:        config_log_monitor_cmd,
        !          3155:        "log monitor",
        !          3156:        "Logging control\n"
        !          3157:        "Set terminal line (monitor) logging level\n")
        !          3158: {
        !          3159:   zlog_set_level (NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl);
        !          3160:   return CMD_SUCCESS;
        !          3161: }
        !          3162: 
        !          3163: DEFUN (config_log_monitor_level,
        !          3164:        config_log_monitor_level_cmd,
        !          3165:        "log monitor "LOG_LEVELS,
        !          3166:        "Logging control\n"
        !          3167:        "Set terminal line (monitor) logging level\n"
        !          3168:        LOG_LEVEL_DESC)
        !          3169: {
        !          3170:   int level;
        !          3171: 
        !          3172:   if ((level = level_match(argv[0])) == ZLOG_DISABLED)
        !          3173:     return CMD_ERR_NO_MATCH;
        !          3174:   zlog_set_level (NULL, ZLOG_DEST_MONITOR, level);
        !          3175:   return CMD_SUCCESS;
        !          3176: }
        !          3177: 
        !          3178: DEFUN (no_config_log_monitor,
        !          3179:        no_config_log_monitor_cmd,
        !          3180:        "no log monitor [LEVEL]",
        !          3181:        NO_STR
        !          3182:        "Logging control\n"
        !          3183:        "Disable terminal line (monitor) logging\n"
        !          3184:        "Logging level\n")
        !          3185: {
        !          3186:   zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
        !          3187:   return CMD_SUCCESS;
        !          3188: }
        !          3189: 
        !          3190: static int
        !          3191: set_log_file(struct vty *vty, const char *fname, int loglevel)
        !          3192: {
        !          3193:   int ret;
        !          3194:   char *p = NULL;
        !          3195:   const char *fullpath;
        !          3196:   
        !          3197:   /* Path detection. */
        !          3198:   if (! IS_DIRECTORY_SEP (*fname))
        !          3199:     {
        !          3200:       char cwd[MAXPATHLEN+1];
        !          3201:       cwd[MAXPATHLEN] = '\0';
        !          3202:       
        !          3203:       if (getcwd (cwd, MAXPATHLEN) == NULL)
        !          3204:         {
        !          3205:           zlog_err ("config_log_file: Unable to alloc mem!");
        !          3206:           return CMD_WARNING;
        !          3207:         }
        !          3208:       
        !          3209:       if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2))
        !          3210:           == NULL)
        !          3211:         {
        !          3212:           zlog_err ("config_log_file: Unable to alloc mem!");
        !          3213:           return CMD_WARNING;
        !          3214:         }
        !          3215:       sprintf (p, "%s/%s", cwd, fname);
        !          3216:       fullpath = p;
        !          3217:     }
        !          3218:   else
        !          3219:     fullpath = fname;
        !          3220: 
        !          3221:   ret = zlog_set_file (NULL, fullpath, loglevel);
        !          3222: 
        !          3223:   if (p)
        !          3224:     XFREE (MTYPE_TMP, p);
        !          3225: 
        !          3226:   if (!ret)
        !          3227:     {
        !          3228:       vty_out (vty, "can't open logfile %s\n", fname);
        !          3229:       return CMD_WARNING;
        !          3230:     }
        !          3231: 
        !          3232:   if (host.logfile)
        !          3233:     XFREE (MTYPE_HOST, host.logfile);
        !          3234: 
        !          3235:   host.logfile = XSTRDUP (MTYPE_HOST, fname);
        !          3236: 
        !          3237:   return CMD_SUCCESS;
        !          3238: }
        !          3239: 
        !          3240: DEFUN (config_log_file,
        !          3241:        config_log_file_cmd,
        !          3242:        "log file FILENAME",
        !          3243:        "Logging control\n"
        !          3244:        "Logging to file\n"
        !          3245:        "Logging filename\n")
        !          3246: {
        !          3247:   return set_log_file(vty, argv[0], zlog_default->default_lvl);
        !          3248: }
        !          3249: 
        !          3250: DEFUN (config_log_file_level,
        !          3251:        config_log_file_level_cmd,
        !          3252:        "log file FILENAME "LOG_LEVELS,
        !          3253:        "Logging control\n"
        !          3254:        "Logging to file\n"
        !          3255:        "Logging filename\n"
        !          3256:        LOG_LEVEL_DESC)
        !          3257: {
        !          3258:   int level;
        !          3259: 
        !          3260:   if ((level = level_match(argv[1])) == ZLOG_DISABLED)
        !          3261:     return CMD_ERR_NO_MATCH;
        !          3262:   return set_log_file(vty, argv[0], level);
        !          3263: }
        !          3264: 
        !          3265: DEFUN (no_config_log_file,
        !          3266:        no_config_log_file_cmd,
        !          3267:        "no log file [FILENAME]",
        !          3268:        NO_STR
        !          3269:        "Logging control\n"
        !          3270:        "Cancel logging to file\n"
        !          3271:        "Logging file name\n")
        !          3272: {
        !          3273:   zlog_reset_file (NULL);
        !          3274: 
        !          3275:   if (host.logfile)
        !          3276:     XFREE (MTYPE_HOST, host.logfile);
        !          3277: 
        !          3278:   host.logfile = NULL;
        !          3279: 
        !          3280:   return CMD_SUCCESS;
        !          3281: }
        !          3282: 
        !          3283: ALIAS (no_config_log_file,
        !          3284:        no_config_log_file_level_cmd,
        !          3285:        "no log file FILENAME LEVEL",
        !          3286:        NO_STR
        !          3287:        "Logging control\n"
        !          3288:        "Cancel logging to file\n"
        !          3289:        "Logging file name\n"
        !          3290:        "Logging level\n")
        !          3291: 
        !          3292: DEFUN (config_log_syslog,
        !          3293:        config_log_syslog_cmd,
        !          3294:        "log syslog",
        !          3295:        "Logging control\n"
        !          3296:        "Set syslog logging level\n")
        !          3297: {
        !          3298:   zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
        !          3299:   return CMD_SUCCESS;
        !          3300: }
        !          3301: 
        !          3302: DEFUN (config_log_syslog_level,
        !          3303:        config_log_syslog_level_cmd,
        !          3304:        "log syslog "LOG_LEVELS,
        !          3305:        "Logging control\n"
        !          3306:        "Set syslog logging level\n"
        !          3307:        LOG_LEVEL_DESC)
        !          3308: {
        !          3309:   int level;
        !          3310: 
        !          3311:   if ((level = level_match(argv[0])) == ZLOG_DISABLED)
        !          3312:     return CMD_ERR_NO_MATCH;
        !          3313:   zlog_set_level (NULL, ZLOG_DEST_SYSLOG, level);
        !          3314:   return CMD_SUCCESS;
        !          3315: }
        !          3316: 
        !          3317: DEFUN_DEPRECATED (config_log_syslog_facility,
        !          3318:                  config_log_syslog_facility_cmd,
        !          3319:                  "log syslog facility "LOG_FACILITIES,
        !          3320:                  "Logging control\n"
        !          3321:                  "Logging goes to syslog\n"
        !          3322:                  "(Deprecated) Facility parameter for syslog messages\n"
        !          3323:                  LOG_FACILITY_DESC)
        !          3324: {
        !          3325:   int facility;
        !          3326: 
        !          3327:   if ((facility = facility_match(argv[0])) < 0)
        !          3328:     return CMD_ERR_NO_MATCH;
        !          3329: 
        !          3330:   zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
        !          3331:   zlog_default->facility = facility;
        !          3332:   return CMD_SUCCESS;
        !          3333: }
        !          3334: 
        !          3335: DEFUN (no_config_log_syslog,
        !          3336:        no_config_log_syslog_cmd,
        !          3337:        "no log syslog [LEVEL]",
        !          3338:        NO_STR
        !          3339:        "Logging control\n"
        !          3340:        "Cancel logging to syslog\n"
        !          3341:        "Logging level\n")
        !          3342: {
        !          3343:   zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
        !          3344:   return CMD_SUCCESS;
        !          3345: }
        !          3346: 
        !          3347: ALIAS (no_config_log_syslog,
        !          3348:        no_config_log_syslog_facility_cmd,
        !          3349:        "no log syslog facility "LOG_FACILITIES,
        !          3350:        NO_STR
        !          3351:        "Logging control\n"
        !          3352:        "Logging goes to syslog\n"
        !          3353:        "Facility parameter for syslog messages\n"
        !          3354:        LOG_FACILITY_DESC)
        !          3355: 
        !          3356: DEFUN (config_log_facility,
        !          3357:        config_log_facility_cmd,
        !          3358:        "log facility "LOG_FACILITIES,
        !          3359:        "Logging control\n"
        !          3360:        "Facility parameter for syslog messages\n"
        !          3361:        LOG_FACILITY_DESC)
        !          3362: {
        !          3363:   int facility;
        !          3364: 
        !          3365:   if ((facility = facility_match(argv[0])) < 0)
        !          3366:     return CMD_ERR_NO_MATCH;
        !          3367:   zlog_default->facility = facility;
        !          3368:   return CMD_SUCCESS;
        !          3369: }
        !          3370: 
        !          3371: DEFUN (no_config_log_facility,
        !          3372:        no_config_log_facility_cmd,
        !          3373:        "no log facility [FACILITY]",
        !          3374:        NO_STR
        !          3375:        "Logging control\n"
        !          3376:        "Reset syslog facility to default (daemon)\n"
        !          3377:        "Syslog facility\n")
        !          3378: {
        !          3379:   zlog_default->facility = LOG_DAEMON;
        !          3380:   return CMD_SUCCESS;
        !          3381: }
        !          3382: 
        !          3383: DEFUN_DEPRECATED (config_log_trap,
        !          3384:                  config_log_trap_cmd,
        !          3385:                  "log trap "LOG_LEVELS,
        !          3386:                  "Logging control\n"
        !          3387:                  "(Deprecated) Set logging level and default for all destinations\n"
        !          3388:                  LOG_LEVEL_DESC)
        !          3389: {
        !          3390:   int new_level ;
        !          3391:   int i;
        !          3392:   
        !          3393:   if ((new_level = level_match(argv[0])) == ZLOG_DISABLED)
        !          3394:     return CMD_ERR_NO_MATCH;
        !          3395: 
        !          3396:   zlog_default->default_lvl = new_level;
        !          3397:   for (i = 0; i < ZLOG_NUM_DESTS; i++)
        !          3398:     if (zlog_default->maxlvl[i] != ZLOG_DISABLED)
        !          3399:       zlog_default->maxlvl[i] = new_level;
        !          3400:   return CMD_SUCCESS;
        !          3401: }
        !          3402: 
        !          3403: DEFUN_DEPRECATED (no_config_log_trap,
        !          3404:                  no_config_log_trap_cmd,
        !          3405:                  "no log trap [LEVEL]",
        !          3406:                  NO_STR
        !          3407:                  "Logging control\n"
        !          3408:                  "Permit all logging information\n"
        !          3409:                  "Logging level\n")
        !          3410: {
        !          3411:   zlog_default->default_lvl = LOG_DEBUG;
        !          3412:   return CMD_SUCCESS;
        !          3413: }
        !          3414: 
        !          3415: DEFUN (config_log_record_priority,
        !          3416:        config_log_record_priority_cmd,
        !          3417:        "log record-priority",
        !          3418:        "Logging control\n"
        !          3419:        "Log the priority of the message within the message\n")
        !          3420: {
        !          3421:   zlog_default->record_priority = 1 ;
        !          3422:   return CMD_SUCCESS;
        !          3423: }
        !          3424: 
        !          3425: DEFUN (no_config_log_record_priority,
        !          3426:        no_config_log_record_priority_cmd,
        !          3427:        "no log record-priority",
        !          3428:        NO_STR
        !          3429:        "Logging control\n"
        !          3430:        "Do not log the priority of the message within the message\n")
        !          3431: {
        !          3432:   zlog_default->record_priority = 0 ;
        !          3433:   return CMD_SUCCESS;
        !          3434: }
        !          3435: 
        !          3436: DEFUN (config_log_timestamp_precision,
        !          3437:        config_log_timestamp_precision_cmd,
        !          3438:        "log timestamp precision <0-6>",
        !          3439:        "Logging control\n"
        !          3440:        "Timestamp configuration\n"
        !          3441:        "Set the timestamp precision\n"
        !          3442:        "Number of subsecond digits\n")
        !          3443: {
        !          3444:   if (argc != 1)
        !          3445:     {
        !          3446:       vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE);
        !          3447:       return CMD_WARNING;
        !          3448:     }
        !          3449: 
        !          3450:   VTY_GET_INTEGER_RANGE("Timestamp Precision",
        !          3451:                        zlog_default->timestamp_precision, argv[0], 0, 6);
        !          3452:   return CMD_SUCCESS;
        !          3453: }
        !          3454: 
        !          3455: DEFUN (no_config_log_timestamp_precision,
        !          3456:        no_config_log_timestamp_precision_cmd,
        !          3457:        "no log timestamp precision",
        !          3458:        NO_STR
        !          3459:        "Logging control\n"
        !          3460:        "Timestamp configuration\n"
        !          3461:        "Reset the timestamp precision to the default value of 0\n")
        !          3462: {
        !          3463:   zlog_default->timestamp_precision = 0 ;
        !          3464:   return CMD_SUCCESS;
        !          3465: }
        !          3466: 
        !          3467: DEFUN (banner_motd_file,
        !          3468:        banner_motd_file_cmd,
        !          3469:        "banner motd file [FILE]",
        !          3470:        "Set banner\n"
        !          3471:        "Banner for motd\n"
        !          3472:        "Banner from a file\n"
        !          3473:        "Filename\n")
        !          3474: {
        !          3475:   if (host.motdfile)
        !          3476:     XFREE (MTYPE_HOST, host.motdfile);
        !          3477:   host.motdfile = XSTRDUP (MTYPE_HOST, argv[0]);
        !          3478: 
        !          3479:   return CMD_SUCCESS;
        !          3480: }
        !          3481: 
        !          3482: DEFUN (banner_motd_default,
        !          3483:        banner_motd_default_cmd,
        !          3484:        "banner motd default",
        !          3485:        "Set banner string\n"
        !          3486:        "Strings for motd\n"
        !          3487:        "Default string\n")
        !          3488: {
        !          3489:   host.motd = default_motd;
        !          3490:   return CMD_SUCCESS;
        !          3491: }
        !          3492: 
        !          3493: DEFUN (no_banner_motd,
        !          3494:        no_banner_motd_cmd,
        !          3495:        "no banner motd",
        !          3496:        NO_STR
        !          3497:        "Set banner string\n"
        !          3498:        "Strings for motd\n")
        !          3499: {
        !          3500:   host.motd = NULL;
        !          3501:   if (host.motdfile) 
        !          3502:     XFREE (MTYPE_HOST, host.motdfile);
        !          3503:   host.motdfile = NULL;
        !          3504:   return CMD_SUCCESS;
        !          3505: }
        !          3506: 
        !          3507: /* Set config filename.  Called from vty.c */
        !          3508: void
        !          3509: host_config_set (char *filename)
        !          3510: {
        !          3511:   if (host.config)
        !          3512:     XFREE (MTYPE_HOST, host.config);
        !          3513:   host.config = XSTRDUP (MTYPE_HOST, filename);
        !          3514: }
        !          3515: 
        !          3516: void
        !          3517: install_default (enum node_type node)
        !          3518: {
        !          3519:   install_element (node, &config_exit_cmd);
        !          3520:   install_element (node, &config_quit_cmd);
        !          3521:   install_element (node, &config_end_cmd);
        !          3522:   install_element (node, &config_help_cmd);
        !          3523:   install_element (node, &config_list_cmd);
        !          3524: 
        !          3525:   install_element (node, &config_write_terminal_cmd);
        !          3526:   install_element (node, &config_write_file_cmd);
        !          3527:   install_element (node, &config_write_memory_cmd);
        !          3528:   install_element (node, &config_write_cmd);
        !          3529:   install_element (node, &show_running_config_cmd);
        !          3530: }
        !          3531: 
        !          3532: /* Initialize command interface. Install basic nodes and commands. */
        !          3533: void
        !          3534: cmd_init (int terminal)
        !          3535: {
        !          3536:   command_cr = XSTRDUP(MTYPE_STRVEC, "<cr>");
        !          3537:   desc_cr.cmd = command_cr;
        !          3538:   desc_cr.str = XSTRDUP(MTYPE_STRVEC, "");
        !          3539: 
        !          3540:   /* Allocate initial top vector of commands. */
        !          3541:   cmdvec = vector_init (VECTOR_MIN_SIZE);
        !          3542: 
        !          3543:   /* Default host value settings. */
        !          3544:   host.name = NULL;
        !          3545:   host.password = NULL;
        !          3546:   host.enable = NULL;
        !          3547:   host.logfile = NULL;
        !          3548:   host.config = NULL;
        !          3549:   host.lines = -1;
        !          3550:   host.motd = default_motd;
        !          3551:   host.motdfile = NULL;
        !          3552: 
        !          3553:   /* Install top nodes. */
        !          3554:   install_node (&view_node, NULL);
        !          3555:   install_node (&enable_node, NULL);
        !          3556:   install_node (&auth_node, NULL);
        !          3557:   install_node (&auth_enable_node, NULL);
        !          3558:   install_node (&restricted_node, NULL);
        !          3559:   install_node (&config_node, config_write_host);
        !          3560: 
        !          3561:   /* Each node's basic commands. */
        !          3562:   install_element (VIEW_NODE, &show_version_cmd);
        !          3563:   if (terminal)
        !          3564:     {
        !          3565:       install_element (VIEW_NODE, &config_list_cmd);
        !          3566:       install_element (VIEW_NODE, &config_exit_cmd);
        !          3567:       install_element (VIEW_NODE, &config_quit_cmd);
        !          3568:       install_element (VIEW_NODE, &config_help_cmd);
        !          3569:       install_element (VIEW_NODE, &config_enable_cmd);
        !          3570:       install_element (VIEW_NODE, &config_terminal_length_cmd);
        !          3571:       install_element (VIEW_NODE, &config_terminal_no_length_cmd);
        !          3572:       install_element (VIEW_NODE, &show_logging_cmd);
        !          3573:       install_element (VIEW_NODE, &echo_cmd);
        !          3574: 
        !          3575:       install_element (RESTRICTED_NODE, &config_list_cmd);
        !          3576:       install_element (RESTRICTED_NODE, &config_exit_cmd);
        !          3577:       install_element (RESTRICTED_NODE, &config_quit_cmd);
        !          3578:       install_element (RESTRICTED_NODE, &config_help_cmd);
        !          3579:       install_element (RESTRICTED_NODE, &config_enable_cmd);
        !          3580:       install_element (RESTRICTED_NODE, &config_terminal_length_cmd);
        !          3581:       install_element (RESTRICTED_NODE, &config_terminal_no_length_cmd);
        !          3582:       install_element (RESTRICTED_NODE, &echo_cmd);
        !          3583:     }
        !          3584: 
        !          3585:   if (terminal)
        !          3586:     {
        !          3587:       install_default (ENABLE_NODE);
        !          3588:       install_element (ENABLE_NODE, &config_disable_cmd);
        !          3589:       install_element (ENABLE_NODE, &config_terminal_cmd);
        !          3590:       install_element (ENABLE_NODE, &copy_runningconfig_startupconfig_cmd);
        !          3591:     }
        !          3592:   install_element (ENABLE_NODE, &show_startup_config_cmd);
        !          3593:   install_element (ENABLE_NODE, &show_version_cmd);
        !          3594: 
        !          3595:   if (terminal)
        !          3596:     {
        !          3597:       install_element (ENABLE_NODE, &config_terminal_length_cmd);
        !          3598:       install_element (ENABLE_NODE, &config_terminal_no_length_cmd);
        !          3599:       install_element (ENABLE_NODE, &show_logging_cmd);
        !          3600:       install_element (ENABLE_NODE, &echo_cmd);
        !          3601:       install_element (ENABLE_NODE, &config_logmsg_cmd);
        !          3602: 
        !          3603:       install_default (CONFIG_NODE);
        !          3604:     }
        !          3605:   
        !          3606:   install_element (CONFIG_NODE, &hostname_cmd);
        !          3607:   install_element (CONFIG_NODE, &no_hostname_cmd);
        !          3608: 
        !          3609:   if (terminal)
        !          3610:     {
        !          3611:       install_element (CONFIG_NODE, &password_cmd);
        !          3612:       install_element (CONFIG_NODE, &password_text_cmd);
        !          3613:       install_element (CONFIG_NODE, &enable_password_cmd);
        !          3614:       install_element (CONFIG_NODE, &enable_password_text_cmd);
        !          3615:       install_element (CONFIG_NODE, &no_enable_password_cmd);
        !          3616: 
        !          3617:       install_element (CONFIG_NODE, &config_log_stdout_cmd);
        !          3618:       install_element (CONFIG_NODE, &config_log_stdout_level_cmd);
        !          3619:       install_element (CONFIG_NODE, &no_config_log_stdout_cmd);
        !          3620:       install_element (CONFIG_NODE, &config_log_monitor_cmd);
        !          3621:       install_element (CONFIG_NODE, &config_log_monitor_level_cmd);
        !          3622:       install_element (CONFIG_NODE, &no_config_log_monitor_cmd);
        !          3623:       install_element (CONFIG_NODE, &config_log_file_cmd);
        !          3624:       install_element (CONFIG_NODE, &config_log_file_level_cmd);
        !          3625:       install_element (CONFIG_NODE, &no_config_log_file_cmd);
        !          3626:       install_element (CONFIG_NODE, &no_config_log_file_level_cmd);
        !          3627:       install_element (CONFIG_NODE, &config_log_syslog_cmd);
        !          3628:       install_element (CONFIG_NODE, &config_log_syslog_level_cmd);
        !          3629:       install_element (CONFIG_NODE, &config_log_syslog_facility_cmd);
        !          3630:       install_element (CONFIG_NODE, &no_config_log_syslog_cmd);
        !          3631:       install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd);
        !          3632:       install_element (CONFIG_NODE, &config_log_facility_cmd);
        !          3633:       install_element (CONFIG_NODE, &no_config_log_facility_cmd);
        !          3634:       install_element (CONFIG_NODE, &config_log_trap_cmd);
        !          3635:       install_element (CONFIG_NODE, &no_config_log_trap_cmd);
        !          3636:       install_element (CONFIG_NODE, &config_log_record_priority_cmd);
        !          3637:       install_element (CONFIG_NODE, &no_config_log_record_priority_cmd);
        !          3638:       install_element (CONFIG_NODE, &config_log_timestamp_precision_cmd);
        !          3639:       install_element (CONFIG_NODE, &no_config_log_timestamp_precision_cmd);
        !          3640:       install_element (CONFIG_NODE, &service_password_encrypt_cmd);
        !          3641:       install_element (CONFIG_NODE, &no_service_password_encrypt_cmd);
        !          3642:       install_element (CONFIG_NODE, &banner_motd_default_cmd);
        !          3643:       install_element (CONFIG_NODE, &banner_motd_file_cmd);
        !          3644:       install_element (CONFIG_NODE, &no_banner_motd_cmd);
        !          3645:       install_element (CONFIG_NODE, &service_terminal_length_cmd);
        !          3646:       install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
        !          3647: 
        !          3648:       install_element (VIEW_NODE, &show_thread_cpu_cmd);
        !          3649:       install_element (ENABLE_NODE, &show_thread_cpu_cmd);
        !          3650:       install_element (RESTRICTED_NODE, &show_thread_cpu_cmd);
        !          3651:       
        !          3652:       install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
        !          3653:       install_element (VIEW_NODE, &show_work_queues_cmd);
        !          3654:       install_element (ENABLE_NODE, &show_work_queues_cmd);
        !          3655:     }
        !          3656:   srand(time(NULL));
        !          3657: }
        !          3658: 
        !          3659: void
        !          3660: cmd_terminate ()
        !          3661: {
        !          3662:   unsigned int i, j, k, l;
        !          3663:   struct cmd_node *cmd_node;
        !          3664:   struct cmd_element *cmd_element;
        !          3665:   struct desc *desc;
        !          3666:   vector cmd_node_v, cmd_element_v, desc_v;
        !          3667: 
        !          3668:   if (cmdvec)
        !          3669:     {
        !          3670:       for (i = 0; i < vector_active (cmdvec); i++) 
        !          3671:         if ((cmd_node = vector_slot (cmdvec, i)) != NULL)
        !          3672:           {
        !          3673:             cmd_node_v = cmd_node->cmd_vector;
        !          3674: 
        !          3675:             for (j = 0; j < vector_active (cmd_node_v); j++)
        !          3676:               if ((cmd_element = vector_slot (cmd_node_v, j)) != NULL &&
        !          3677:                   cmd_element->strvec != NULL)
        !          3678:                 {
        !          3679:                   cmd_element_v = cmd_element->strvec;
        !          3680: 
        !          3681:                   for (k = 0; k < vector_active (cmd_element_v); k++)
        !          3682:                     if ((desc_v = vector_slot (cmd_element_v, k)) != NULL)
        !          3683:                       {
        !          3684:                         for (l = 0; l < vector_active (desc_v); l++)
        !          3685:                           if ((desc = vector_slot (desc_v, l)) != NULL)
        !          3686:                             {
        !          3687:                               if (desc->cmd)
        !          3688:                                 XFREE (MTYPE_STRVEC, desc->cmd);
        !          3689:                               if (desc->str)
        !          3690:                                 XFREE (MTYPE_STRVEC, desc->str);
        !          3691: 
        !          3692:                               XFREE (MTYPE_DESC, desc);
        !          3693:                             }
        !          3694:                         vector_free (desc_v);
        !          3695:                       }
        !          3696: 
        !          3697:                   cmd_element->strvec = NULL;
        !          3698:                   vector_free (cmd_element_v);
        !          3699:                 }
        !          3700: 
        !          3701:             vector_free (cmd_node_v);
        !          3702:           }
        !          3703: 
        !          3704:       vector_free (cmdvec);
        !          3705:       cmdvec = NULL;
        !          3706:     }
        !          3707: 
        !          3708:   if (command_cr)
        !          3709:     XFREE(MTYPE_STRVEC, command_cr);
        !          3710:   if (desc_cr.str)
        !          3711:     XFREE(MTYPE_STRVEC, desc_cr.str);
        !          3712:   if (host.name)
        !          3713:     XFREE (MTYPE_HOST, host.name);
        !          3714:   if (host.password)
        !          3715:     XFREE (MTYPE_HOST, host.password);
        !          3716:   if (host.password_encrypt)
        !          3717:     XFREE (MTYPE_HOST, host.password_encrypt);
        !          3718:   if (host.enable)
        !          3719:     XFREE (MTYPE_HOST, host.enable);
        !          3720:   if (host.enable_encrypt)
        !          3721:     XFREE (MTYPE_HOST, host.enable_encrypt);
        !          3722:   if (host.logfile)
        !          3723:     XFREE (MTYPE_HOST, host.logfile);
        !          3724:   if (host.motdfile)
        !          3725:     XFREE (MTYPE_HOST, host.motdfile);
        !          3726:   if (host.config)
        !          3727:     XFREE (MTYPE_HOST, host.config);
        !          3728: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>