summaryrefslogtreecommitdiff
path: root/main/pbx.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2016-08-01 09:31:27 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2016-08-01 09:31:27 -0500
commitb8fdd3ad794857c455f4cc67243e886ef6ed4816 (patch)
tree24b7fad70e402e45e0ffada3c111d885c554642c /main/pbx.c
parentd462cb73a8f3d2802bd5261cc2d218a0890d4f1e (diff)
parent89a0a1eb45dd6055a1052c93e591de5833b85b47 (diff)
Merge "pbx.c: Fix handling of '-' in extension name and callerid"
Diffstat (limited to 'main/pbx.c')
-rw-r--r--main/pbx.c194
1 files changed, 143 insertions, 51 deletions
diff --git a/main/pbx.c b/main/pbx.c
index 27f1a4ecb..3705ea127 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -237,9 +237,11 @@ AST_THREADSTORAGE(extensionstate_buf);
priority.
*/
struct ast_exten {
- char *exten; /*!< Extension name */
+ char *exten; /*!< Clean Extension id */
+ char *name; /*!< Extension name (may include '-' eye candy) */
int matchcid; /*!< Match caller id ? */
const char *cidmatch; /*!< Caller id to match for this extension */
+ const char *cidmatch_display; /*!< Caller id to match (display version) */
int priority; /*!< Priority */
const char *label; /*!< Label */
struct ast_context *parent; /*!< The context this extension belongs to */
@@ -654,6 +656,7 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
static struct ast_context *find_context_locked(const char *context);
static struct ast_context *find_context(const char *context);
static void get_device_state_causing_channels(struct ao2_container *c);
+static int ext_strncpy(char *dst, const char *src, int len, int nofluff);
/*!
* \internal
@@ -878,9 +881,13 @@ int check_contexts(char *file, int line )
e2 = ast_hashtab_lookup(c1->root_table, &ex);
if (!e2) {
if (e1->matchcid == AST_EXT_MATCHCID_ON) {
- ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s (CID match: %s) but it is not in its root_table\n", file, line, c2->name, dummy_name, e1->cidmatch );
+ ast_log(LOG_NOTICE, "Called from: %s:%d: The %s context records "
+ "the exten %s (CID match: %s) but it is not in its root_table\n",
+ file, line, c2->name, dummy_name, e1->cidmatch_display);
} else {
- ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s but it is not in its root_table\n", file, line, c2->name, dummy_name );
+ ast_log(LOG_NOTICE, "Called from: %s:%d: The %s context records "
+ "the exten %s but it is not in its root_table\n",
+ file, line, c2->name, dummy_name);
}
check_contexts_trouble();
}
@@ -1113,11 +1120,11 @@ static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
if (strlen(node->x) > 1) {
ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
- node->exten ? node->exten->exten : "", extenstr);
+ node->exten ? node->exten->name : "", extenstr);
} else {
ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
- node->exten ? node->exten->exten : "", extenstr);
+ node->exten ? node->exten->name : "", extenstr);
}
ast_str_set(&my_prefix, 0, "%s+ ", prefix);
@@ -1232,7 +1239,7 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct
return; \
} \
} else { \
- ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \
+ ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->name); \
return; /* the first match, by definition, will be the best, because of the sorted tree */ \
} \
} \
@@ -1245,13 +1252,13 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct
if (*(str + 1) || p->next_char->x[0] == '!') { \
new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
if (score->exten) { \
- ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \
+ ast_debug(4 ,"returning an exact match-- %s\n", score->exten->name); \
return; /* the first match is all we need */ \
} \
} else { \
new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \
- ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \
+ ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->name : \
"NULL"); \
return; /* the first match is all we need */ \
} \
@@ -1289,14 +1296,17 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct
if (p->exten && *str2 != '/') {
update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
if (score->exten) {
- ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
+ ast_debug(4, "return because scoreboard has a match with '/'--- %s\n",
+ score->exten->name);
return; /* the first match is all we need */
}
}
if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
- ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
+ ast_debug(4, "return because scoreboard has exact match OR "
+ "CANMATCH/MATCHMORE & canmatch set--- %s\n",
+ score->exten ? score->exten->name : "NULL");
return; /* the first match is all we need */
}
}
@@ -1311,14 +1321,17 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct
if (p->exten && *str2 != '/') {
update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
if (score->exten) {
- ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
+ ast_debug(4, "return because scoreboard has a '!' match--- %s\n",
+ score->exten->name);
return; /* the first match is all we need */
}
}
if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
- ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
+ ast_debug(4, "return because scoreboard has exact match OR "
+ "CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n",
+ score->exten ? score->exten->name : "NULL");
return; /* the first match is all we need */
}
}
@@ -1327,7 +1340,9 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct
if (p->next_char && callerid && *callerid) {
new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
- ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
+ ast_debug(4, "return because scoreboard has exact match OR "
+ "CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n",
+ score->exten ? score->exten->name : "NULL");
return; /* the first match is all we need */
}
}
@@ -1680,7 +1695,7 @@ static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, str
}
if (m2->exten) {
ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
- m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
+ m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
}
m2->exten = e1;
m2->deleted = 0;
@@ -1706,7 +1721,7 @@ static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, str
if (!pat_node[idx_next].buf[0]) {
if (m2 && m2->exten) {
ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
- m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
+ m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
}
m1->deleted = 0;
m1->exten = e1;
@@ -2113,6 +2128,41 @@ static int ext_cmp(const char *left, const char *right)
return ext_cmp_pattern(left + 1, right + 1);
}
+static int ext_fluff_count(const char *exten)
+{
+ int fluff = 0;
+
+ if (*exten != '_') {
+ /* not a pattern, simple check. */
+ while (*exten) {
+ if (*exten == '-') {
+ fluff++;
+ }
+ exten++;
+ }
+
+ return fluff;
+ }
+
+ /* do pattern check */
+ while (*exten) {
+ if (*exten == '-') {
+ fluff++;
+ } else if (*exten == '[') {
+ /* skip set, dashes here matter. */
+ exten = strchr(exten, ']');
+
+ if (!exten) {
+ /* we'll end up warning about this later, don't spam logs */
+ return fluff;
+ }
+ }
+ exten++;
+ }
+
+ return fluff;
+}
+
int ast_extension_cmp(const char *a, const char *b)
{
int cmp;
@@ -4883,6 +4933,7 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char *
struct ast_exten *peer;
struct ast_exten ex, *exten2, *exten3;
char dummy_name[1024];
+ char dummy_cid[1024];
struct ast_exten *previous_peer = NULL;
struct ast_exten *next_peer = NULL;
int found = 0;
@@ -4898,9 +4949,14 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char *
#endif
/* find this particular extension */
ex.exten = dummy_name;
+ ext_strncpy(dummy_name, extension, sizeof(dummy_name), 1);
ex.matchcid = matchcallerid;
- ex.cidmatch = callerid;
- ast_copy_string(dummy_name, extension, sizeof(dummy_name));
+ if (callerid) {
+ ex.cidmatch = dummy_cid;
+ ext_strncpy(dummy_cid, callerid, sizeof(dummy_cid), 1);
+ } else {
+ ex.cidmatch = NULL;
+ }
exten = ast_hashtab_lookup(con->root_table, &ex);
if (exten) {
if (priority == 0) {
@@ -4923,13 +4979,19 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char *
if (exten2) {
if (exten2->label) { /* if this exten has a label, remove that, too */
exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
- if (!exten3)
- ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten);
+ if (!exten3) {
+ ast_log(LOG_ERROR, "Did not remove this priority label (%d/%s) "
+ "from the peer_label_table of context %s, extension %s!\n",
+ priority, exten2->label, con->name, exten2->name);
+ }
}
exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
- if (!exten3)
- ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten);
+ if (!exten3) {
+ ast_log(LOG_ERROR, "Did not remove this priority (%d) from the "
+ "peer_table of context %s, extension %s!\n",
+ priority, con->name, exten2->name);
+ }
if (exten2 == exten && exten2->peer) {
exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
ast_hashtab_insert_immediate(con->root_table, exten2->peer);
@@ -4938,8 +5000,11 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char *
/* well, if the last priority of an exten is to be removed,
then, the extension is removed, too! */
exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
- if (!exten3)
- ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
+ if (!exten3) {
+ ast_log(LOG_ERROR, "Did not remove this exten (%s) from the "
+ "context root_table (%s) (priority %d)\n",
+ exten->name, con->name, priority);
+ }
if (con->pattern_tree) {
struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
if (x->exten) { /* this test for safety purposes */
@@ -4950,7 +5015,7 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char *
}
} else {
ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
- priority, exten->exten, con->name);
+ priority, exten->name, con->name);
}
}
} else {
@@ -4967,7 +5032,7 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char *
/* scan the extension list to find first matching extension-registrar */
for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
- if (!strcmp(exten->exten, extension) &&
+ if (!strcmp(exten->exten, ex.exten) &&
(!registrar || !strcmp(exten->registrar, registrar)) &&
(!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
break;
@@ -4981,7 +5046,7 @@ int ast_context_remove_extension_callerid2(struct ast_context *con, const char *
/* scan the priority list to remove extension with exten->priority == priority */
for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
- peer && !strcmp(peer->exten, extension) &&
+ peer && !strcmp(peer->exten, ex.exten) &&
(!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ;
peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
@@ -6271,11 +6336,11 @@ static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *
dupdstr = ast_strdup(prio_item->data);
- res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label,
+ res1 = ast_add_extension2(new, 0, prio_item->name, prio_item->priority, prio_item->label,
prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar);
if (!res1 && new_exten_item && new_prio_item){
ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
- context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
+ context->name, prio_item->name, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
} else {
/* we do NOT pass the priority data from the old to the new -- we pass a copy of it, so no changes to the current dialplan take place,
and no double frees take place, either! */
@@ -6880,8 +6945,8 @@ int ast_async_goto_by_name(const char *channame, const char *context, const char
return res;
}
-/*! \brief copy a string skipping whitespace */
-static int ext_strncpy(char *dst, const char *src, int len)
+/*! \brief copy a string skipping whitespace and dashes */
+static int ext_strncpy(char *dst, const char *src, int len, int nofluff)
{
int count = 0;
int insquares = 0;
@@ -6894,6 +6959,9 @@ static int ext_strncpy(char *dst, const char *src, int len)
} else if (*src == ' ' && !insquares) {
src++;
continue;
+ } else if (*src == '-' && !insquares && nofluff) {
+ src++;
+ continue;
}
*dst = *src;
dst++;
@@ -6919,14 +6987,14 @@ static int add_priority(struct ast_context *con, struct ast_exten *tmp,
for (ep = NULL; e ; ep = e, e = e->peer) {
if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
- if (strcmp(e->exten, tmp->exten)) {
+ if (strcmp(e->name, tmp->name)) {
ast_log(LOG_WARNING,
"Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
- tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority);
+ tmp->name, tmp->priority, con->name, tmp->label, e->name, e->priority);
} else {
ast_log(LOG_WARNING,
"Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
- tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
+ tmp->name, tmp->priority, con->name, tmp->label, e->priority);
}
repeated_label = 1;
}
@@ -6952,14 +7020,14 @@ static int add_priority(struct ast_context *con, struct ast_exten *tmp,
/* Can't have something exactly the same. Is this a
replacement? If so, replace, otherwise, bonk. */
if (!replace) {
- if (strcmp(e->exten, tmp->exten)) {
+ if (strcmp(e->name, tmp->name)) {
ast_log(LOG_WARNING,
"Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
- tmp->exten, tmp->priority, con->name, e->exten);
+ tmp->name, tmp->priority, con->name, e->name);
} else {
ast_log(LOG_WARNING,
"Unable to register extension '%s' priority %d in '%s', already in use\n",
- tmp->exten, tmp->priority, con->name);
+ tmp->name, tmp->priority, con->name);
}
return -1;
@@ -7144,6 +7212,8 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
char expand_buf[VAR_BUF_SIZE];
struct ast_exten dummy_exten = {0};
char dummy_name[1024];
+ int exten_fluff;
+ int callerid_fluff;
if (ast_strlen_zero(extension)) {
ast_log(LOG_ERROR,"You have to be kidding-- add exten '' to context %s? Figure out a name and call me back. Action ignored.\n",
@@ -7178,15 +7248,26 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
}
}
+ exten_fluff = ext_fluff_count(extension);
+ callerid_fluff = callerid ? ext_fluff_count(callerid) : 0;
+
length = sizeof(struct ast_exten);
length += strlen(extension) + 1;
+ if (exten_fluff) {
+ length += strlen(extension) + 1 - exten_fluff;
+ }
length += strlen(application) + 1;
- if (label)
+ if (label) {
length += strlen(label) + 1;
- if (callerid)
+ }
+ if (callerid) {
length += strlen(callerid) + 1;
- else
+ if (callerid_fluff) {
+ length += strlen(callerid) + 1 - callerid_fluff;
+ }
+ } else {
length ++; /* just the '\0' */
+ }
/* Be optimistic: Build the extension structure first */
if (!(tmp = ast_calloc(1, length)))
@@ -7202,14 +7283,25 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
strcpy(p, label);
p += strlen(label) + 1;
}
- tmp->exten = p;
- p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
+ tmp->name = p;
+ p += ext_strncpy(p, extension, strlen(extension) + 1, 0) + 1;
+ if (exten_fluff) {
+ tmp->exten = p;
+ p += ext_strncpy(p, extension, strlen(extension) + 1, 1) + 1;
+ } else {
+ /* no fluff, we don't need a copy. */
+ tmp->exten = tmp->name;
+ }
tmp->priority = priority;
- tmp->cidmatch = p; /* but use p for assignments below */
+ tmp->cidmatch_display = tmp->cidmatch = p; /* but use p for assignments below */
/* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
if (callerid) {
- p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
+ p += ext_strncpy(p, callerid, strlen(callerid) + 1, 0) + 1;
+ if (callerid_fluff) {
+ tmp->cidmatch = p;
+ p += ext_strncpy(p, callerid, strlen(callerid) + 1, 1) + 1;
+ }
tmp->matchcid = AST_EXT_MATCHCID_ON;
} else {
*p++ = '\0';
@@ -7228,7 +7320,7 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
an extension, and the trie exists, then we need to incrementally add this pattern to it. */
- ast_copy_string(dummy_name, extension, sizeof(dummy_name));
+ ext_strncpy(dummy_name, tmp->exten, sizeof(dummy_name), 1);
dummy_exten.exten = dummy_name;
dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
dummy_exten.cidmatch = 0;
@@ -7332,19 +7424,19 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
if (option_debug) {
if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
- tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
+ tmp->name, tmp->priority, tmp->cidmatch_display, con->name, con);
} else {
ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
- tmp->exten, tmp->priority, con->name, con);
+ tmp->name, tmp->priority, con->name, con);
}
}
if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
- tmp->exten, tmp->priority, tmp->cidmatch, con->name);
+ tmp->name, tmp->priority, tmp->cidmatch_display, con->name);
} else {
ast_verb(3, "Added extension '%s' priority %d to %s\n",
- tmp->exten, tmp->priority, con->name);
+ tmp->name, tmp->priority, con->name);
}
return 0;
@@ -7882,7 +7974,7 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
continue;
}
ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
- tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
+ tmp->name, prio_item->name, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
ast_copy_string(extension, prio_item->exten, sizeof(extension));
if (prio_item->cidmatch) {
ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
@@ -8302,7 +8394,7 @@ struct ast_context *ast_get_extension_context(struct ast_exten *exten)
const char *ast_get_extension_name(struct ast_exten *exten)
{
- return exten ? exten->exten : NULL;
+ return exten ? exten->name : NULL;
}
const char *ast_get_extension_label(struct ast_exten *exten)
@@ -8335,7 +8427,7 @@ int ast_get_extension_matchcid(struct ast_exten *e)
const char *ast_get_extension_cidmatch(struct ast_exten *e)
{
- return e ? e->cidmatch : NULL;
+ return e ? e->cidmatch_display : NULL;
}
const char *ast_get_extension_app(struct ast_exten *e)