diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/asterisk.c | 254 | ||||
-rw-r--r-- | main/cli.c | 101 | ||||
-rw-r--r-- | main/translate.c | 29 |
3 files changed, 174 insertions, 210 deletions
diff --git a/main/asterisk.c b/main/asterisk.c index 77046f272..dd66867b8 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -3001,121 +3001,64 @@ static char *cli_prompt(EditLine *editline) return ast_str_buffer(prompt); } -static void destroy_match_list(char **match_list, int matches) +static struct ast_vector_string *ast_el_strtoarr(char *buf) { - if (match_list) { - int idx; + char *retstr; + struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec)); - for (idx = 0; idx < matches; ++idx) { - ast_free(match_list[idx]); - } - ast_free(match_list); + if (!vec) { + return NULL; } -} - -static char **ast_el_strtoarr(char *buf) -{ - char *retstr; - char **match_list = NULL; - char **new_list; - size_t match_list_len = 1; - int matches = 0; while ((retstr = strsep(&buf, " "))) { if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) { break; } - if (matches + 1 >= match_list_len) { - match_list_len <<= 1; - new_list = ast_realloc(match_list, match_list_len * sizeof(char *)); - if (!new_list) { - destroy_match_list(match_list, matches); - return NULL; - } - match_list = new_list; - } retstr = ast_strdup(retstr); - if (!retstr) { - destroy_match_list(match_list, matches); - return NULL; + if (!retstr || AST_VECTOR_APPEND(vec, retstr)) { + ast_free(retstr); + goto vector_cleanup; } - match_list[matches++] = retstr; } - if (!match_list) { - return NULL; - } - - if (matches >= match_list_len) { - new_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)); - if (!new_list) { - destroy_match_list(match_list, matches); - return NULL; - } - match_list = new_list; + if (!AST_VECTOR_SIZE(vec)) { + goto vector_cleanup; } - match_list[matches] = NULL; - - return match_list; -} + return vec; -static int ast_el_sort_compare(const void *i1, const void *i2) -{ - char *s1, *s2; +vector_cleanup: + AST_VECTOR_CALLBACK_VOID(vec, ast_free); + AST_VECTOR_PTR_FREE(vec); - s1 = ((char **)i1)[0]; - s2 = ((char **)i2)[0]; - - return strcasecmp(s1, s2); + return NULL; } -static int ast_cli_display_match_list(char **matches, int len, int max) +static void ast_cli_display_match_list(struct ast_vector_string *matches, int max) { - int i, idx, limit, count; - int screenwidth = 0; - int numoutput = 0, numoutputline = 0; - - screenwidth = ast_get_termcols(STDOUT_FILENO); - + int idx = 1; /* find out how many entries can be put on one line, with two spaces between strings */ - limit = screenwidth / (max + 2); - if (limit == 0) - limit = 1; - - /* how many lines of output */ - count = len / limit; - if (count * limit < len) - count++; + int limit = ast_get_termcols(STDOUT_FILENO) / (max + 2); - idx = 1; - - qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare); - - for (; count > 0; count--) { - numoutputline = 0; - for (i = 0; i < limit && matches[idx]; i++, idx++) { + if (limit == 0) { + limit = 1; + } - /* Don't print dupes */ - if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) { - i--; - ast_free(matches[idx]); - matches[idx] = NULL; - continue; - } + for (;;) { + int numoutputline; - numoutput++; + for (numoutputline = 0; numoutputline < limit && idx < AST_VECTOR_SIZE(matches); idx++) { numoutputline++; - fprintf(stdout, "%-*s ", max, matches[idx]); - ast_free(matches[idx]); - matches[idx] = NULL; + fprintf(stdout, "%-*s ", max, AST_VECTOR_GET(matches, idx)); + } + + if (!numoutputline) { + break; } - if (numoutputline > 0) - fprintf(stdout, "\n"); - } - return numoutput; + fprintf(stdout, "\n"); + } } @@ -3123,10 +3066,9 @@ static char *cli_complete(EditLine *editline, int ch) { int len = 0; char *ptr; - int nummatches = 0; - char **matches; + struct ast_vector_string *matches; int retval = CC_ERROR; - char buf[2048], savechr; + char savechr; int res; LineInfo *lf = (LineInfo *)el_line(editline); @@ -3147,96 +3089,90 @@ static char *cli_complete(EditLine *editline, int ch) len = lf->cursor - ptr; if (ast_opt_remote) { - snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr); - fdsend(ast_consock, buf); - if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) { - return (char*)(CC_ERROR); +#define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\"" + char *mbuf; + char *new_mbuf; + int mlen = 0, maxmbuf = 2048; + + /* Start with a 2048 byte buffer */ + mbuf = ast_malloc(maxmbuf); + + /* This will run snprintf twice at most. */ + while (mbuf && (mlen = snprintf(mbuf, maxmbuf, CMD_MATCHESARRAY, lf->buffer, ptr)) > maxmbuf) { + /* Return value does not include space for NULL terminator. */ + maxmbuf = mlen + 1; + ast_free(mbuf); + mbuf = ast_malloc(maxmbuf); } - buf[res] = '\0'; - nummatches = atoi(buf); - - if (nummatches > 0) { - char *mbuf; - char *new_mbuf; - int mlen = 0, maxmbuf = 2048; - - /* Start with a 2048 byte buffer */ - if (!(mbuf = ast_malloc(maxmbuf))) { - *((char *) lf->cursor) = savechr; - return (char *)(CC_ERROR); - } - snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr); - fdsend(ast_consock, buf); - res = 0; - mbuf[0] = '\0'; - while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) { - if (mlen + 1024 > maxmbuf) { - /* Every step increment buffer 1024 bytes */ - maxmbuf += 1024; - new_mbuf = ast_realloc(mbuf, maxmbuf); - if (!new_mbuf) { - ast_free(mbuf); - *((char *) lf->cursor) = savechr; - return (char *)(CC_ERROR); - } - mbuf = new_mbuf; + + if (!mbuf) { + *((char *) lf->cursor) = savechr; + + return (char *)(CC_ERROR); + } + + fdsend(ast_consock, mbuf); + res = 0; + mlen = 0; + mbuf[0] = '\0'; + + while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) { + if (mlen + 1024 > maxmbuf) { + /* Expand buffer to the next 1024 byte increment. */ + maxmbuf = mlen + 1024; + new_mbuf = ast_realloc(mbuf, maxmbuf); + if (!new_mbuf) { + ast_free(mbuf); + *((char *) lf->cursor) = savechr; + + return (char *)(CC_ERROR); } - /* Only read 1024 bytes at a time */ - res = read(ast_consock, mbuf + mlen, 1024); - if (res > 0) - mlen += res; + mbuf = new_mbuf; } - mbuf[mlen] = '\0'; + /* Only read 1024 bytes at a time */ + res = read(ast_consock, mbuf + mlen, 1024); + if (res > 0) { + mlen += res; + } + } + mbuf[mlen] = '\0'; - matches = ast_el_strtoarr(mbuf); - ast_free(mbuf); - } else - matches = (char **) NULL; + matches = ast_el_strtoarr(mbuf); + ast_free(mbuf); } else { - char **p, *oldbuf=NULL; - nummatches = 0; - matches = ast_cli_completion_matches((char *)lf->buffer,ptr); - for (p = matches; p && *p; p++) { - if (!oldbuf || strcmp(*p,oldbuf)) - nummatches++; - oldbuf = *p; - } + matches = ast_cli_completion_vector((char *)lf->buffer, ptr); } if (matches) { int i; - int matches_num, maxlen, match_len; + int maxlen, match_len; + const char *best_match = AST_VECTOR_GET(matches, 0); - if (matches[0][0] != '\0') { + if (!ast_strlen_zero(best_match)) { el_deletestr(editline, (int) len); - el_insertstr(editline, matches[0]); + el_insertstr(editline, best_match); retval = CC_REFRESH; } - if (nummatches == 1) { + if (AST_VECTOR_SIZE(matches) == 2) { /* Found an exact match */ el_insertstr(editline, " "); retval = CC_REFRESH; } else { /* Must be more than one match */ - for (i = 1, maxlen = 0; matches[i]; i++) { - match_len = strlen(matches[i]); - if (match_len > maxlen) + for (i = 1, maxlen = 0; i < AST_VECTOR_SIZE(matches); i++) { + match_len = strlen(AST_VECTOR_GET(matches, i)); + if (match_len > maxlen) { maxlen = match_len; + } } - matches_num = i - 1; - if (matches_num >1) { - fprintf(stdout, "\n"); - ast_cli_display_match_list(matches, nummatches, maxlen); - retval = CC_REDISPLAY; - } else { - el_insertstr(editline," "); - retval = CC_REFRESH; - } + + fprintf(stdout, "\n"); + ast_cli_display_match_list(matches, maxlen); + retval = CC_REDISPLAY; } - for (i = 0; matches[i]; i++) - ast_free(matches[i]); - ast_free(matches); + AST_VECTOR_CALLBACK_VOID(matches, ast_free); + AST_VECTOR_PTR_FREE(matches); } *((char *) lf->cursor) = savechr; 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; } diff --git a/main/translate.c b/main/translate.c index 92c0cb9ea..70e97f955 100644 --- a/main/translate.c +++ b/main/translate.c @@ -946,7 +946,8 @@ static void handle_cli_recalc(struct ast_cli_args *a) static char *handle_show_translation_table(struct ast_cli_args *a) { int x, y, i, k; - int longest = 0, num_codecs = 0, curlen = 0; + int longest = 7; /* slin192 */ + int num_codecs = 0, curlen = 0; struct ast_str *out = ast_str_create(1024); struct ast_codec *codec; @@ -983,6 +984,7 @@ static char *handle_show_translation_table(struct ast_cli_args *a) ast_str_set(&out, 0, " "); for (k = 0; k < num_codecs; k++) { + int adjust = 0; struct ast_codec *col = k ? ast_codec_get_by_id(k) : NULL; y = -1; @@ -998,6 +1000,12 @@ static char *handle_show_translation_table(struct ast_cli_args *a) if (k > 0) { curlen = strlen(col->name); + if (!strcmp(col->name, "slin") || + !strcmp(col->name, "speex") || + !strcmp(col->name, "silk")) { + adjust = log10(col->sample_rate / 1000) + 1; + curlen = curlen + adjust; + } } if (curlen < 5) { @@ -1009,10 +1017,25 @@ static char *handle_show_translation_table(struct ast_cli_args *a) ast_str_append(&out, 0, "%*u", curlen + 1, (matrix_get(x, y)->table_cost/100)); } else if (i == 0 && k > 0) { /* Top row - use a dynamic size */ - ast_str_append(&out, 0, "%*s", curlen + 1, col->name); + if (!strcmp(col->name, "slin") || + !strcmp(col->name, "speex") || + !strcmp(col->name, "silk")) { + ast_str_append(&out, 0, "%*s%u", curlen - adjust + 1, + col->name, col->sample_rate / 1000); + } else { + ast_str_append(&out, 0, "%*s", curlen + 1, col->name); + } } else if (k == 0 && i > 0) { /* Left column - use a static size. */ - ast_str_append(&out, 0, "%*s", longest, row->name); + if (!strcmp(row->name, "slin") || + !strcmp(row->name, "speex") || + !strcmp(row->name, "silk")) { + int adjust_row = log10(row->sample_rate / 1000) + 1; + ast_str_append(&out, 0, "%*s%u", longest - adjust_row, + row->name, row->sample_rate / 1000); + } else { + ast_str_append(&out, 0, "%*s", longest, row->name); + } } else if (x >= 0 && y >= 0) { /* Codec not supported */ ast_str_append(&out, 0, "%*s", curlen + 1, "-"); |