<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/7268">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">CLI: Refactor cli_complete.<br><br>* Stop using "_COMMAND NUMMATCHES" on remote consoles.  Using this<br>  command had doubled the amount of work needed from the Asterisk<br>  daemon for each completion request.<br>* Fix code formatting.<br>* Remove static buffer used to send the command, use the same buffer<br>  that will receive the results.<br>* Move sort from ast_cli_display_match_list.<br><br>Change-Id: Ie2211b519a3d4bec45bf46e0095bdd01d384cb69<br>---<br>M main/asterisk.c<br>1 file changed, 76 insertions(+), 66 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/68/7268/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/main/asterisk.c b/main/asterisk.c<br>index 46dc9a7..1ee6aa4 100644<br>--- a/main/asterisk.c<br>+++ b/main/asterisk.c<br>@@ -3054,7 +3054,7 @@<br>   return strcasecmp(s1, s2);<br> }<br> <br>-static void ast_cli_display_match_list(char **matches, int len, int max)<br>+static void ast_cli_display_match_list(char **matches, int max)<br> {<br>    int idx = 1;<br>  /* find out how many entries can be put on one line, with two spaces between strings */<br>@@ -3063,8 +3063,6 @@<br>        if (limit == 0) {<br>             limit = 1;<br>    }<br>-<br>- qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);<br> <br>        for (;;) {<br>            int numoutputline;<br>@@ -3095,7 +3093,7 @@<br>     int nummatches = 0;<br>   char **matches;<br>       int retval = CC_ERROR;<br>-       char buf[2048], savechr;<br>+     char savechr;<br>         int res;<br> <br>   LineInfo *lf = (LineInfo *)el_line(editline);<br>@@ -3116,65 +3114,80 @@<br>        len = lf->cursor - ptr;<br> <br>         if (ast_opt_remote) {<br>-                snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);<br>-           fdsend(ast_consock, buf);<br>-            if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) {<br>-                        return (char*)(CC_ERROR);<br>-            }<br>-            buf[res] = '\0';<br>-             nummatches = atoi(buf);<br>+              static const char * const cmd_matches_fmt = "_COMMAND MATCHESARRAY \"%s\" \"%s\"";<br>+             char *mbuf;<br>+          char *new_mbuf;<br>+              int mlen = 0, maxmbuf = 2048;<br> <br>-             if (nummatches > 0) {<br>-                     char *mbuf;<br>-                  char *new_mbuf;<br>-                      int mlen = 0, maxmbuf = 2048;<br>+                /* Start with a 2048 byte buffer */<br>+          mbuf = ast_malloc(maxmbuf);<br> <br>-                       /* Start with a 2048 byte buffer */<br>-                  if (!(mbuf = ast_malloc(maxmbuf))) {<br>-                         *((char *) lf->cursor) = savechr;<br>-                         return (char *)(CC_ERROR);<br>-                   }<br>-                    snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);<br>-                 fdsend(ast_consock, buf);<br>-                    res = 0;<br>-                     mbuf[0] = '\0';<br>-                      while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {<br>-                           if (mlen + 1024 > maxmbuf) {<br>-                                      /* Every step increment buffer 1024 bytes */<br>-                                 maxmbuf += 1024;<br>-                                     new_mbuf = ast_realloc(mbuf, maxmbuf);<br>-                                       if (!new_mbuf) {<br>-                                             ast_free(mbuf);<br>-                                              *((char *) lf->cursor) = savechr;<br>-                                         return (char *)(CC_ERROR);<br>-                                   }<br>-                                    mbuf = new_mbuf;<br>-                             }<br>-                            /* Only read 1024 bytes at a time */<br>-                         res = read(ast_consock, mbuf + mlen, 1024);<br>-                          if (res > 0)<br>-                                      mlen += res;<br>-                 }<br>-                    mbuf[mlen] = '\0';<br>-<br>-                        matches = ast_el_strtoarr(mbuf);<br>+             /* This will run snprintf twice at most. */<br>+          while (mbuf && (mlen = snprintf(mbuf, maxmbuf, cmd_matches_fmt, lf->buffer, ptr)) > maxmbuf) {<br>+                 /* Return value does not include space for NULL terminator. */<br>+                       maxmbuf = mlen + 1;<br>                   ast_free(mbuf);<br>-              } else<br>-                       matches = (char **) NULL;<br>-    } else {<br>-             char **p, *oldbuf=NULL;<br>-              nummatches = 0;<br>-              matches = ast_cli_completion_matches((char *)lf->buffer,ptr);<br>-             for (p = matches; p && *p; p++) {<br>-                    if (!oldbuf || strcmp(*p,oldbuf))<br>-                            nummatches++;<br>-                        oldbuf = *p;<br>+                 mbuf = ast_malloc(maxmbuf);<br>           }<br>+<br>+         if (!mbuf) {<br>+                 *((char *) lf->cursor) = savechr;<br>+<br>+                      return (char *)(CC_ERROR);<br>+           }<br>+<br>+         fdsend(ast_consock, mbuf);<br>+           res = 0;<br>+             mlen = 0;<br>+            mbuf[0] = '\0';<br>+<br>+           while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {<br>+                   if (mlen + 1024 > maxmbuf) {<br>+                              /* Expand buffer to the next 1024 byte increment. */<br>+                         maxmbuf = mlen + 1024;<br>+                               new_mbuf = ast_realloc(mbuf, maxmbuf);<br>+                               if (!new_mbuf) {<br>+                                     ast_free(mbuf);<br>+                                      *((char *) lf->cursor) = savechr;<br>+<br>+                                      return (char *)(CC_ERROR);<br>+                           }<br>+                            mbuf = new_mbuf;<br>+                     }<br>+                    /* Only read 1024 bytes at a time */<br>+                 res = read(ast_consock, mbuf + mlen, 1024);<br>+                  if (res > 0) {<br>+                            mlen += res;<br>+                 }<br>+            }<br>+            mbuf[mlen] = '\0';<br>+<br>+                matches = ast_el_strtoarr(mbuf);<br>+             ast_free(mbuf);<br>+      } else {<br>+             matches = ast_cli_completion_matches((char *)lf->buffer,ptr);<br>      }<br> <br>  if (matches) {<br>                int i;<br>-               int matches_num, maxlen, match_len;<br>+          int maxlen, match_len;<br>+<br>+            while (matches[nummatches + 1]) {<br>+                    nummatches++;<br>+                }<br>+<br>+         if (nummatches > 1) {<br>+                     qsort(&matches[0], (size_t)(nummatches), sizeof(char *), ast_el_sort_compare);<br>+                   nummatches = 1;<br>+                      i = 1;<br>+                       while (matches[i + 1]) {<br>+                             if (strcasecmp(matches[i], matches[i + 1])) {<br>+                                        /* don't count duplicates. */<br>+                                    nummatches++;<br>+                                }<br>+                            i++;<br>+                 }<br>+            }<br> <br>          if (matches[0][0] != '\0') {<br>                  el_deletestr(editline, (int) len);<br>@@ -3190,21 +3203,18 @@<br>                   /* Must be more than one match */<br>                     for (i = 1, maxlen = 0; matches[i]; i++) {<br>                            match_len = strlen(matches[i]);<br>-                              if (match_len > maxlen)<br>+                           if (match_len > maxlen) {<br>                                  maxlen = match_len;<br>+                          }<br>                     }<br>-                    matches_num = i - 1;<br>-                 if (matches_num >1) {<br>-                             fprintf(stdout, "\n");<br>-                             ast_cli_display_match_list(matches, nummatches, maxlen);<br>-                             retval = CC_REDISPLAY;<br>-                       } else {<br>-                             el_insertstr(editline," ");<br>-                                retval = CC_REFRESH;<br>-                 }<br>+<br>+                 fprintf(stdout, "\n");<br>+                     ast_cli_display_match_list(matches, maxlen);<br>+                 retval = CC_REDISPLAY;<br>                }<br>-            for (i = 0; matches[i]; i++)<br>+         for (i = 0; matches[i]; i++) {<br>                        ast_free(matches[i]);<br>+                }<br>             ast_free(matches);<br>    }<br> <br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7268">change 7268</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.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.asterisk.org/7268"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ie2211b519a3d4bec45bf46e0095bdd01d384cb69 </div>
<div style="display:none"> Gerrit-Change-Number: 7268 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>