summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/asterisk.c254
-rw-r--r--main/cli.c101
-rw-r--r--main/translate.c29
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, "-");