<p>laforge <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/14436">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">vty: command.c: Fix: multi-choice args are no longer passed incomplete to vty func<br><br>For instance, take command "multi0 (one|two|three)":<br>If user executes "multi0 tw", VTY func will receive argv[0]="two"<br>instead of argv[0]="tw".<br><br>Fixes: OS#4045<br>Change-Id: I91b6621ac3d87fda5412a9b415e7bfb4736c8a9a<br>---<br>M src/vty/command.c<br>M tests/tdef/tdef_vty_test_config_root.vty<br>M tests/vty/vty_transcript_test.vty<br>3 files changed, 56 insertions(+), 18 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/vty/command.c b/src/vty/command.c</span><br><span>index 17d28fe..3c91bfd 100644</span><br><span>--- a/src/vty/command.c</span><br><span>+++ b/src/vty/command.c</span><br><span>@@ -2217,7 +2217,7 @@</span><br><span> cmd_execute_command_real(vector vline, struct vty *vty,</span><br><span>                   struct cmd_element **cmd)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int i, j;</span><br><span>   unsigned int index;</span><br><span>  vector cmd_vector;</span><br><span>   struct cmd_element *cmd_element;</span><br><span>@@ -2228,6 +2228,10 @@</span><br><span>    enum match_type match = 0;</span><br><span>   int varflag;</span><br><span>         char *command;</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Used for temporary storage of cmd_deopt() allocated arguments during</span><br><span style="color: hsl(120, 100%, 40%);">+          argv[] generation */</span><br><span style="color: hsl(120, 100%, 40%);">+       void *cmd_deopt_ctx = NULL;</span><br><span> </span><br><span>      /* Make copy of command elements. */</span><br><span>         cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));</span><br><span>@@ -2293,9 +2297,13 @@</span><br><span>    varflag = 0;</span><br><span>         argc = 0;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ cmd_deopt_ctx = talloc_named_const(tall_vty_cmd_ctx, 0, __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         for (i = 0; i < vector_active(vline); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (argc == CMD_ARGC_MAX)</span><br><span style="color: hsl(0, 100%, 40%);">-                       return CMD_ERR_EXEED_ARGC_MAX;</span><br><span style="color: hsl(120, 100%, 40%);">+                if (argc == CMD_ARGC_MAX) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   rc = CMD_ERR_EXEED_ARGC_MAX;</span><br><span style="color: hsl(120, 100%, 40%);">+                  goto rc_free_deopt_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span>            if (varflag) {</span><br><span>                       argv[argc++] = vector_slot(vline, i);</span><br><span>                        continue;</span><br><span>@@ -2313,7 +2321,32 @@</span><br><span>                       || CMD_OPTION(desc->cmd))</span><br><span>                             argv[argc++] = vector_slot(vline, i);</span><br><span>                } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        argv[argc++] = vector_slot(vline, i);</span><br><span style="color: hsl(120, 100%, 40%);">+                 /* multi choice argument. look up which choice</span><br><span style="color: hsl(120, 100%, 40%);">+                           the user meant (can only be one after</span><br><span style="color: hsl(120, 100%, 40%);">+                         filtering and checking for ambigous). For instance,</span><br><span style="color: hsl(120, 100%, 40%);">+                           if user typed "th" for "(two|three)" arg, we</span><br><span style="color: hsl(120, 100%, 40%);">+                      want to pass "three" in argv[]. */</span><br><span style="color: hsl(120, 100%, 40%);">+                       for (j = 0; j < vector_active(descvec); j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             struct desc *desc = vector_slot(descvec, j);</span><br><span style="color: hsl(120, 100%, 40%);">+                          const char *tmp_cmd;</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (!desc)</span><br><span style="color: hsl(120, 100%, 40%);">+                                    continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             if (cmd_match(desc->cmd, vector_slot(vline, i), ANY_MATCH, true) == NO_MATCH)</span><br><span style="color: hsl(120, 100%, 40%);">+                                      continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             if (CMD_OPTION(desc->cmd)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       /* we need to first remove the [] chars, then check to see what's inside (var or token) */</span><br><span style="color: hsl(120, 100%, 40%);">+                                        tmp_cmd = cmd_deopt(cmd_deopt_ctx, desc->cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+                             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      tmp_cmd = desc->cmd;</span><br><span style="color: hsl(120, 100%, 40%);">+                               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                           if(CMD_VARIABLE(tmp_cmd)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                   argv[argc++] = vector_slot(vline, i);</span><br><span style="color: hsl(120, 100%, 40%);">+                         } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      argv[argc++] = tmp_cmd;</span><br><span style="color: hsl(120, 100%, 40%);">+                               }</span><br><span style="color: hsl(120, 100%, 40%);">+                             break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span>            }</span><br><span>    }</span><br><span> </span><br><span>@@ -2322,10 +2355,14 @@</span><br><span>              *cmd = matched_element;</span><br><span> </span><br><span>  if (matched_element->daemon)</span><br><span style="color: hsl(0, 100%, 40%);">-         return CMD_SUCCESS_DAEMON;</span><br><span style="color: hsl(120, 100%, 40%);">+            rc = CMD_SUCCESS_DAEMON;</span><br><span style="color: hsl(120, 100%, 40%);">+      else    /* Execute matched command. */</span><br><span style="color: hsl(120, 100%, 40%);">+                rc = (*matched_element->func) (matched_element, vty, argc, argv);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        /* Execute matched command. */</span><br><span style="color: hsl(0, 100%, 40%);">-  return (*matched_element->func) (matched_element, vty, argc, argv);</span><br><span style="color: hsl(120, 100%, 40%);">+rc_free_deopt_ctx:</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Now after we called the command func, we can free temporary strings */</span><br><span style="color: hsl(120, 100%, 40%);">+     talloc_free(cmd_deopt_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+   return rc;</span><br><span> }</span><br><span> </span><br><span> int</span><br><span>diff --git a/tests/tdef/tdef_vty_test_config_root.vty b/tests/tdef/tdef_vty_test_config_root.vty</span><br><span>index 8613ff3..f3aba0f 100644</span><br><span>--- a/tests/tdef/tdef_vty_test_config_root.vty</span><br><span>+++ b/tests/tdef/tdef_vty_test_config_root.vty</span><br><span>@@ -163,7 +163,6 @@</span><br><span> tdef_vty_test(config)# timer test T2 100</span><br><span> </span><br><span> tdef_vty_test(config)# timer tes T2 100</span><br><span style="color: hsl(0, 100%, 40%);">-% Error: no timers found</span><br><span> </span><br><span> tdef_vty_test(config)# timer te T2 100</span><br><span> % Ambiguous command.</span><br><span>@@ -219,7 +218,6 @@</span><br><span> software: T3 = 480 m    Fix bugs (default: 480 m)</span><br><span> </span><br><span> tdef_vty_test(config)# timer softw T3 23</span><br><span style="color: hsl(0, 100%, 40%);">-% Error: no timers found</span><br><span> </span><br><span> tdef_vty_test(config)# timer</span><br><span> tea: T1 = 50 s Water Boiling Timeout (default: 50 s)</span><br><span>@@ -234,7 +232,7 @@</span><br><span> test: X23 = 239471 s     Negative T number (default: 239471 s)</span><br><span> software: T1 = 13 m    Write code (default: 30 m)</span><br><span> software: T2 = 0 ms       Hit segfault (default: 20 ms)</span><br><span style="color: hsl(0, 100%, 40%);">-software: T3 = 480 m       Fix bugs (default: 480 m)</span><br><span style="color: hsl(120, 100%, 40%);">+software: T3 = 23 m  Fix bugs (default: 480 m)</span><br><span> </span><br><span> tdef_vty_test(config)# do show timer</span><br><span> tea: T1 = 50 s Water Boiling Timeout (default: 50 s)</span><br><span>@@ -249,13 +247,14 @@</span><br><span> test: X23 = 239471 s   Negative T number (default: 239471 s)</span><br><span> software: T1 = 13 m    Write code (default: 30 m)</span><br><span> software: T2 = 0 ms       Hit segfault (default: 20 ms)</span><br><span style="color: hsl(0, 100%, 40%);">-software: T3 = 480 m       Fix bugs (default: 480 m)</span><br><span style="color: hsl(120, 100%, 40%);">+software: T3 = 23 m  Fix bugs (default: 480 m)</span><br><span> </span><br><span> tdef_vty_test(config)# show running-config</span><br><span> ... !timer</span><br><span> timer tea T3 32</span><br><span> timer software T1 13</span><br><span> timer software T2 0</span><br><span style="color: hsl(120, 100%, 40%);">+timer software T3 23</span><br><span> ... !timer</span><br><span> </span><br><span> tdef_vty_test(config)# timer tea T3 default</span><br><span>@@ -263,10 +262,12 @@</span><br><span> tdef_vty_test(config)# show running-config</span><br><span> ... !timer</span><br><span> timer software T2 0</span><br><span style="color: hsl(120, 100%, 40%);">+timer software T3 23</span><br><span> ... !timer</span><br><span> </span><br><span> tdef_vty_test(config)# timer softw 2 default</span><br><span style="color: hsl(0, 100%, 40%);">-% Error: no timers found</span><br><span> tdef_vty_test(config)# timer software 2 default</span><br><span> tdef_vty_test(config)# show running-config</span><br><span> ... !timer</span><br><span style="color: hsl(120, 100%, 40%);">+timer software T3 23</span><br><span style="color: hsl(120, 100%, 40%);">+... !timer</span><br><span>diff --git a/tests/vty/vty_transcript_test.vty b/tests/vty/vty_transcript_test.vty</span><br><span>index 1557744..f2dbacb 100644</span><br><span>--- a/tests/vty/vty_transcript_test.vty</span><br><span>+++ b/tests/vty/vty_transcript_test.vty</span><br><span>@@ -16,13 +16,13 @@</span><br><span> ok argc=1 two</span><br><span> </span><br><span> vty_transcript_test> multi0 o</span><br><span style="color: hsl(0, 100%, 40%);">-ok argc=1 o</span><br><span style="color: hsl(120, 100%, 40%);">+ok argc=1 one</span><br><span> </span><br><span> vty_transcript_test> multi0 t</span><br><span> % Ambiguous command.</span><br><span> </span><br><span> vty_transcript_test> multi0 th</span><br><span style="color: hsl(0, 100%, 40%);">-ok argc=1 th</span><br><span style="color: hsl(120, 100%, 40%);">+ok argc=1 three</span><br><span> </span><br><span> vty_transcript_test> multi0</span><br><span> % Command incomplete.</span><br><span>@@ -39,13 +39,13 @@</span><br><span> ok argc=1 two</span><br><span> </span><br><span> vty_transcript_test> multi1 o</span><br><span style="color: hsl(0, 100%, 40%);">-ok argc=1 o</span><br><span style="color: hsl(120, 100%, 40%);">+ok argc=1 one</span><br><span> </span><br><span> vty_transcript_test> multi1 t</span><br><span> % Ambiguous command.</span><br><span> </span><br><span> vty_transcript_test> multi1 th</span><br><span style="color: hsl(0, 100%, 40%);">-ok argc=1 th</span><br><span style="color: hsl(120, 100%, 40%);">+ok argc=1 three</span><br><span> </span><br><span> vty_transcript_test> multi1</span><br><span> ok argc=0</span><br><span>@@ -68,10 +68,10 @@</span><br><span> ok argc=0</span><br><span> </span><br><span> vty_transcript_test> multi0 thr</span><br><span style="color: hsl(0, 100%, 40%);">-ok argc=1 thr</span><br><span style="color: hsl(120, 100%, 40%);">+ok argc=1 three</span><br><span> </span><br><span> vty_transcript_test> multi1 on</span><br><span style="color: hsl(0, 100%, 40%);">-ok argc=1 on</span><br><span style="color: hsl(120, 100%, 40%);">+ok argc=1 one</span><br><span> </span><br><span> vty_transcript_test> multi2 t</span><br><span> % Ambiguous command.</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/14436">change 14436</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/14436"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I91b6621ac3d87fda5412a9b415e7bfb4736c8a9a </div>
<div style="display:none"> Gerrit-Change-Number: 14436 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>