diff options
Diffstat (limited to 'main/cli.c')
-rw-r--r-- | main/cli.c | 101 |
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; } |