summaryrefslogtreecommitdiff
path: root/main/loader.c
diff options
context:
space:
mode:
authorCorey Farrell <git@cfware.com>2017-10-30 18:30:18 -0400
committerCorey Farrell <git@cfware.com>2017-11-01 19:37:09 -0400
commitb9f457eac082da584d1167794ae91d60a71cc315 (patch)
tree35c8e841a4cdde34a561f70652af382ab55ecd3b /main/loader.c
parent64f1294ef2c799cda27ee83258fc5567a274bb34 (diff)
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 have active references or are not running. * 'module load' now excludes modules that are already running. * 'core set debug [atleast] <level> [module]' shows running modules only. ASTERISK-27378 Change-Id: Iea3e00054461484196c46f688f02635cc886bad1
Diffstat (limited to 'main/loader.c')
-rw-r--r--main/loader.c119
1 files changed, 103 insertions, 16 deletions
diff --git a/main/loader.c b/main/loader.c
index 8250f1ffb..add6a4209 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,35 +703,121 @@ int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode f
return res;
}
-char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
+static int module_matches_helper_type(struct ast_module *mod, enum ast_module_helper_type type)
{
- struct ast_module *cur;
- int i, which=0, l = strlen(word);
- char *ret = NULL;
+ switch (type) {
+ case AST_MODULE_HELPER_UNLOAD:
+ return !mod->usecount && mod->flags.running && !mod->flags.declined;
- if (pos != rpos) {
- return NULL;
+ 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;
+ default:
+ /* This function is not called for AST_MODULE_HELPER_LOAD. */
+ /* Unknown ast_module_helper_type. Assume it doesn't match. */
+ ast_assert(0);
+
+ return 0;
}
+}
+
+static char *module_load_helper(const char *word, int state)
+{
+ struct ast_module *mod;
+ int which = 0;
+ char *name;
+ char *ret = NULL;
+ char *editline_ret;
+ char fullpath[PATH_MAX];
+ int idx = 0;
+ /* This is needed to avoid listing modules that are already running. */
+ AST_VECTOR(, char *) running_modules;
+
+ AST_VECTOR_INIT(&running_modules, 200);
AST_DLLIST_LOCK(&module_list);
- AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
- if (!strncasecmp(word, cur->resource, l) &&
- (cur->info->reload || !needsreload) &&
- ++which > state) {
- ret = ast_strdup(cur->resource);
- break;
+ AST_DLLIST_TRAVERSE(&module_list, mod, entry) {
+ if (mod->flags.running) {
+ AST_VECTOR_APPEND(&running_modules, mod->resource);
}
}
+
+ if (word[0] == '/') {
+ /* BUGBUG: we should not support this. */
+ ast_copy_string(fullpath, word, sizeof(fullpath));
+ } else {
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", ast_config_AST_MODULE_DIR, word);
+ }
+
+ /*
+ * This is ugly that we keep calling filename_completion_function.
+ * The only way to avoid this would be to make a copy of the function
+ * that skips matches found in the running_modules vector.
+ */
+ while (!ret && (name = editline_ret = filename_completion_function(fullpath, idx++))) {
+ if (word[0] != '/') {
+ name += (strlen(ast_config_AST_MODULE_DIR) + 1);
+ }
+
+ /* Don't list files that are already loaded! */
+ if (!AST_VECTOR_GET_CMP(&running_modules, name, !strcasecmp) && ++which > state) {
+ ret = ast_strdup(name);
+ }
+
+ ast_std_free(editline_ret);
+ }
+
+ /* Do not clean-up the elements, they belong to module_list. */
+ AST_VECTOR_FREE(&running_modules);
AST_DLLIST_UNLOCK(&module_list);
- if (!ret && needsreload) {
- 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);
+ return ret;
+}
+
+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 *mod;
+ int which = 0;
+ int wordlen = strlen(word);
+ char *ret = NULL;
+
+ if (pos != rpos) {
+ return NULL;
+ }
+
+ if (type == AST_MODULE_HELPER_LOAD) {
+ return module_load_helper(word, state);
+ }
+
+ if (type == AST_MODULE_HELPER_RELOAD) {
+ int idx;
+
+ for (idx = 0; reload_classes[idx].name; idx++) {
+ if (!strncasecmp(word, reload_classes[idx].name, wordlen) && ++which > state) {
+ return ast_strdup(reload_classes[idx].name);
}
}
}
+ AST_DLLIST_LOCK(&module_list);
+ AST_DLLIST_TRAVERSE(&module_list, mod, entry) {
+ if (!module_matches_helper_type(mod, type)) {
+ continue;
+ }
+
+ if (!strncasecmp(word, mod->resource, wordlen) && ++which > state) {
+ ret = ast_strdup(mod->resource);
+ break;
+ }
+ }
+ AST_DLLIST_UNLOCK(&module_list);
+
return ret;
}