#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"
#include "asterisk/app.h"
#include "asterisk/test.h"
#include "asterisk/sounds_index.h"
+#include "asterisk/cli.h"
#include <dlfcn.h>
}
}
-static char *module_load_helper(const char *word, int state)
+struct module_load_word {
+ const char *word;
+ size_t len;
+ size_t moddir_len;
+};
+
+static int module_load_helper_on_file(const char *dir_name, const char *filename, void *obj)
{
+ struct module_load_word *word = obj;
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;
+ char *filename_merged = NULL;
- AST_VECTOR_INIT(&running_modules, 200);
+ /* dir_name will never be shorter than word->moddir_len. */
+ dir_name += word->moddir_len;
+ if (!ast_strlen_zero(dir_name)) {
+ ast_assert(dir_name[0] == '/');
- AST_DLLIST_LOCK(&module_list);
- AST_DLLIST_TRAVERSE(&module_list, mod, entry) {
- if (mod->flags.running) {
- AST_VECTOR_APPEND(&running_modules, mod->resource);
+ dir_name += 1;
+ if (ast_asprintf(&filename_merged, "%s/%s", dir_name, filename) < 0) {
+ /* If we can't allocate the string just give up! */
+ return -1;
}
+ filename = filename_merged;
}
- 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);
+ if (!strncasecmp(filename, word->word, word->len)) {
+ /* Don't list files that are already loaded! */
+ mod = find_resource(filename, 0);
+ if (!mod || !mod->flags.running) {
+ ast_cli_completion_add(ast_strdup(filename));
+ }
}
- /*
- * 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);
- }
+ ast_free(filename_merged);
- /* Don't list files that are already loaded! */
- if (!AST_VECTOR_GET_CMP(&running_modules, name, !strcasecmp) && ++which > state) {
- ret = ast_strdup(name);
- }
+ return 0;
+}
- ast_std_free(editline_ret);
- }
+static void module_load_helper(const char *word)
+{
+ struct module_load_word word_l = {
+ .word = word,
+ .len = strlen(word),
+ .moddir_len = strlen(ast_config_AST_MODULE_DIR),
+ };
- /* Do not clean-up the elements, they belong to module_list. */
- AST_VECTOR_FREE(&running_modules);
+ AST_DLLIST_LOCK(&module_list);
+ ast_file_read_dirs(ast_config_AST_MODULE_DIR, module_load_helper_on_file, &word_l, -1);
AST_DLLIST_UNLOCK(&module_list);
-
- return ret;
}
char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int _type)
}
if (type == AST_MODULE_HELPER_LOAD) {
- return module_load_helper(word, state);
+ module_load_helper(word);
+
+ return NULL;
}
if (type == AST_MODULE_HELPER_RELOAD) {