cli.c
上传用户:allwinjm
上传日期:2021-08-29
资源大小:99k
文件大小:11k
源码类别:

Internet/IE编程

开发平台:

Unix_Linux

  1. /************************************************************************ 
  2.  * RSTP library - Rapid Spanning Tree (802.1t, 802.1w) 
  3.  * Copyright (C) 2001-2003 Optical Access 
  4.  * Author: Alex Rozin 
  5.  * 
  6.  * This file is part of RSTP library. 
  7.  * 
  8.  * RSTP library is free software; you can redistribute it and/or modify it 
  9.  * under the terms of the GNU Lesser General Public License as published by the 
  10.  * Free Software Foundation; version 2.1 
  11.  * 
  12.  * RSTP library 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 Lesser 
  15.  * General Public License for more details. 
  16.  * 
  17.  * You should have received a copy of the GNU Lesser General Public License 
  18.  * along with RSTP library; see the file COPYING.  If not, write to the Free 
  19.  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
  20.  * 02111-1307, USA. 
  21.  **********************************************************************/
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <time.h>
  25. #include <string.h>
  26. #include <sys/wait.h>
  27. #include <sys/time.h>
  28. #include <sys/types.h>
  29. #include <signal.h>
  30. #include <unistd.h>
  31. #include <errno.h>
  32. #include <readline/readline.h>
  33. #include <readline/history.h>
  34. #include "cli.h"
  35. static CMD_DSCR_T* TheList = 0;
  36. static int
  37. cli_parse_parms (const char* line, int skip_words, char** argv)
  38. {
  39.   static char pool[MAX_CLI_BUFF];
  40.   register char* ptr;
  41.   register int argc = 0, iii;
  42.   ptr = strchr (line, 'n');
  43.   if (ptr) *ptr = '';
  44.   memcpy (pool, line, MAX_CLI_BUFF);
  45.   pool[MAX_CLI_BUFF - 1] = '';
  46.   for (iii = 0; iii < MAXPARAMNUM; iii++) {
  47.     ptr = strtok (iii ? NULL : pool, "tn ");
  48.     if (! ptr) break;
  49.     if (skip_words-- <= 0) {
  50.       /* printf ("targv[%d]='%s' skip_words=%dn", argc, ptr, skip_words); */
  51.       argv[argc++] = ptr;
  52.     } else {
  53.       /* printf ("tskip '%s' skip_words now %dn", ptr, skip_words); */
  54.     }
  55.   }
  56.   return argc;
  57. }
  58. int cli_count_words (char* line)
  59. {
  60.   static char pool[MAX_CLI_BUFF];
  61.   register char* ptr = NULL;
  62.   register int cnt;
  63.   ptr = strchr (line, 'n');
  64.   if (ptr) *ptr = '';
  65.   strncpy (pool, line, MAX_CLI_BUFF);
  66.   pool[MAX_CLI_BUFF - 1] = '';
  67.   for (cnt = 0;; cnt++) {
  68.     ptr =  strtok (cnt ? NULL : pool, "tn ");
  69.     if (! ptr) {
  70.       break;
  71.     }
  72.   }
  73.   return cnt - 1;
  74. }
  75. void cli_register_language (const CMD_DSCR_T* cmd_list)
  76. {
  77.   TheList = ( CMD_DSCR_T*) cmd_list;
  78. }
  79. static int help_on_param (int iii, CMD_PAR_DSCR_T* par, int cry_on_empty)
  80. {
  81.   register int kkk;
  82.   if (! par->param_help) {
  83.     if (cry_on_empty)
  84.       printf ("absent parameter #%dn", iii);
  85.     return 1;
  86.   }
  87.   printf ("    arg%2d: %s", iii + 1, par->param_help);
  88.   switch (par->param_type) {
  89.     case CMD_PAR_NUMBER:
  90.       printf ("; integer in [%ld, %ld]",par->number_limits.min,par->number_limits.max);
  91.       break;
  92.     case CMD_PAR_STRING:
  93.       break;
  94.     case CMD_PAR_BOOL_YN:
  95.     case CMD_PAR_ENUM:
  96.       printf ("n");
  97.       for (kkk = 0; par->string_selector[kkk].string_value; kkk++) {
  98.          printf ("           %-20st%sn", 
  99.                  par->string_selector[kkk].string_value,
  100.                  par->string_selector[kkk].string_help);
  101.       }
  102.       break;
  103.   }
  104.   if (par->default_value) {
  105.       printf ("           default '%s'", par->default_value);
  106.   }
  107.   printf (" n");
  108.   return 0;
  109. }
  110. void help_on_command (CMD_DSCR_T* reg, char brief)
  111. {
  112.   register CMD_PAR_DSCR_T* par;
  113.   register int iii;
  114.   if (brief) {
  115.     printf ("%-20s %sn", reg->cmd_name, reg->cmd_help);
  116.     return;
  117.   }
  118.   printf ("%s: %sn", reg->cmd_name, reg->cmd_help);
  119.   for (iii = 0; iii < 2 + strlen (reg->cmd_name) + strlen (reg->cmd_help); iii++)
  120.     printf ("-");
  121.   printf ("n");
  122.   if (reg->param->param_help)
  123.     printf ("  arguments:n  ----------n");
  124.   for (iii = 0, par = reg->param; ; iii++, par++) {
  125.     if (! par->param_help) break;
  126.     help_on_param (iii + 1, par, 0);
  127.   }
  128.   if (reg->param->param_help)
  129.     printf ("n");
  130. }
  131. static int cli_dummy (int argc, char** argv)
  132. {
  133.   return 0;
  134. }
  135. static CMD_DSCR_T stdcmd[] = {
  136.   THE_COMMAND("exit", "'shutdown'")
  137.   THE_FUNC(cli_dummy)
  138.   THE_COMMAND("?", "help")
  139.   THE_FUNC(cli_dummy)
  140.   END_OF_LANG
  141. };
  142. static char* get_commnad_name (int list_index)
  143. {
  144.   register CMD_DSCR_T* reg;
  145.   if (list_index < 2 && list_index >= 0) {
  146.     return stdcmd[list_index].cmd_name;
  147.   }
  148.   list_index -= 2;
  149.   reg = TheList + list_index;
  150.   if (reg->cmd_name && *reg->cmd_name)
  151.     return reg->cmd_name;
  152.   return NULL;
  153. }
  154. static int find_command (const char* line, char forHelp, CMD_DSCR_T **reg_ptr)
  155. {
  156.   register CMD_DSCR_T* reg;
  157.   register int iii = 0;
  158.   for (reg = stdcmd; reg->cmd_name; reg++) {
  159.     if (! strncasecmp (reg->cmd_name, line, strlen (line))) {
  160.       *reg_ptr = reg; iii++;
  161.       if (forHelp)
  162.         help_on_command (reg, 1);
  163.     }
  164.   }
  165.   for (reg = TheList; reg->cmd_name; reg++) {
  166.     if (! strncasecmp (reg->cmd_name, line, strlen (line))) {
  167.       *reg_ptr = reg; iii++;
  168.       if (forHelp)
  169.         help_on_command (reg, 1);
  170.     }
  171.   }
  172.   return iii;
  173. }
  174. void usage (void)
  175. {
  176.   CMD_DSCR_T* reg;
  177.   if (! TheList) {
  178.     printf ("Sorry, command list hasn't been registeredn");
  179.     return;
  180.   }
  181.   printf ("List of possible commands:n");
  182.   for (reg = TheList; reg->cmd_name; reg++) {
  183.     help_on_command (reg, 1);
  184.   }
  185.   printf ("'standard' commands:n");
  186.   for (reg = stdcmd; reg->cmd_name; reg++) {
  187.     help_on_command (reg, 1);
  188.   }
  189. }
  190. void cli_debug_dump_args (char* title, int argc, char** argv)
  191. {
  192.   int iii;
  193.   printf ("in %s argc=%dn", title, argc);
  194.   for (iii = 0; iii < argc; iii++)
  195.     printf ("targv[%d]='%s'n", iii, argv[iii]);
  196.   printf ("n");
  197. }
  198. static int count_command_paramms (CMD_DSCR_T* reg)
  199. {
  200.   register int iii;
  201.   register CMD_PAR_DSCR_T* par;
  202.   for (iii = 0, par = reg->param; ; iii++, par++) {
  203.     if (! par->param_help) break;
  204.   }
  205.   return iii;
  206. }
  207. static void
  208. cli_help_brosed_line (int argc, char** argv, const char* line)
  209. {
  210.   char pool[MAX_CLI_BUFF];
  211.   CMD_DSCR_T* reg;
  212.   int iii, nf;
  213.   printf ("n");
  214. #if 0
  215.   cli_debug_dump_args ("cli_help_brosed_line", argc, argv);
  216. #endif
  217.   memset (pool, 0, MAX_CLI_BUFF);
  218.   for (iii = 0; iii < argc; iii++) {
  219.     if (iii) strcat (pool, " ");
  220.     strcat (pool, argv[iii]);
  221.     nf = find_command (pool, 0, &reg);
  222.     if (1 == nf) {
  223.       nf = count_command_paramms (reg);
  224.       iii++;
  225. #if 0
  226.       printf ("iii=%d argc=%d nf=%dn", iii, argc, nf);
  227. #endif
  228.       nf = strlen (line);
  229.       if (nf && ' ' == line[nf - 1])
  230.         argc++;
  231.       if (iii < argc) {
  232.         iii = argc - iii - 1;
  233.         if (! help_on_param (iii + 1, reg->param + iii, 1)) {
  234.           return;
  235.         }
  236.       }
  237.       help_on_command (reg, 0);
  238.       return;
  239.     } else if (! nf) {
  240.       printf ("nunknown <%s>n", pool);
  241.       usage ();
  242.       return;
  243.     }
  244.   }
  245.   find_command (pool, 1, &reg);
  246. }
  247. void cli_help (int argc, char** argv, const char* line)
  248. {
  249. #if 0
  250.   cli_debug_dump_args ("cli_help", argc, argv);
  251. #endif
  252.   if (argc > 1)
  253.     cli_help_brosed_line (argc - 1, argv + 1, line);
  254.   else
  255.     usage ();
  256. }
  257. static void cli_set_defaults (CMD_DSCR_T* reg, char** argv)
  258. {
  259.   register int iii;
  260.   register CMD_PAR_DSCR_T* par;
  261.   for (iii = 0, par = reg->param; ; iii++, par++) {
  262.     if (! par->param_help) break;
  263.     argv[iii + 1] = par->default_value;
  264.   }
  265. }
  266. static int cli_call_callback (CMD_DSCR_T* reg, const char* line, int* argc, char** argv)
  267. {
  268.   int cnt;
  269.   if (reg->clbk) {
  270.     cnt = cli_count_words (reg->cmd_name);
  271.     /* printf ("cli_count_words returned %dn", cnt); */
  272.     cli_set_defaults (reg, argv);
  273.     *argc = cli_parse_parms (line, cnt, argv);
  274.     return (*reg->clbk) (*argc, argv);
  275.   }
  276.   printf ("<Empty command !>n");
  277.   return 0;
  278. }
  279. int cli_execute_command (const char* line)
  280. {
  281.   CMD_DSCR_T* reg;
  282.   int argc, nf;
  283.   char *argv[MAXPARAMNUM];
  284.   if ('n' == *line || ! *line) return 0;
  285.   /* check "common commands" */
  286.   if ('q' == *line || ! strncasecmp ("ex", line, 2)) {
  287.     return 4;
  288.   }
  289.   if ('?' == *line || 'h' == *line) {
  290.     argc = cli_parse_parms (line, 0, argv);
  291.     cli_help (argc, argv, line);
  292.     return 0;
  293.   }
  294.   if (! TheList) {
  295.     printf ("Sorry, command list hasn't been registeredn");
  296.     return -11;
  297.   }
  298.   for (reg = TheList; reg->cmd_name; reg++) {
  299.     if (! strncasecmp (reg->cmd_name, line, strlen (reg->cmd_name))) {
  300.       return cli_call_callback (reg, line, &argc, argv);
  301.     }
  302.   }
  303.   nf = find_command (line, 0, &reg);
  304.   if (1 == nf)
  305.     return cli_call_callback (reg, line, &argc, argv);
  306.   
  307.   printf ("unknown command: <%s>", line);
  308.   usage ();
  309.   return 0;
  310. }
  311. extern char shutdown_flag;
  312. char read_cli (void)
  313. {
  314.   if (!rl_line_buffer) {
  315.     return 1;
  316.   }
  317.   if (*rl_line_buffer != 0) {
  318.     add_history (rl_line_buffer);
  319.     /** printf ("n try to call <%s>n", rl_line_buffer); **/
  320.     if (0 != cli_execute_command (rl_line_buffer)) {
  321.       printf("Goodbye, I'm a gonnern");
  322.       rl_callback_handler_remove ();
  323.       return 2;
  324.     }
  325.   }
  326.   return 0;
  327. }
  328. #ifdef OLD_READLINE
  329. void rl_read_cli (void)
  330. #else
  331. void rl_read_cli (char *str)
  332. #endif
  333. {
  334.   shutdown_flag |= read_cli ();
  335.   rl_callback_handler_install (get_prompt (), rl_read_cli);
  336. }
  337. char* UT_sprint_time_stamp (void)
  338. {
  339.   time_t      clock;
  340.   struct      tm *local_tm;
  341.   static char time_str[20];
  342.   time(&clock);
  343.   local_tm = localtime (&clock);
  344.   strftime(time_str, 20 - 1, "%H:%M:%S", local_tm);
  345.   return time_str;
  346. }
  347. int complete_status;
  348. /* To disable readline's filename completion */
  349. #ifdef OLD_READLINE
  350. int cli_completion_entry_fucntion (int ignore, int invoking_key)
  351. { return 0; }
  352. #else
  353. char* cli_completion_entry_fucntion (const char *str, int ignore)
  354. { return NULL; }
  355. #endif
  356. #ifdef OLD_READLINE
  357. char* command_generator (char* text, int state)
  358. #else
  359. char* command_generator (const char* text, int state)
  360. #endif
  361. {
  362.   static int list_index, len;
  363.   char *name, dlen;
  364. /****
  365.   printf (" state=%d list_index=%d rl_line_buffer'%s' text'%s'n",
  366.           state, list_index, rl_line_buffer, text);
  367. ****/
  368.   dlen = strlen (rl_line_buffer) - strlen (text);
  369.   if (! state) {
  370.     list_index = 0;
  371.     len = strlen (rl_line_buffer);
  372. /****
  373.     printf ("tlen=%d text<%s>n", len, text);
  374. ****/
  375.   }
  376.   for (;;) { 
  377.     name = get_commnad_name (list_index);
  378.     if (! name) break;
  379.     list_index++;
  380.     if (! strncmp (rl_line_buffer, name, len)) {
  381. /****
  382.       printf (" find <%s> => return '%s'n", name, name + dlen);
  383. ****/
  384.       return strdup (name + dlen);
  385.     }
  386.   }
  387.   return ((char *)NULL);
  388. }
  389. #ifdef OLD_READLINE
  390. int cli_inline_help (void)
  391. #else
  392. int cli_inline_help (int a, int b)
  393. #endif
  394. {
  395.   int argc;
  396.   char *argv[MAXPARAMNUM];
  397.   if (! *rl_line_buffer) {
  398.     usage ();
  399.   } else {
  400.     argc = cli_parse_parms (rl_line_buffer, 0, argv);
  401.     cli_help_brosed_line (argc, argv, (const char*) rl_line_buffer);
  402.   }
  403.   
  404.   rl_on_new_line();
  405.   return 0;
  406. }
  407. char **
  408. cli_private_completion (char *text, int start, int end)
  409. {
  410.   char **matches = NULL;
  411. #ifdef OLD_READLINE
  412.   matches = completion_matches (text, command_generator);
  413. #else
  414.   matches = rl_completion_matches (text, command_generator);
  415. #endif
  416.   return matches;
  417. }
  418. void rl_init ()
  419. {
  420.   /* disable completion */
  421. #if 0
  422.   rl_bind_key ('t', rl_insert);  
  423. #else
  424.   rl_callback_handler_install (get_prompt (), rl_read_cli);
  425.   rl_bind_key ('?', cli_inline_help);
  426.   rl_completion_entry_function = cli_completion_entry_fucntion;
  427.   rl_attempted_completion_function = (CPPFunction *)cli_private_completion;
  428.   rl_completion_append_character = '';
  429. #endif
  430. }
  431. void rl_shutdown ()
  432. {
  433.   rl_initialize ();
  434. }