summaryrefslogtreecommitdiff
path: root/main/cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/cli.c')
-rw-r--r--main/cli.c101
1 files changed, 53 insertions, 48 deletions
diff --git a/main/cli.c b/main/cli.c
index eae14adc4..75846b8c9 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -1336,33 +1336,6 @@ static char *handle_commandmatchesarray(struct ast_cli_entry *e, int cmd, struct
}
-
-static char *handle_commandnummatches(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
- int matches = 0;
-
- switch (cmd) {
- case CLI_INIT:
- e->command = "_command nummatches";
- e->usage =
- "Usage: _command nummatches \"<line>\" text \n"
- " This function is used internally to help with command completion and should.\n"
- " never be called by the user directly.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
- if (a->argc != 4)
- return CLI_SHOWUSAGE;
-
- matches = ast_cli_generatornummatches(a->argv[2], a->argv[3]);
-
- ast_cli(a->fd, "%d", matches);
-
- return CLI_SUCCESS;
-}
-
struct channel_set_debug_args {
int fd;
int is_off;
@@ -1794,7 +1767,6 @@ static char *handle_cli_wait_fullybooted(struct ast_cli_entry *e, int cmd, struc
static char *handle_help(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static struct ast_cli_entry cli_cli[] = {
- AST_CLI_DEFINE(handle_commandnummatches, "Returns number of command matches"),
AST_CLI_DEFINE(handle_commandmatchesarray, "Returns command matches array"),
AST_CLI_DEFINE(handle_nodebugchan_deprecated, "Disable debugging on channel(s)"),
@@ -2472,24 +2444,6 @@ static char *parse_args(const char *s, int *argc, const char *argv[], int max, i
return duplicate;
}
-/*! \brief Return the number of unique matches for the generator */
-int ast_cli_generatornummatches(const char *text, const char *word)
-{
- int matches = 0, i = 0;
- char *buf = NULL, *oldbuf = NULL;
-
- while ((buf = ast_cli_generator(text, word, i++))) {
- if (!oldbuf || strcmp(buf,oldbuf))
- matches++;
- if (oldbuf)
- ast_free(oldbuf);
- oldbuf = buf;
- }
- if (oldbuf)
- ast_free(oldbuf);
- return matches;
-}
-
char **ast_cli_completion_matches(const char *text, const char *word)
{
struct ast_vector_string *vec = ast_cli_completion_vector(text, word);
@@ -2513,6 +2467,44 @@ char **ast_cli_completion_matches(const char *text, const char *word)
return match_list;
}
+AST_THREADSTORAGE_RAW(completion_storage);
+
+/*!
+ * \internal
+ * \brief Add a value to the vector.
+ *
+ * \param vec Vector to add \a value to. Must be from threadstorage.
+ * \param value The value to add.
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+static int cli_completion_vector_add(struct ast_vector_string *vec, char *value)
+{
+ if (!value) {
+ return 0;
+ }
+
+ if (!vec || AST_VECTOR_ADD_SORTED(vec, value, strcasecmp)) {
+ if (vec) {
+ ast_threadstorage_set_ptr(&completion_storage, NULL);
+
+ AST_VECTOR_CALLBACK_VOID(vec, ast_free);
+ AST_VECTOR_FREE(vec);
+ }
+ ast_free(value);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int ast_cli_completion_add(char *value)
+{
+ return cli_completion_vector_add(ast_threadstorage_get_ptr(&completion_storage), value);
+}
+
struct ast_vector_string *ast_cli_completion_vector(const char *text, const char *word)
{
char *retstr, *prevstr;
@@ -2520,13 +2512,23 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char
size_t which = 0;
struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
+ /* Recursion into this function is a coding error. */
+ ast_assert(!ast_threadstorage_get_ptr(&completion_storage));
+
if (!vec) {
return NULL;
}
+ if (ast_threadstorage_set_ptr(&completion_storage, vec)) {
+ ast_log(LOG_ERROR, "Failed to initialize threadstorage for completion.\n");
+ ast_free(vec);
+
+ return NULL;
+ }
+
while ((retstr = ast_cli_generator(text, word, which)) != NULL) {
- if (AST_VECTOR_ADD_SORTED(vec, retstr, strcasecmp)) {
- ast_free(retstr);
+ if (cli_completion_vector_add(vec, retstr)) {
+ ast_threadstorage_set_ptr(&completion_storage, NULL);
goto vector_cleanup;
}
@@ -2534,6 +2536,8 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char
++which;
}
+ ast_threadstorage_set_ptr(&completion_storage, NULL);
+
if (!AST_VECTOR_SIZE(vec)) {
AST_VECTOR_PTR_FREE(vec);
@@ -2572,6 +2576,7 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char
retstr = ast_strndup(AST_VECTOR_GET(vec, 0), max_equal);
if (!retstr || AST_VECTOR_INSERT_AT(vec, 0, retstr)) {
ast_free(retstr);
+
goto vector_cleanup;
}