[Asterisk-code-review] Modules: Additional improvements to CLI completion. (asterisk[master])

Corey Farrell asteriskteam at digium.com
Mon Oct 30 18:09:35 CDT 2017


Corey Farrell has uploaded this change for review. ( https://gerrit.asterisk.org/6942


Change subject: Modules: Additional improvements to CLI completion.
......................................................................

Modules: Additional improvements to CLI completion.

Replace 'needsreload' argument with a 'type' argument to specify which
type of modules you want completion.  This provides more accurate CLI
completion for load and unload commands.

* 'module unload' now excludes modules that are not running or have
  active references.
* 'module load' now includes modules that are loaded but not running.
* 'core set debug [atleast] <level> [module]' shows running modules only.

ASTERISK-27378

Change-Id: Iea3e00054461484196c46f688f02635cc886bad1
---
M include/asterisk/module.h
M main/cli.c
M main/loader.c
3 files changed, 96 insertions(+), 41 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/42/6942/1

diff --git a/include/asterisk/module.h b/include/asterisk/module.h
index e614a72..69ebb26 100644
--- a/include/asterisk/module.h
+++ b/include/asterisk/module.h
@@ -94,6 +94,20 @@
 	AST_MODULE_SUPPORT_DEPRECATED,
 };
 
+/*! Used to specify which modules should be returned by ast_module_helper. */
+enum ast_module_helper_type {
+	/*! Modules that are loaded by dlopen. */
+	AST_MODULE_HELPER_LOADED = 0,
+	/*! Running modules that include a reload callback. */
+	AST_MODULE_HELPER_RELOAD = 1,
+	/*! Modules that can be loaded or started. */
+	AST_MODULE_HELPER_LOAD,
+	/*! Modules that can be unloaded. */
+	AST_MODULE_HELPER_UNLOAD,
+	/*! Running modules */
+	AST_MODULE_HELPER_RUNNING,
+};
+
 /*! 
  * \brief Load a module.
  * \param resource_name The name of the module to load.
@@ -237,14 +251,12 @@
  * \param state The possible match to return.
  * \param rpos The position we should be matching.  This should be the same as
  *        pos.
- * \param needsreload This should be 1 if we need to reload this module and 0
- *        otherwise.  This function will only return modules that are reloadble
- *        if this is 1.
+ * \param type The type of action that will be performed by CLI.
  *
  * \retval A possible completion of the partial match.
  * \retval NULL if no matches were found.
  */
-char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload);
+char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type);
 
 /* Opaque type for module handles generated by the loader */
 
diff --git a/main/cli.c b/main/cli.c
index ef86e25..abd96eb 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -45,7 +45,6 @@
 #include <regex.h>
 #include <pwd.h>
 #include <grp.h>
-#include <editline/readline.h>
 
 #include "asterisk/cli.h"
 #include "asterisk/linkedlists.h"
@@ -224,28 +223,6 @@
 
 static AST_RWLIST_HEAD_STATIC(helpers, ast_cli_entry);
 
-static char *complete_fn(const char *word, int state)
-{
-	char *c, *d;
-	char filename[PATH_MAX];
-
-	if (word[0] == '/')
-		ast_copy_string(filename, word, sizeof(filename));
-	else
-		snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
-
-	c = d = filename_completion_function(filename, state);
-
-	if (c && word[0] != '/')
-		c += (strlen(ast_config_AST_MODULE_DIR) + 1);
-	if (c)
-		c = ast_strdup(c);
-
-	ast_std_free(d);
-
-	return c;
-}
-
 static char *handle_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	/* "module load <mod>" */
@@ -258,12 +235,14 @@
 		return NULL;
 
 	case CLI_GENERATE:
-		if (a->pos != e->args)
+		if (a->pos != e->args) {
 			return NULL;
-		return complete_fn(a->word, a->n);
+		}
+		return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOAD);
 	}
-	if (a->argc != e->args + 1)
+	if (a->argc != e->args + 1) {
 		return CLI_SHOWUSAGE;
+	}
 	if (ast_load_resource(a->argv[e->args])) {
 		ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]);
 		return CLI_FAILURE;
@@ -286,7 +265,7 @@
 		return NULL;
 
 	case CLI_GENERATE:
-		return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 1);
+		return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RELOAD);
 	}
 	if (a->argc == e->args) {
 		ast_module_reload(NULL);
@@ -482,7 +461,7 @@
 			}
 		} else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off") && strcasecmp(argv3, "channel"))
 			|| (a->pos == 5 && atleast)) {
-			return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
+			return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RUNNING);
 		}
 		return NULL;
 	}
@@ -733,7 +712,7 @@
 		return NULL;
 
 	case CLI_GENERATE:
-		return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
+		return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_UNLOAD);
 	}
 	if (a->argc < e->args + 1)
 		return CLI_SHOWUSAGE;
@@ -889,10 +868,11 @@
 		return NULL;
 
 	case CLI_GENERATE:
-		if (a->pos == e->args)
-			return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
-		else
+		if (a->pos == e->args) {
+			return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOADED);
+		} else {
 			return NULL;
+		}
 	}
 	/* all the above return, so we proceed with the handler.
 	 * we are guaranteed to have argc >= e->args
diff --git a/main/loader.c b/main/loader.c
index 8250f1f..eab5d36 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -36,6 +36,7 @@
 #include "asterisk/_private.h"
 #include "asterisk/paths.h"	/* use ast_config_AST_MODULE_DIR */
 #include <dirent.h>
+#include <editline/readline.h>
 
 #include "asterisk/dlinkedlists.h"
 #include "asterisk/module.h"
@@ -702,7 +703,59 @@
 	return res;
 }
 
-char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
+static char *complete_fn(const char *word, int state)
+{
+	char *c, *d;
+	char filename[PATH_MAX];
+
+	if (word[0] == '/') {
+		ast_copy_string(filename, word, sizeof(filename));
+	} else {
+		snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
+	}
+
+	c = d = filename_completion_function(filename, state);
+
+	if (c && word[0] != '/') {
+		c += (strlen(ast_config_AST_MODULE_DIR) + 1);
+	}
+	if (c) {
+		c = ast_strdup(c);
+	}
+
+	/* d was allocated by editline library */
+	ast_std_free(d);
+
+	return c;
+}
+
+static int module_matches_helper_type(struct ast_module *mod, enum ast_module_helper_type type)
+{
+	switch (type) {
+	case AST_MODULE_HELPER_LOAD:
+		return !mod->flags.running;
+
+	case AST_MODULE_HELPER_UNLOAD:
+		return !mod->usecount && mod->flags.running && !mod->flags.declined;
+
+	case AST_MODULE_HELPER_RELOAD:
+		return mod->flags.running && mod->info->reload;
+
+	case AST_MODULE_HELPER_RUNNING:
+		return mod->flags.running;
+
+	case AST_MODULE_HELPER_LOADED:
+		/* if we have a 'struct ast_module' then we're loaded. */
+		return 1;
+	}
+
+	/* Unknown ast_module_helper_type. Assume it doesn't match. */
+	ast_assert(0);
+
+	return 0;
+}
+
+char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type)
 {
 	struct ast_module *cur;
 	int i, which=0, l = strlen(word);
@@ -714,16 +767,22 @@
 
 	AST_DLLIST_LOCK(&module_list);
 	AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
-		if (!strncasecmp(word, cur->resource, l) &&
-		    (cur->info->reload || !needsreload) &&
-		    ++which > state) {
+		if (!module_matches_helper_type(cur, type)) {
+			continue;
+		}
+
+		if (strncasecmp(word, cur->resource, l)) {
+			continue;
+		}
+
+		if (++which > state) {
 			ret = ast_strdup(cur->resource);
 			break;
 		}
 	}
 	AST_DLLIST_UNLOCK(&module_list);
 
-	if (!ret && needsreload) {
+	if (!ret && type == AST_MODULE_HELPER_RELOAD) {
 		for (i=0; !ret && reload_classes[i].name; i++) {
 			if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) {
 				ret = ast_strdup(reload_classes[i].name);
@@ -731,6 +790,10 @@
 		}
 	}
 
+	if (!ret && type == AST_MODULE_HELPER_LOAD) {
+		ret = complete_fn(word, state);
+	}
+
 	return ret;
 }
 

-- 
To view, visit https://gerrit.asterisk.org/6942
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iea3e00054461484196c46f688f02635cc886bad1
Gerrit-Change-Number: 6942
Gerrit-PatchSet: 1
Gerrit-Owner: Corey Farrell <git at cfware.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20171030/e7b003c3/attachment-0001.html>


More information about the asterisk-code-review mailing list