]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/vty.c
Merge remote-tracking branch 'origin/master' into evpn_plus_struct_attr
[mirror_frr.git] / lib / vty.c
index 54a5f727e1110b97c535426262f5c734cf71079e..a6cd75f1c18f4d74e969a21d612ae5179f5267cf 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -92,28 +92,23 @@ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
 
 static int do_log_commands = 0;
 
-/* VTY standard output function. */
-int
-vty_out (struct vty *vty, const char *format, ...)
+static int
+vty_out_variadic (struct vty *vty, const char *format, va_list args)
 {
-  va_list args;
   int len = 0;
   int size = 1024;
   char buf[1024];
   char *p = NULL;
+  va_list cp;
 
   if (vty_shell (vty))
-    {
-      va_start (args, format);
-      vprintf (format, args);
-      va_end (args);
-    }
+    vprintf (format, args);
   else
     {
       /* Try to write to initial buffer.  */
-      va_start (args, format);
-      len = vsnprintf (buf, sizeof(buf), format, args);
-      va_end (args);
+      va_copy (cp, args);
+      len = vsnprintf (buf, sizeof(buf), format, cp);
+      va_end (cp);
 
       /* Initial buffer is not enough.  */
       if (len < 0 || len >= size)
@@ -129,9 +124,9 @@ vty_out (struct vty *vty, const char *format, ...)
               if (! p)
                 return -1;
 
-              va_start (args, format);
-              len = vsnprintf (p, size, format, args);
-              va_end (args);
+              va_copy (cp, args);
+              len = vsnprintf (p, size, format, cp);
+              va_end (cp);
 
               if (len > -1 && len < size)
                 break;
@@ -152,6 +147,32 @@ vty_out (struct vty *vty, const char *format, ...)
 
   return len;
 }
+/* VTY standard output function. */
+int
+vty_out (struct vty *vty, const char *format, ...)
+{
+  int len;
+  va_list args;
+
+  va_start (args, format);
+  len = vty_out_variadic (vty, format, args);
+  va_end (args);
+
+  return len;
+}
+
+int
+vty_outln (struct vty *vty, const char *format, ...)
+{
+  int len;
+  va_list args;
+
+  va_start (args, format);
+  len = vty_out_variadic (vty, format, args);
+  va_end (args);
+
+  return len + vty_out (vty, "%s", VTYNL);
+}
 
 static int
 vty_log_out (struct vty *vty, const char *level, const char *proto_str,
@@ -244,12 +265,12 @@ vty_hello (struct vty *vty)
               for (s = buf + strlen (buf); (s > buf) && isspace ((int)*(s - 1));
                    s--);
               *s = '\0';
-              vty_out (vty, "%s%s", buf, VTY_NEWLINE);
+              vty_outln (vty, "%s", buf);
             }
           fclose (f);
         }
       else
-        vty_out (vty, "MOTD file not found%s", VTY_NEWLINE);
+        vty_outln (vty, "MOTD file not found");
     }
   else if (host.motd)
     vty_out (vty, "%s", host.motd);
@@ -382,14 +403,14 @@ vty_auth (struct vty *vty, char *buf)
         {
           if (vty->node == AUTH_NODE)
             {
-              vty_out (vty, "%% Bad passwords, too many failures!%s", VTY_NEWLINE);
+              vty_outln (vty, "%% Bad passwords, too many failures!");
               vty->status = VTY_CLOSE;
             }
           else
             {
               /* AUTH_ENABLE_NODE */
               vty->fail = 0;
-              vty_out (vty, "%% Bad enable passwords, too many failures!%s", VTY_NEWLINE);
+              vty_outln (vty, "%% Bad enable passwords, too many failures!");
              vty->status = VTY_CLOSE;
             }
         }
@@ -474,16 +495,16 @@ vty_command (struct vty *vty, char *buf)
       {
       case CMD_WARNING:
         if (vty->type == VTY_FILE)
-          vty_out (vty, "Warning...%s", VTY_NEWLINE);
+          vty_outln (vty, "Warning...");
         break;
       case CMD_ERR_AMBIGUOUS:
-        vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
+        vty_outln (vty, "%% Ambiguous command.");
         break;
       case CMD_ERR_NO_MATCH:
-        vty_out (vty, "%% [%s] Unknown command: %s%s", protocolname, buf, VTY_NEWLINE);
+        vty_outln (vty, "%% [%s] Unknown command: %s", protocolname, buf);
         break;
       case CMD_ERR_INCOMPLETE:
-        vty_out (vty, "%% Command incomplete.%s", VTY_NEWLINE);
+        vty_outln (vty, "%% Command incomplete.");
         break;
       }
   cmd_free_strvec (vline);
@@ -711,7 +732,7 @@ vty_backward_word (struct vty *vty)
 static void
 vty_down_level (struct vty *vty)
 {
-  vty_out (vty, "%s", VTY_NEWLINE);
+  vty_out (vty, VTYNL);
   cmd_exit (vty);
   vty_prompt (vty);
   vty->cp = 0;
@@ -721,7 +742,7 @@ vty_down_level (struct vty *vty)
 static void
 vty_end_config (struct vty *vty)
 {
-  vty_out (vty, "%s", VTY_NEWLINE);
+  vty_out (vty, VTYNL);
 
   switch (vty->node)
     {
@@ -765,6 +786,7 @@ vty_end_config (struct vty *vty)
     case MASC_NODE:
     case PIM_NODE:
     case VTY_NODE:
+    case BGP_EVPN_VNI_NODE:
       vty_config_unlock (vty);
       vty->node = ENABLE_NODE;
       break;
@@ -926,16 +948,16 @@ vty_complete_command (struct vty *vty)
 
   cmd_free_strvec (vline);
 
-  vty_out (vty, "%s", VTY_NEWLINE);
+  vty_out (vty, VTYNL);
   switch (ret)
     {
     case CMD_ERR_AMBIGUOUS:
-      vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
+      vty_outln (vty, "%% Ambiguous command.");
       vty_prompt (vty);
       vty_redraw_line (vty);
       break;
     case CMD_ERR_NO_MATCH:
-      /* vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE); */
+      /* vty_out (vty, "%% There is no matched command.%s", VTYNL); */
       vty_prompt (vty);
       vty_redraw_line (vty);
       break;
@@ -943,7 +965,7 @@ vty_complete_command (struct vty *vty)
       if (!matched[0])
         {
           /* 2016-11-28 equinox -- need to debug, SEGV here */
-          vty_out (vty, "%% CLI BUG: FULL_MATCH with NULL str%s", VTY_NEWLINE);
+          vty_outln (vty, "%% CLI BUG: FULL_MATCH with NULL str");
           vty_prompt (vty);
           vty_redraw_line (vty);
           break;
@@ -966,11 +988,11 @@ vty_complete_command (struct vty *vty)
       for (i = 0; matched[i] != NULL; i++)
         {
           if (i != 0 && ((i % 6) == 0))
-            vty_out (vty, "%s", VTY_NEWLINE);
+            vty_out (vty, VTYNL);
           vty_out (vty, "%-10s ", matched[i]);
           XFREE (MTYPE_COMPLETION, matched[i]);
         }
-      vty_out (vty, "%s", VTY_NEWLINE);
+      vty_out (vty, VTYNL);
 
       vty_prompt (vty);
       vty_redraw_line (vty);
@@ -998,7 +1020,7 @@ vty_describe_fold (struct vty *vty, int cmd_width,
 
   if (desc_width <= 0)
     {
-      vty_out (vty, "  %-*s  %s%s", cmd_width, cmd, token->desc, VTY_NEWLINE);
+      vty_outln (vty, "  %-*s  %s", cmd_width, cmd, token->desc);
       return;
     }
 
@@ -1015,12 +1037,12 @@ vty_describe_fold (struct vty *vty, int cmd_width,
 
       strncpy (buf, p, pos);
       buf[pos] = '\0';
-      vty_out (vty, "  %-*s  %s%s", cmd_width, cmd, buf, VTY_NEWLINE);
+      vty_outln (vty, "  %-*s  %s", cmd_width, cmd, buf);
 
       cmd = "";
     }
 
-  vty_out (vty, "  %-*s  %s%s", cmd_width, cmd, p, VTY_NEWLINE);
+  vty_outln (vty, "  %-*s  %s", cmd_width, cmd, p);
 
   XFREE (MTYPE_TMP, buf);
 }
@@ -1049,17 +1071,17 @@ vty_describe_command (struct vty *vty)
 
   describe = cmd_describe_command (vline, vty, &ret);
 
-  vty_out (vty, "%s", VTY_NEWLINE);
+  vty_out (vty, VTYNL);
 
   /* Ambiguous error. */
   switch (ret)
     {
     case CMD_ERR_AMBIGUOUS:
-      vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
+      vty_outln (vty, "%% Ambiguous command.");
       goto out;
       break;
     case CMD_ERR_NO_MATCH:
-      vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE);
+      vty_outln (vty, "%% There is no matched command.");
       goto out;
       break;
     }
@@ -1097,13 +1119,12 @@ vty_describe_command (struct vty *vty)
           }
 
         if (!token->desc)
-          vty_out (vty, "  %-s%s",
-                   token->text,
-                   VTY_NEWLINE);
+          vty_outln (vty, "  %-s",
+                   token->text);
         else if (desc_width >= strlen (token->desc))
-          vty_out (vty, "  %-*s  %s%s", width,
+          vty_outln (vty, "  %-*s  %s", width,
                    token->text,
-                   token->desc, VTY_NEWLINE);
+                   token->desc);
         else
           vty_describe_fold (vty, width, desc_width, token);
 
@@ -1114,36 +1135,31 @@ vty_describe_command (struct vty *vty)
             vector varcomps = vector_init (VECTOR_MIN_SIZE);
             cmd_variable_complete (token, ref, varcomps);
 
-            if (vector_active(varcomps) > 0)
+            if (vector_active (varcomps) > 0)
               {
-                vty_out(vty, "     ");
-                for (size_t j = 0; j < vector_active (varcomps); j++)
-                  {
-                    char *item = vector_slot (varcomps, j);
-                    vty_out(vty, " %s", item);
-                    XFREE(MTYPE_COMPLETION, item);
-                  }
-                vty_out(vty, "%s", VTY_NEWLINE);
+                char *ac = cmd_variable_comp2str(varcomps, vty->width, VTYNL);
+                vty_outln(vty, "%s", ac);
+                XFREE(MTYPE_TMP, ac);
               }
+
             vector_free(varcomps);
           }
 #if 0
         vty_out (vty, "  %-*s %s%s", width
                  desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
-                 desc->str ? desc->str : "", VTY_NEWLINE);
+                 desc->str ? desc->str : "", VTYNL);
 #endif /* 0 */
       }
 
   if ((token = token_cr))
     {
       if (!token->desc)
-        vty_out (vty, "  %-s%s",
-                 token->text,
-                 VTY_NEWLINE);
+        vty_outln (vty, "  %-s",
+                 token->text);
       else if (desc_width >= strlen (token->desc))
-        vty_out (vty, "  %-*s  %s%s", width,
+        vty_outln (vty, "  %-*s  %s", width,
                  token->text,
-                 token->desc, VTY_NEWLINE);
+                 token->desc);
       else
         vty_describe_fold (vty, width, desc_width, token);
     }
@@ -1169,7 +1185,7 @@ vty_stop_input (struct vty *vty)
 {
   vty->cp = vty->length = 0;
   vty_clear_buf (vty);
-  vty_out (vty, "%s", VTY_NEWLINE);
+  vty_out (vty, VTYNL);
 
   switch (vty->node)
     {
@@ -1280,20 +1296,20 @@ vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes)
           vty_out (vty, "SE ");
           break;
         case TELOPT_ECHO:
-          vty_out (vty, "TELOPT_ECHO %s", VTY_NEWLINE);
+          vty_outln (vty, "TELOPT_ECHO ");
           break;
         case TELOPT_SGA:
-          vty_out (vty, "TELOPT_SGA %s", VTY_NEWLINE);
+          vty_outln (vty, "TELOPT_SGA ");
           break;
         case TELOPT_NAWS:
-          vty_out (vty, "TELOPT_NAWS %s", VTY_NEWLINE);
+          vty_outln (vty, "TELOPT_NAWS ");
           break;
         default:
           vty_out (vty, "%x ", buf[i]);
           break;
         }
     }
-  vty_out (vty, "%s", VTY_NEWLINE);
+  vty_out (vty, VTYNL);
 
 #endif /* TELNET_OPTION_DEBUG */
 
@@ -1330,9 +1346,9 @@ vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes)
                 vty->width = ((vty->sb_buf[1] << 8)|vty->sb_buf[2]);
                 vty->height = ((vty->sb_buf[3] << 8)|vty->sb_buf[4]);
 #ifdef TELNET_OPTION_DEBUG
-                vty_out(vty, "TELNET NAWS window size negotiation completed: "
-                              "width %d, height %d%s",
-                        vty->width, vty->height, VTY_NEWLINE);
+                vty_outln (vty, "TELNET NAWS window size negotiation completed: "
+                              "width %d, height %d",
+                        vty->width, vty->height);
 #endif
               }
             break;
@@ -1589,7 +1605,7 @@ vty_read (struct thread *thread)
           break;
         case '\n':
         case '\r':
-          vty_out (vty, "%s", VTY_NEWLINE);
+          vty_out (vty, VTYNL);
           vty_execute (vty);
           break;
         case '\t':
@@ -1748,7 +1764,7 @@ vty_create (int vty_sock, union sockunion *su)
       /* Vty is not available if password isn't set. */
       if (host.password == NULL && host.password_encrypt == NULL)
         {
-          vty_out (vty, "Vty password is not set.%s", VTY_NEWLINE);
+          vty_outln (vty, "Vty password is not set.");
           vty->status = VTY_CLOSE;
           vty_close (vty);
           return NULL;
@@ -1758,7 +1774,8 @@ vty_create (int vty_sock, union sockunion *su)
   /* Say hello to the world. */
   vty_hello (vty);
   if (! no_password_check)
-    vty_out (vty, "%sUser Access Verification%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+    vty_outln (vty, "%sUser Access Verification%s", VTYNL,
+               VTYNL);
 
   /* Setting up terminal. */
   vty_will_echo (vty);
@@ -2175,7 +2192,7 @@ vtysh_read (struct thread *thread)
       /* Clear command line buffer. */
       vty->cp = vty->length = 0;
       vty_clear_buf (vty);
-      vty_out (vty, "%% Command is too long.%s", VTY_NEWLINE);
+      vty_outln (vty, "%% Command is too long.");
     }
   else
     {
@@ -2201,7 +2218,7 @@ vtysh_read (struct thread *thread)
               if (ret == CMD_SUSPEND)
                 break;
 
-              /* warning: watchquagga hardcodes this result write */
+              /* warning: watchfrr hardcodes this result write */
               header[3] = ret;
               buffer_put(vty->obuf, header, 4);
 
@@ -2318,7 +2335,7 @@ vty_timeout (struct thread *thread)
 
   /* Clear buffer*/
   buffer_reset (vty->obuf);
-  vty_out (vty, "%sVty connection is timed out.%s", VTY_NEWLINE, VTY_NEWLINE);
+  vty_outln (vty, "%sVty connection is timed out.", VTYNL);
 
   /* Close connection. */
   vty->status = VTY_CLOSE;
@@ -2701,7 +2718,7 @@ DEFUN_NOSH (config_who,
     if ((v = vector_slot (vtyvec, i)) != NULL)
       vty_out (vty, "%svty[%d] connected from %s.%s",
                v->config ? "*" : " ",
-               i, v->address, VTY_NEWLINE);
+               i, v->address, VTYNL);
   return CMD_SUCCESS;
 }
 
@@ -2799,9 +2816,8 @@ DEFUN (no_vty_access_class,
   const char *accesslist = (argc == 3) ? argv[idx_word]->arg : NULL;
   if (! vty_accesslist_name || (argc == 3 && strcmp(vty_accesslist_name, accesslist)))
     {
-      vty_out (vty, "Access-class is not currently applied to vty%s",
-               VTY_NEWLINE);
-      return CMD_WARNING;
+      vty_outln (vty,"Access-class is not currently applied to vty");
+      return CMD_WARNING_CONFIG_FAILED;
     }
 
   XFREE(MTYPE_VTY, vty_accesslist_name);
@@ -2843,9 +2859,8 @@ DEFUN (no_vty_ipv6_access_class,
   if (! vty_ipv6_accesslist_name ||
       (argc == 4 && strcmp(vty_ipv6_accesslist_name, accesslist)))
     {
-      vty_out (vty, "IPv6 access-class is not currently applied to vty%s",
-               VTY_NEWLINE);
-      return CMD_WARNING;
+      vty_outln (vty,"IPv6 access-class is not currently applied to vty");
+      return CMD_WARNING_CONFIG_FAILED;
     }
 
   XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
@@ -2945,7 +2960,7 @@ DEFUN_NOSH (show_history,
         }
 
       if (vty->hist[index] != NULL)
-        vty_out (vty, "  %s%s", vty->hist[index], VTY_NEWLINE);
+        vty_out (vty, "  %s%s", vty->hist[index], VTYNL);
 
       index++;
     }
@@ -2968,30 +2983,30 @@ DEFUN (log_commands,
 static int
 vty_config_write (struct vty *vty)
 {
-  vty_out (vty, "line vty%s", VTY_NEWLINE);
+  vty_outln (vty, "line vty");
 
   if (vty_accesslist_name)
-    vty_out (vty, " access-class %s%s",
-             vty_accesslist_name, VTY_NEWLINE);
+    vty_outln (vty, " access-class %s",
+             vty_accesslist_name);
 
   if (vty_ipv6_accesslist_name)
-    vty_out (vty, " ipv6 access-class %s%s",
-             vty_ipv6_accesslist_name, VTY_NEWLINE);
+    vty_outln (vty, " ipv6 access-class %s",
+             vty_ipv6_accesslist_name);
 
   /* exec-timeout */
   if (vty_timeout_val != VTY_TIMEOUT_DEFAULT)
-    vty_out (vty, " exec-timeout %ld %ld%s",
+    vty_outln (vty, " exec-timeout %ld %ld",
              vty_timeout_val / 60,
-             vty_timeout_val % 60, VTY_NEWLINE);
+             vty_timeout_val % 60);
 
   /* login */
   if (no_password_check)
-    vty_out (vty, " no login%s", VTY_NEWLINE);
+    vty_outln (vty, " no login");
 
   if (do_log_commands)
-    vty_out (vty, "log commands%s", VTY_NEWLINE);
+    vty_outln (vty, "log commands");
 
-  vty_out (vty, "!%s", VTY_NEWLINE);
+  vty_outln (vty, "!");
 
   return CMD_SUCCESS;
 }