pg: exec file fixes
[vpp.git] / src / vlib / unix / cli.c
index 6b02fdf..7b9a231 100644 (file)
@@ -92,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
@@ -242,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.
@@ -447,13 +449,6 @@ static unix_cli_parse_actions_t unix_cli_parse_pager[] = {
 
 #undef _
 
-/** CLI session events. */
-typedef enum
-{
-  UNIX_CLI_PROCESS_EVENT_READ_READY,  /**< A file descriptor has data to be read. */
-  UNIX_CLI_PROCESS_EVENT_QUIT,       /**< A CLI session wants to close. */
-} unix_cli_process_event_type_t;
-
 /** CLI session telnet negotiation timer events. */
 typedef enum
 {
@@ -493,7 +488,7 @@ typedef struct
   /** List of new sessions */
   unix_cli_new_session_t *new_sessions;
 
-  /* Macro expander */
+  /** system default macro table */
   clib_macro_main_t macro_main;
 
 } unix_cli_main_t;
@@ -501,6 +496,24 @@ typedef struct
 /** 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.
  *
@@ -1243,9 +1256,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);
@@ -2500,6 +2513,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;
            }
@@ -2575,9 +2589,11 @@ more:
       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 (&cm->macro_main,
+      expanded = (u8 *) clib_macro_eval (&cf->macro_main,
                                         (i8 *) cf->current_command,
-                                        1 /* complain */ );
+                                        1 /* complain */ ,
+                                        0 /* level */ ,
+                                        8 /* max_level */ );
       /* Macro processor NULL terminates the return */
       _vec_len (expanded) -= 1;
       vec_reset_length (cf->current_command);
@@ -2685,10 +2701,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);
 }
 
@@ -2868,9 +2886,9 @@ unix_cli_file_add (unix_cli_main_t * cm, char *name, int fd)
        * the same new name.
        * Then, throw away the old shared name-vector.
        */
-      for (i = 0; i < vec_len (vlib_mains); i++)
+      for (i = 0; i < vlib_get_n_threads (); i++)
        {
-         this_vlib_main = vlib_mains[i];
+         this_vlib_main = vlib_get_main_by_index (i);
          if (this_vlib_main == 0)
            continue;
          n = vlib_get_node (this_vlib_main,
@@ -2906,6 +2924,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;
@@ -3333,11 +3352,16 @@ unix_cli_exec (vlib_main_t * vm,
   char *file_name;
   int fd;
   unformat_input_t sub_input;
+  unformat_input_t _line_input, *line_input = &_line_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))
     {
@@ -3354,25 +3378,69 @@ 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_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;
+       }
 
-  unformat_init_clib_file (&sub_input, fd);
+      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);
+  while (unformat_user (&sub_input, unformat_line_input, line_input))
+    {
+      vlib_cli_input (vm, line_input, 0, 0);
+      unformat_free (line_input);
+    }
   unformat_free (&sub_input);
 
 done:
@@ -3505,7 +3573,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);
@@ -3518,7 +3586,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);
 
@@ -3658,7 +3726,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,
@@ -3671,7 +3739,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
 
@@ -3962,7 +4030,7 @@ define_cmd_fn (vlib_main_t * vm,
 {
   u8 *macro_name;
   unformat_input_t _line_input, *line_input = &_line_input;
-  unix_cli_main_t *cm = &unix_cli_main;
+  clib_macro_main_t *mm = get_macro_main ();
   clib_error_t *error;
 
   if (!unformat (input, "%s", &macro_name))
@@ -3980,8 +4048,7 @@ define_cmd_fn (vlib_main_t * vm,
     }
   /* the macro expander expects c-strings, not vectors... */
   vec_add1 (line_input->buffer, 0);
-  clib_macro_set_value (&cm->macro_main, (char *) macro_name,
-                       (char *) line_input->buffer);
+  clib_macro_set_value (mm, (char *) macro_name, (char *) line_input->buffer);
   vec_free (macro_name);
   unformat_free (line_input);
   return 0;
@@ -4001,12 +4068,12 @@ undefine_cmd_fn (vlib_main_t * vm,
                 unformat_input_t * input, vlib_cli_command_t * cmd)
 {
   u8 *macro_name;
-  unix_cli_main_t *cm = &unix_cli_main;
+  clib_macro_main_t *mm = get_macro_main ();
 
   if (!unformat (input, "%s", &macro_name))
     return clib_error_return (0, "missing variable name...");
 
-  if (clib_macro_unset (&cm->macro_main, (char *) macro_name))
+  if (clib_macro_unset (mm, (char *) macro_name))
     vlib_cli_output (vm, "%s wasn't set...", macro_name);
 
   vec_free (macro_name);
@@ -4025,7 +4092,7 @@ static clib_error_t *
 show_macro_cmd_fn (vlib_main_t * vm,
                   unformat_input_t * input, vlib_cli_command_t * cmd)
 {
-  unix_cli_main_t *cm = &unix_cli_main;
+  clib_macro_main_t *mm = get_macro_main ();
   int evaluate = 1;
 
   if (unformat (input, "noevaluate %=", &evaluate, 0))
@@ -4033,8 +4100,7 @@ show_macro_cmd_fn (vlib_main_t * vm,
   else if (unformat (input, "noeval %=", &evaluate, 0))
     ;
 
-  vlib_cli_output (vm, "%U", format_clib_macro_main, &cm->macro_main,
-                  evaluate);
+  vlib_cli_output (vm, "%U", format_clib_macro_main, mm, evaluate);
   return 0;
 }
 
@@ -4055,6 +4121,7 @@ unix_cli_init (vlib_main_t * vm)
    * has not been started */
   cm->new_session_process_node_index = ~0;
   clib_macro_init (&cm->macro_main);
+
   return 0;
 }