<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/6942">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Modules: Additional improvements to CLI completion.<br><br>Replace 'needsreload' argument with a 'type' argument to specify which<br>type of modules you want completion.  This provides more accurate CLI<br>completion for load and unload commands.<br><br>* 'module unload' now excludes modules that are not running or have<br>  active references.<br>* 'module load' now includes modules that are loaded but not running.<br>* 'core set debug [atleast] <level> [module]' shows running modules only.<br><br>ASTERISK-27378<br><br>Change-Id: Iea3e00054461484196c46f688f02635cc886bad1<br>---<br>M include/asterisk/module.h<br>M main/cli.c<br>M main/loader.c<br>3 files changed, 96 insertions(+), 41 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/42/6942/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/module.h b/include/asterisk/module.h<br>index e614a72..69ebb26 100644<br>--- a/include/asterisk/module.h<br>+++ b/include/asterisk/module.h<br>@@ -94,6 +94,20 @@<br>  AST_MODULE_SUPPORT_DEPRECATED,<br> };<br> <br>+/*! Used to specify which modules should be returned by ast_module_helper. */<br>+enum ast_module_helper_type {<br>+       /*! Modules that are loaded by dlopen. */<br>+    AST_MODULE_HELPER_LOADED = 0,<br>+        /*! Running modules that include a reload callback. */<br>+       AST_MODULE_HELPER_RELOAD = 1,<br>+        /*! Modules that can be loaded or started. */<br>+        AST_MODULE_HELPER_LOAD,<br>+      /*! Modules that can be unloaded. */<br>+ AST_MODULE_HELPER_UNLOAD,<br>+    /*! Running modules */<br>+       AST_MODULE_HELPER_RUNNING,<br>+};<br>+<br> /*! <br>  * \brief Load a module.<br>  * \param resource_name The name of the module to load.<br>@@ -237,14 +251,12 @@<br>  * \param state The possible match to return.<br>  * \param rpos The position we should be matching.  This should be the same as<br>  *        pos.<br>- * \param needsreload This should be 1 if we need to reload this module and 0<br>- *        otherwise.  This function will only return modules that are reloadble<br>- *        if this is 1.<br>+ * \param type The type of action that will be performed by CLI.<br>  *<br>  * \retval A possible completion of the partial match.<br>  * \retval NULL if no matches were found.<br>  */<br>-char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload);<br>+char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type);<br> <br> /* Opaque type for module handles generated by the loader */<br> <br>diff --git a/main/cli.c b/main/cli.c<br>index ef86e25..abd96eb 100644<br>--- a/main/cli.c<br>+++ b/main/cli.c<br>@@ -45,7 +45,6 @@<br> #include <regex.h><br> #include <pwd.h><br> #include <grp.h><br>-#include <editline/readline.h><br> <br> #include "asterisk/cli.h"<br> #include "asterisk/linkedlists.h"<br>@@ -224,28 +223,6 @@<br> <br> static AST_RWLIST_HEAD_STATIC(helpers, ast_cli_entry);<br> <br>-static char *complete_fn(const char *word, int state)<br>-{<br>-     char *c, *d;<br>- char filename[PATH_MAX];<br>-<br>-  if (word[0] == '/')<br>-          ast_copy_string(filename, word, sizeof(filename));<br>-   else<br>-         snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);<br>-<br>- c = d = filename_completion_function(filename, state);<br>-<br>-    if (c && word[0] != '/')<br>-             c += (strlen(ast_config_AST_MODULE_DIR) + 1);<br>-        if (c)<br>-               c = ast_strdup(c);<br>-<br>-        ast_std_free(d);<br>-<br>-  return c;<br>-}<br>-<br> static char *handle_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)<br> {<br>     /* "module load <mod>" */<br>@@ -258,12 +235,14 @@<br>              return NULL;<br> <br>       case CLI_GENERATE:<br>-           if (a->pos != e->args)<br>+         if (a->pos != e->args) {<br>                        return NULL;<br>-         return complete_fn(a->word, a->n);<br>+             }<br>+            return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOAD);<br>      }<br>-    if (a->argc != e->args + 1)<br>+    if (a->argc != e->args + 1) {<br>           return CLI_SHOWUSAGE;<br>+        }<br>     if (ast_load_resource(a->argv[e->args])) {<br>              ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]);<br>            return CLI_FAILURE;<br>@@ -286,7 +265,7 @@<br>              return NULL;<br> <br>       case CLI_GENERATE:<br>-           return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 1);<br>+          return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RELOAD);<br>    }<br>     if (a->argc == e->args) {<br>               ast_module_reload(NULL);<br>@@ -482,7 +461,7 @@<br>                         }<br>             } else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off") && strcasecmp(argv3, "channel"))<br>                       || (a->pos == 5 && atleast)) {<br>-                    return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);<br>+                  return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RUNNING);<br>           }<br>             return NULL;<br>  }<br>@@ -733,7 +712,7 @@<br>                return NULL;<br> <br>       case CLI_GENERATE:<br>-           return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);<br>+          return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_UNLOAD);<br>    }<br>     if (a->argc < e->args + 1)<br>           return CLI_SHOWUSAGE;<br>@@ -889,10 +868,11 @@<br>          return NULL;<br> <br>       case CLI_GENERATE:<br>-           if (a->pos == e->args)<br>-                 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);<br>-          else<br>+         if (a->pos == e->args) {<br>+                       return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOADED);<br>+           } else {<br>                      return NULL;<br>+         }<br>     }<br>     /* all the above return, so we proceed with the handler.<br>       * we are guaranteed to have argc >= e->args<br>diff --git a/main/loader.c b/main/loader.c<br>index 8250f1f..eab5d36 100644<br>--- a/main/loader.c<br>+++ b/main/loader.c<br>@@ -36,6 +36,7 @@<br> #include "asterisk/_private.h"<br> #include "asterisk/paths.h"   /* use ast_config_AST_MODULE_DIR */<br> #include <dirent.h><br>+#include <editline/readline.h><br> <br> #include "asterisk/dlinkedlists.h"<br> #include "asterisk/module.h"<br>@@ -702,7 +703,59 @@<br>       return res;<br> }<br> <br>-char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)<br>+static char *complete_fn(const char *word, int state)<br>+{<br>+  char *c, *d;<br>+ char filename[PATH_MAX];<br>+<br>+  if (word[0] == '/') {<br>+                ast_copy_string(filename, word, sizeof(filename));<br>+   } else {<br>+             snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);<br>+    }<br>+<br>+ c = d = filename_completion_function(filename, state);<br>+<br>+    if (c && word[0] != '/') {<br>+           c += (strlen(ast_config_AST_MODULE_DIR) + 1);<br>+        }<br>+    if (c) {<br>+             c = ast_strdup(c);<br>+   }<br>+<br>+ /* d was allocated by editline library */<br>+    ast_std_free(d);<br>+<br>+  return c;<br>+}<br>+<br>+static int module_matches_helper_type(struct ast_module *mod, enum ast_module_helper_type type)<br>+{<br>+       switch (type) {<br>+      case AST_MODULE_HELPER_LOAD:<br>+         return !mod->flags.running;<br>+<br>+    case AST_MODULE_HELPER_UNLOAD:<br>+               return !mod->usecount && mod->flags.running && !mod->flags.declined;<br>+<br>+     case AST_MODULE_HELPER_RELOAD:<br>+               return mod->flags.running && mod->info->reload;<br>+<br>+  case AST_MODULE_HELPER_RUNNING:<br>+              return mod->flags.running;<br>+<br>+     case AST_MODULE_HELPER_LOADED:<br>+               /* if we have a 'struct ast_module' then we're loaded. */<br>+                return 1;<br>+    }<br>+<br>+ /* Unknown ast_module_helper_type. Assume it doesn't match. */<br>+   ast_assert(0);<br>+<br>+    return 0;<br>+}<br>+<br>+char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type)<br> {<br>    struct ast_module *cur;<br>       int i, which=0, l = strlen(word);<br>@@ -714,16 +767,22 @@<br> <br>   AST_DLLIST_LOCK(&module_list);<br>    AST_DLLIST_TRAVERSE(&module_list, cur, entry) {<br>-          if (!strncasecmp(word, cur->resource, l) &&<br>-                   (cur->info->reload || !needsreload) &&<br>-                 ++which > state) {<br>+            if (!module_matches_helper_type(cur, type)) {<br>+                        continue;<br>+            }<br>+<br>+         if (strncasecmp(word, cur->resource, l)) {<br>+                        continue;<br>+            }<br>+<br>+         if (++which > state) {<br>                     ret = ast_strdup(cur->resource);<br>                   break;<br>                }<br>     }<br>     AST_DLLIST_UNLOCK(&module_list);<br> <br>-      if (!ret && needsreload) {<br>+   if (!ret && type == AST_MODULE_HELPER_RELOAD) {<br>               for (i=0; !ret && reload_classes[i].name; i++) {<br>                      if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) {<br>                            ret = ast_strdup(reload_classes[i].name);<br>@@ -731,6 +790,10 @@<br>               }<br>     }<br> <br>+ if (!ret && type == AST_MODULE_HELPER_LOAD) {<br>+                ret = complete_fn(word, state);<br>+      }<br>+<br>  return ret;<br> }<br> <br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/6942">change 6942</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/6942"/><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: Iea3e00054461484196c46f688f02635cc886bad1 </div>
<div style="display:none"> Gerrit-Change-Number: 6942 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>