X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Funix%2Fcli.c;h=8120befef716d5b3ce67a5ef53016487e90c5e1a;hb=bad1d35d7d4ed37f046d17fe7a0b6f7d8897d3d6;hp=b553e12bac238023674a3975fc62625e722326c1;hpb=10a22a629468b18f5b07316980e2761285283939;p=vpp.git diff --git a/src/vlib/unix/cli.c b/src/vlib/unix/cli.c index b553e12bac2..8120befef71 100644 --- a/src/vlib/unix/cli.c +++ b/src/vlib/unix/cli.c @@ -61,6 +61,7 @@ #include #include #include +#include /** ANSI escape code. */ #define ESC "\x1b" @@ -91,7 +92,7 @@ /** Maximum depth into a byte stream from which to compile a Telnet * protocol message. This is a safety measure. */ -#define UNIX_CLI_MAX_DEPTH_TELNET 24 +#define UNIX_CLI_MAX_DEPTH_TELNET 32 /** Maximum terminal width we will accept */ #define UNIX_CLI_MAX_TERMINAL_WIDTH 512 @@ -241,6 +242,8 @@ typedef struct */ u8 cursor_direction; + /** Macro tables for this session */ + clib_macro_main_t macro_main; } unix_cli_file_t; /** Resets the pager buffer and other data. @@ -491,11 +494,33 @@ typedef struct /** List of new sessions */ unix_cli_new_session_t *new_sessions; + + /** system default macro table */ + clib_macro_main_t macro_main; + } unix_cli_main_t; /** CLI global state */ static unix_cli_main_t unix_cli_main; +/** Return the macro main / tables we should use for this session + */ +static clib_macro_main_t * +get_macro_main (void) +{ + unix_cli_main_t *cm = &unix_cli_main; + vlib_main_t *vm = vlib_get_main (); + vlib_process_t *cp = vlib_get_current_process (vm); + unix_cli_file_t *cf; + + if (pool_is_free_index (cm->cli_file_pool, cp->output_function_arg)) + return (&cm->macro_main); + + cf = pool_elt_at_index (cm->cli_file_pool, cp->output_function_arg); + + return (&cf->macro_main); +} + /** * @brief Search for a byte sequence in the action list. * @@ -1238,9 +1263,9 @@ unix_cli_file_welcome (unix_cli_main_t * cm, unix_cli_file_t * cf) */ unix_cli_add_pending_output (uf, cf, (u8 *) "\r", 1); - if (!um->cli_no_banner) + if (!um->cli_no_banner && (um->flags & UNIX_FLAG_NOBANNER) == 0) { - if (cf->ansi_capable) + if (cf->ansi_capable && (um->flags & UNIX_FLAG_NOCOLOR) == 0) { banner = unix_cli_banner_color; len = ARRAY_LEN (unix_cli_banner_color); @@ -2495,6 +2520,7 @@ unix_cli_line_edit (unix_cli_main_t * cm, unix_main_t * um, if (cf->line_mode) { vec_delete (cf->input_vector, i, 0); + vec_free (cf->current_command); cf->current_command = cf->input_vector; return 0; } @@ -2563,6 +2589,25 @@ more: int rv __attribute__ ((unused)) = write (um->log_fd, lv, vec_len (lv)); } + /* Run the command through the macro processor */ + if (vec_len (cf->current_command)) + { + u8 *expanded; + vec_validate (cf->current_command, vec_len (cf->current_command)); + cf->current_command[vec_len (cf->current_command) - 1] = 0; + /* The macro expander expects proper C-strings, not vectors */ + expanded = (u8 *) clib_macro_eval (&cf->macro_main, + (i8 *) cf->current_command, + 1 /* complain */ , + 0 /* level */ , + 8 /* max_level */ ); + /* Macro processor NULL terminates the return */ + _vec_len (expanded) -= 1; + vec_reset_length (cf->current_command); + vec_append (cf->current_command, expanded); + vec_free (expanded); + } + /* Build an unformat structure around our command */ unformat_init_vector (&input, cf->current_command); @@ -2663,10 +2708,12 @@ unix_cli_kill (unix_cli_main_t * cm, uword cli_file_index) vec_free (cf->command_history[i]); vec_free (cf->command_history); + vec_free (cf->input_vector); clib_file_del (fm, uf); unix_cli_file_free (cf); + clib_macro_free (&cf->macro_main); pool_put (cm->cli_file_pool, cf); } @@ -2884,6 +2931,7 @@ unix_cli_file_add (unix_cli_main_t * cm, char *name, int fd) pool_get (cm->cli_file_pool, cf); clib_memset (cf, 0, sizeof (*cf)); + clib_macro_init (&cf->macro_main); template.read_function = unix_cli_read_ready; template.write_function = unix_cli_write_ready; @@ -2896,6 +2944,8 @@ unix_cli_file_add (unix_cli_main_t * cm, char *name, int fd) cf->clib_file_index = clib_file_add (fm, &template); cf->output_vector = 0; cf->input_vector = 0; + vec_validate (cf->current_command, 0); + _vec_len (cf->current_command) = 0; vlib_start_process (vm, n->runtime_index); @@ -3310,10 +3360,14 @@ unix_cli_exec (vlib_main_t * vm, int fd; unformat_input_t sub_input; clib_error_t *error; - + unix_cli_main_t *cm = &unix_cli_main; + unix_cli_file_t *cf; + u8 *file_data = 0; file_name = 0; fd = -1; error = 0; + struct stat s; + if (!unformat (input, "%s", &file_name)) { @@ -3330,23 +3384,63 @@ unix_cli_exec (vlib_main_t * vm, } /* Make sure its a regular file. */ - { - struct stat s; + if (fstat (fd, &s) < 0) + { + error = clib_error_return_unix (0, "failed to stat `%s'", file_name); + goto done; + } - if (fstat (fd, &s) < 0) - { - error = clib_error_return_unix (0, "failed to stat `%s'", file_name); - goto done; - } + if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode))) + { + error = clib_error_return (0, "not a regular file `%s'", file_name); + goto done; + } - if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode))) - { - error = clib_error_return (0, "not a regular file `%s'", file_name); - goto done; - } - } + /* Read the file */ + vec_validate (file_data, s.st_size); + + if (read (fd, file_data, s.st_size) != s.st_size) + { + error = clib_error_return_unix (0, "Failed to read %d bytes from '%s'", + s.st_size, file_name); + vec_free (file_data); + goto done; + } + + /* The macro expander expects a c string... */ + vec_add1 (file_data, 0); - unformat_init_clib_file (&sub_input, fd); + unformat_init_vector (&sub_input, file_data); + + /* Run the file contents through the macro processor */ + if (vec_len (sub_input.buffer) > 1) + { + u8 *expanded; + clib_macro_main_t *mm = 0; + + /* Initial config process? Use the global macro table. */ + if (pool_is_free_index + (cm->cli_file_pool, cm->current_input_file_index)) + mm = &cm->macro_main; + else + { + /* Otherwise, use the per-cli-process macro table */ + cf = pool_elt_at_index (cm->cli_file_pool, + cm->current_input_file_index); + mm = &cf->macro_main; + } + + expanded = (u8 *) clib_macro_eval (mm, + (i8 *) sub_input.buffer, + 1 /* complain */ , + 0 /* level */ , + 8 /* max_level */ ); + /* Macro processor NULL terminates the return */ + _vec_len (expanded) -= 1; + vec_reset_length (sub_input.buffer); + vec_append (sub_input.buffer, expanded); + vec_free (expanded); + } vlib_cli_input (vm, &sub_input, 0, 0); unformat_free (&sub_input); @@ -3481,7 +3575,7 @@ unix_show_files (vlib_main_t * vm, "Read", "Write", "Error", "File Name", "Description"); /* *INDENT-OFF* */ - pool_foreach (f, fm->file_pool,( + pool_foreach (f, fm->file_pool) { int rv; s = format (s, "/proc/self/fd/%d%c", f->file_descriptor, 0); @@ -3494,7 +3588,7 @@ unix_show_files (vlib_main_t * vm, f->read_events, f->write_events, f->error_events, path, f->description); vec_reset_length (s); - })); + } /* *INDENT-ON* */ vec_free (s); @@ -3634,7 +3728,7 @@ unix_cli_show_cli_sessions (vlib_main_t * vm, #define fl(x, y) ( (x) ? toupper((y)) : tolower((y)) ) /* *INDENT-OFF* */ - pool_foreach (cf, cm->cli_file_pool, ({ + pool_foreach (cf, cm->cli_file_pool) { uf = pool_elt_at_index (fm->file_pool, cf->clib_file_index); n = vlib_get_node (vm, cf->process_node_index); vlib_cli_output (vm, @@ -3647,7 +3741,7 @@ unix_cli_show_cli_sessions (vlib_main_t * vm, fl (cf->line_mode, 'l'), fl (cf->has_epipe, 'p'), fl (cf->ansi_capable, 'a')); - })); + } /* *INDENT-ON* */ #undef fl @@ -3905,6 +3999,121 @@ VLIB_CLI_COMMAND (cli_unix_wait_cmd, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +echo_cmd (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + { + vlib_cli_output (vm, ""); + return 0; + } + + vlib_cli_output (vm, "%v", line_input->buffer); + + unformat_free (line_input); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_unix_echo_cmd, static) = { + .path = "echo", + .short_help = "echo ", + .function = echo_cmd, +}; +/* *INDENT-ON* */ + +static clib_error_t * +define_cmd_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + u8 *macro_name; + unformat_input_t _line_input, *line_input = &_line_input; + clib_macro_main_t *mm = get_macro_main (); + clib_error_t *error; + + if (!unformat (input, "%s", ¯o_name)) + return clib_error_return (0, "missing variable name..."); + + /* Remove white space */ + (void) unformat (input, ""); + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + { + error = clib_error_return (0, "missing value for '%s'...", macro_name); + vec_free (macro_name); + return error; + } + /* the macro expander expects c-strings, not vectors... */ + vec_add1 (line_input->buffer, 0); + clib_macro_set_value (mm, (char *) macro_name, (char *) line_input->buffer); + vec_free (macro_name); + unformat_free (line_input); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (define_cmd, static) = { + .path = "define", + .short_help = "define ", + .function = define_cmd_fn, +}; + +/* *INDENT-ON* */ + +static clib_error_t * +undefine_cmd_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + u8 *macro_name; + clib_macro_main_t *mm = get_macro_main (); + + if (!unformat (input, "%s", ¯o_name)) + return clib_error_return (0, "missing variable name..."); + + if (clib_macro_unset (mm, (char *) macro_name)) + vlib_cli_output (vm, "%s wasn't set...", macro_name); + + vec_free (macro_name); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (undefine_cmd, static) = { + .path = "undefine", + .short_help = "undefine ", + .function = undefine_cmd_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +show_macro_cmd_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + clib_macro_main_t *mm = get_macro_main (); + int evaluate = 1; + + if (unformat (input, "noevaluate %=", &evaluate, 0)) + ; + else if (unformat (input, "noeval %=", &evaluate, 0)) + ; + + vlib_cli_output (vm, "%U", format_clib_macro_main, mm, evaluate); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_macro, static) = { + .path = "show macro", + .short_help = "show macro [noevaluate]", + .function = show_macro_cmd_fn, +}; +/* *INDENT-ON* */ + static clib_error_t * unix_cli_init (vlib_main_t * vm) { @@ -3913,6 +4122,7 @@ unix_cli_init (vlib_main_t * vm) /* Breadcrumb to indicate the new session process * has not been started */ cm->new_session_process_node_index = ~0; + clib_macro_init (&cm->macro_main); return 0; }