1 /************************************************************************
2 * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3 * Copyright (C) 2001-2003 Optical Access
6 * This file is part of RSTP library.
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
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.
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
21 **********************************************************************/
29 #include <sys/types.h>
33 #include <readline/readline.h>
34 #include <readline/history.h>
38 static CMD_DSCR_T
* TheList
= 0;
41 cli_parse_parms (const char* line
, int skip_words
, char** argv
)
43 static char pool
[MAX_CLI_BUFF
];
45 register int argc
= 0, iii
;
47 ptr
= strchr (line
, '\n');
49 memcpy (pool
, line
, MAX_CLI_BUFF
);
50 pool
[MAX_CLI_BUFF
- 1] = '\0';
52 for (iii
= 0; iii
< MAXPARAMNUM
; iii
++) {
53 ptr
= strtok (iii
? NULL
: pool
, "\t\n ");
55 if (skip_words
-- <= 0) {
56 /* printf ("\targv[%d]='%s' skip_words=%d\n", argc, ptr, skip_words); */
59 /* printf ("\tskip '%s' skip_words now %d\n", ptr, skip_words); */
66 int cli_count_words (char* line
)
68 static char pool
[MAX_CLI_BUFF
];
69 register char* ptr
= NULL
;
72 ptr
= strchr (line
, '\n');
74 strncpy (pool
, line
, MAX_CLI_BUFF
);
75 pool
[MAX_CLI_BUFF
- 1] = '\0';
77 for (cnt
= 0;; cnt
++) {
78 ptr
= strtok (cnt
? NULL
: pool
, "\t\n ");
87 void cli_register_language (const CMD_DSCR_T
* cmd_list
)
89 TheList
= ( CMD_DSCR_T
*) cmd_list
;
92 static int help_on_param (int iii
, CMD_PAR_DSCR_T
* par
, int cry_on_empty
)
96 if (! par
->param_help
) {
98 printf ("absent parameter #%d\n", iii
);
102 printf (" arg%2d: %s", iii
+ 1, par
->param_help
);
103 switch (par
->param_type
) {
105 printf ("; integer in [%ld, %ld]",par
->number_limits
.min
,par
->number_limits
.max
);
109 case CMD_PAR_BOOL_YN
:
112 for (kkk
= 0; par
->string_selector
[kkk
].string_value
; kkk
++) {
113 printf (" %-20s\t%s\n",
114 par
->string_selector
[kkk
].string_value
,
115 par
->string_selector
[kkk
].string_help
);
120 if (par
->default_value
) {
121 printf (" default '%s'", par
->default_value
);
127 void help_on_command (CMD_DSCR_T
* reg
, char brief
)
129 register CMD_PAR_DSCR_T
* par
;
133 printf ("%-20s %s\n", reg
->cmd_name
, reg
->cmd_help
);
136 printf ("%s: %s\n", reg
->cmd_name
, reg
->cmd_help
);
137 for (iii
= 0; iii
< 2 + strlen (reg
->cmd_name
) + strlen (reg
->cmd_help
); iii
++)
141 if (reg
->param
->param_help
)
142 printf (" arguments:\n ----------\n");
143 for (iii
= 0, par
= reg
->param
; ; iii
++, par
++) {
144 if (! par
->param_help
) break;
145 help_on_param (iii
+ 1, par
, 0);
147 if (reg
->param
->param_help
)
151 static int cli_dummy (int argc
, char** argv
)
156 static CMD_DSCR_T stdcmd
[] = {
157 THE_COMMAND("exit", "'shutdown'")
160 THE_COMMAND("?", "help")
166 static char* get_commnad_name (int list_index
)
168 register CMD_DSCR_T
* reg
;
170 if (list_index
< 2 && list_index
>= 0) {
171 return stdcmd
[list_index
].cmd_name
;
175 reg
= TheList
+ list_index
;
176 if (reg
->cmd_name
&& *reg
->cmd_name
)
177 return reg
->cmd_name
;
181 static int find_command (const char* line
, char forHelp
, CMD_DSCR_T
**reg_ptr
)
183 register CMD_DSCR_T
* reg
;
184 register int iii
= 0;
186 for (reg
= stdcmd
; reg
->cmd_name
; reg
++) {
187 if (! strncasecmp (reg
->cmd_name
, line
, strlen (line
))) {
188 *reg_ptr
= reg
; iii
++;
190 help_on_command (reg
, 1);
194 for (reg
= TheList
; reg
->cmd_name
; reg
++) {
195 if (! strncasecmp (reg
->cmd_name
, line
, strlen (line
))) {
196 *reg_ptr
= reg
; iii
++;
198 help_on_command (reg
, 1);
210 printf ("Sorry, command list hasn't been registered\n");
214 printf ("List of possible commands:\n");
215 for (reg
= TheList
; reg
->cmd_name
; reg
++) {
216 help_on_command (reg
, 1);
219 printf ("'standard' commands:\n");
220 for (reg
= stdcmd
; reg
->cmd_name
; reg
++) {
221 help_on_command (reg
, 1);
225 void cli_debug_dump_args (char* title
, int argc
, char** argv
)
228 printf ("in %s argc=%d\n", title
, argc
);
229 for (iii
= 0; iii
< argc
; iii
++)
230 printf ("\targv[%d]='%s'\n", iii
, argv
[iii
]);
235 static int count_command_paramms (CMD_DSCR_T
* reg
)
238 register CMD_PAR_DSCR_T
* par
;
240 for (iii
= 0, par
= reg
->param
; ; iii
++, par
++) {
241 if (! par
->param_help
) break;
247 cli_help_brosed_line (int argc
, char** argv
, const char* line
)
249 char pool
[MAX_CLI_BUFF
];
255 cli_debug_dump_args ("cli_help_brosed_line", argc
, argv
);
258 memset (pool
, 0, MAX_CLI_BUFF
);
259 for (iii
= 0; iii
< argc
; iii
++) {
260 if (iii
) strcat (pool
, " ");
261 strcat (pool
, argv
[iii
]);
262 nf
= find_command (pool
, 0, ®
);
264 nf
= count_command_paramms (reg
);
267 printf ("iii=%d argc=%d nf=%d\n", iii
, argc
, nf
);
270 if (nf
&& ' ' == line
[nf
- 1])
273 iii
= argc
- iii
- 1;
274 if (! help_on_param (iii
+ 1, reg
->param
+ iii
, 1)) {
278 help_on_command (reg
, 0);
281 printf ("\nunknown <%s>\n", pool
);
286 find_command (pool
, 1, ®
);
289 void cli_help (int argc
, char** argv
, const char* line
)
292 cli_debug_dump_args ("cli_help", argc
, argv
);
295 cli_help_brosed_line (argc
- 1, argv
+ 1, line
);
300 static void cli_set_defaults (CMD_DSCR_T
* reg
, char** argv
)
303 register CMD_PAR_DSCR_T
* par
;
305 for (iii
= 0, par
= reg
->param
; ; iii
++, par
++) {
306 if (! par
->param_help
) break;
307 argv
[iii
+ 1] = par
->default_value
;
311 static int cli_call_callback (CMD_DSCR_T
* reg
, const char* line
, int* argc
, char** argv
)
316 cnt
= cli_count_words (reg
->cmd_name
);
317 /* printf ("cli_count_words returned %d\n", cnt); */
318 cli_set_defaults (reg
, argv
);
319 *argc
= cli_parse_parms (line
, cnt
, argv
);
320 return (*reg
->clbk
) (*argc
, argv
);
322 printf ("<Empty command !>\n");
326 int cli_execute_command (const char* line
)
330 char *argv
[MAXPARAMNUM
];
332 if ('\n' == *line
|| ! *line
) return 0;
334 /* check "common commands" */
335 if ('q' == *line
|| ! strncasecmp ("ex", line
, 2)) {
339 if ('?' == *line
|| 'h' == *line
) {
340 argc
= cli_parse_parms (line
, 0, argv
);
341 cli_help (argc
, argv
, line
);
346 printf ("Sorry, command list hasn't been registered\n");
350 for (reg
= TheList
; reg
->cmd_name
; reg
++) {
351 if (! strncasecmp (reg
->cmd_name
, line
, strlen (reg
->cmd_name
))) {
352 return cli_call_callback (reg
, line
, &argc
, argv
);
356 nf
= find_command (line
, 0, ®
);
358 return cli_call_callback (reg
, line
, &argc
, argv
);
360 printf ("unknown command: <%s>", line
);
365 extern char shutdown_flag
;
369 if (!rl_line_buffer
) {
373 if (*rl_line_buffer
!= 0) {
374 add_history (rl_line_buffer
);
375 /** printf ("\n try to call <%s>\n", rl_line_buffer); **/
377 if (0 != cli_execute_command (rl_line_buffer
)) {
378 printf("Goodbye, I'm a gonner\n");
379 rl_callback_handler_remove ();
388 void rl_read_cli (void)
390 void rl_read_cli (char *str
)
393 shutdown_flag
|= read_cli ();
394 rl_callback_handler_install (get_prompt (), rl_read_cli
);
397 char* UT_sprint_time_stamp (void)
401 static char time_str
[20];
404 local_tm
= localtime (&clock
);
405 strftime(time_str
, 20 - 1, "%H:%M:%S", local_tm
);
411 /* To disable readline's filename completion */
413 int cli_completion_entry_fucntion (int ignore
, int invoking_key
)
416 char* cli_completion_entry_fucntion (const char *str
, int ignore
)
421 char* command_generator (char* text
, int state
)
423 char* command_generator (const char* text
, int state
)
426 static int list_index
, len
;
430 printf (" state=%d list_index=%d rl_line_buffer'%s' text'%s'\n",
431 state, list_index, rl_line_buffer, text);
434 dlen
= strlen (rl_line_buffer
) - strlen (text
);
437 len
= strlen (rl_line_buffer
);
439 printf ("\tlen=%d text<%s>\n", len, text);
444 name
= get_commnad_name (list_index
);
447 if (! strncmp (rl_line_buffer
, name
, len
)) {
449 printf (" find <%s> => return '%s'\n", name, name + dlen);
451 return strdup (name
+ dlen
);
455 return ((char *)NULL
);
459 int cli_inline_help (void)
461 int cli_inline_help (int a
, int b
)
465 char *argv
[MAXPARAMNUM
];
467 if (! *rl_line_buffer
) {
470 argc
= cli_parse_parms (rl_line_buffer
, 0, argv
);
471 cli_help_brosed_line (argc
, argv
, (const char*) rl_line_buffer
);
480 cli_private_completion (char *text
, int start
, int end
)
482 char **matches
= NULL
;
485 matches
= completion_matches (text
, command_generator
);
487 matches
= rl_completion_matches (text
, command_generator
);
495 /* disable completion */
497 rl_bind_key ('\t', rl_insert
);
499 rl_callback_handler_install (get_prompt (), rl_read_cli
);
500 rl_bind_key ('?', cli_inline_help
);
501 rl_completion_entry_function
= cli_completion_entry_fucntion
;
502 rl_attempted_completion_function
= (CPPFunction
*)cli_private_completion
;
503 rl_completion_append_character
= '\0';