Newer
Older
int ret = -1;
struct ast_context *c = find_context_locked(context);
if (c) {
ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
ast_unlock_contexts();
int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
{
struct ast_ignorepat *ip, *ipl = NULL;
if (ast_mutex_lock(&con->lock)) {
Mark Spencer
committed
(!registrar || (registrar == ip->registrar))) {
if (ipl) {
ipl->next = ip->next;
free(ip);
} else {
con->ignorepats = ip->next;
free(ip);
}
ast_mutex_unlock(&con->lock);
ast_mutex_unlock(&con->lock);
errno = EINVAL;
return -1;
}
/*
* EBUSY - can't lock
int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar)
int ret = -1;
struct ast_context *c = find_context_locked(context);
if (c) {
ret = ast_context_add_ignorepat2(c, value, registrar);
ast_unlock_contexts();
int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
{
struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
int length;
length = sizeof(struct ast_ignorepat);
length += strlen(value) + 1;
Russell Bryant
committed
if (!(ignorepat = ast_calloc(1, length)))
Russell Bryant
committed
/* The cast to char * is because we need to write the initial value.
* The field is not supposed to be modified otherwise
*/
strcpy((char *)ignorepat->pattern, value);
ignorepat->next = NULL;
ignorepat->registrar = registrar;
ast_mutex_lock(&con->lock);
for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
ignorepatl = ignorepatc;
if (!strcasecmp(ignorepatc->pattern, value)) {
ast_mutex_unlock(&con->lock);
if (ignorepatl)
ignorepatl->next = ignorepat;
ast_mutex_unlock(&con->lock);
int ast_ignore_pattern(const char *context, const char *pattern)
{
struct ast_context *con;
struct ast_ignorepat *pat;
for (pat = con->ignorepats; pat; pat = pat->next) {
if (ast_extension_match(pat->pattern, pattern))
return 1;
}
}
return 0;
}
/*
* EBUSY - can't lock
int ast_add_extension(const char *context, int replace, const char *extension,
int priority, const char *label, const char *callerid,
const char *application, void *data, void (*datad)(void *), const char *registrar)
int ret = -1;
struct ast_context *c = find_context_locked(context);
if (c) {
ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
application, data, datad, registrar);
ast_unlock_contexts();
Kevin P. Fleming
committed
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
{
if (!chan)
return -1;
if (!ast_strlen_zero(context))
ast_copy_string(chan->context, context, sizeof(chan->context));
if (!ast_strlen_zero(exten))
ast_copy_string(chan->exten, exten, sizeof(chan->exten));
Kevin P. Fleming
committed
if (priority > -1) {
chan->priority = priority;
/* see flag description in channel.h for explanation */
if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
chan->priority--;
Kevin P. Fleming
committed
return 0;
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Kevin P. Fleming
committed
Mark Spencer
committed
ast_mutex_lock(&chan->lock);
if (chan->pbx) {
/* This channel is currently in the PBX */
Kevin P. Fleming
committed
ast_explicit_goto(chan, context, exten, priority);
ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
} else {
/* In order to do it when the channel doesn't really exist within
the PBX, we have to make a new channel, masquerade, and start the PBX
at the new location */
struct ast_channel *tmpchan = ast_channel_alloc(0);
if (!tmpchan)
res = -1;
else {
ast_string_field_build(tmpchan, name, "AsyncGoto/%s", chan->name);
/* Make formats okay */
tmpchan->readformat = chan->readformat;
tmpchan->writeformat = chan->writeformat;
/* Setup proper location */
ast_explicit_goto(tmpchan,
S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
/* Masquerade into temp channel */
ast_channel_masquerade(tmpchan, chan);
/* Grab the locks and get going */
ast_mutex_lock(&tmpchan->lock);
Mark Spencer
committed
ast_do_masquerade(tmpchan);
ast_mutex_unlock(&tmpchan->lock);
/* Start the PBX going on our stolen channel */
if (ast_pbx_start(tmpchan)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
ast_hangup(tmpchan);
res = -1;
}
}
}
Mark Spencer
committed
ast_mutex_unlock(&chan->lock);
int ast_async_goto_by_name(const char *channame, const char *context, const char *exten, int priority)
Kevin P. Fleming
committed
chan = ast_get_channel_by_name_locked(channame);
if (chan) {
res = ast_async_goto(chan, context, exten, priority);
ast_mutex_unlock(&chan->lock);
}
return res;
/*! \brief copy a string skipping whitespace */
static int ext_strncpy(char *dst, const char *src, int len)
/* otherwise exten => [a-b],1,... doesn't work */
/* case '-': */
/* Ignore */
break;
default:
*dst = *src;
dst++;
}
src++;
count++;
}
*dst = '\0';
static void null_datad(void *foo)
{
}
/*
* EBUSY - can't lock
* EEXIST - extension with the same priority exist and no replace is set
*
*/
int replace, const char *extension, int priority, const char *label, const char *callerid,
const char *application, void *data, void (*datad)(void *),
const char *registrar)
#define LOG do { if (option_debug) {\
if (tmp->matchcid) { \
ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
} else { \
ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
} \
} else if (option_verbose > 2) { \
if (tmp->matchcid) { \
ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
} else { \
ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
} \
} } while(0)
/*
* This is a fairly complex routine. Different extensions are kept
* in order by the extension number. Then, extensions of different
* priorities (same extension) are kept in a list, according to the
* peer pointer.
*/
struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
int res;
int length;
char *p;
char expand_buf[VAR_BUF_SIZE] = { 0, };
/* if we are adding a hint, and there are global variables, and the hint
contains variable references, then expand them
*/
ast_mutex_lock(&globalslock);
if ((priority == PRIORITY_HINT) && AST_LIST_FIRST(&globals) && strstr(application, "${")) {
pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf));
application = expand_buf;
}
ast_mutex_unlock(&globalslock);
length = sizeof(struct ast_exten);
length += strlen(extension) + 1;
length += strlen(application) + 1;
if (label)
length += strlen(label) + 1;
if (callerid)
length += strlen(callerid) + 1;
else
/* Be optimistic: Build the extension structure first */
if (datad == NULL)
datad = null_datad;
Russell Bryant
committed
if (!(tmp = ast_calloc(1, length)))
Russell Bryant
committed
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
/* use p as dst in assignments, as the fields are const char * */
p = tmp->stuff;
if (label) {
tmp->label = p;
strcpy(p, label);
p += strlen(label) + 1;
}
tmp->exten = p;
p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
tmp->priority = priority;
tmp->cidmatch = p; /* but use p for assignments below */
if (callerid) {
p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
tmp->matchcid = 1;
} else {
*p++ = '\0';
tmp->matchcid = 0;
}
tmp->app = p;
strcpy(p, application);
tmp->parent = con;
tmp->data = data;
tmp->datad = datad;
tmp->registrar = registrar;
if (ast_mutex_lock(&con->lock)) {
free(tmp);
/* And properly destroy the data */
datad(data);
ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
/* Make sure patterns are always last! */
if ((e->exten[0] != '_') && (extension[0] == '_'))
res = -1;
else if ((e->exten[0] == '_') && (extension[0] != '_'))
res = 1;
else
res= strcmp(e->exten, extension);
if (!res) {
if (!e->matchcid && !tmp->matchcid)
res = 0;
else if (tmp->matchcid && !e->matchcid)
res = 1;
else if (e->matchcid && !tmp->matchcid)
res = -1;
else
res = strcasecmp(e->cidmatch, tmp->cidmatch);
}
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
if (res == 0) {
/* We have an exact match, now we find where we are
and be sure there's no duplicates */
while(e) {
if (e->priority == tmp->priority) {
/* Can't have something exactly the same. Is this a
replacement? If so, replace, otherwise, bonk. */
if (replace) {
if (ep) {
/* We're in the peer list, insert ourselves */
ep->peer = tmp;
tmp->peer = e->peer;
} else if (el) {
/* We're the first extension. Take over e's functions */
el->next = tmp;
tmp->next = e->next;
tmp->peer = e->peer;
} else {
/* We're the very first extension. */
con->root = tmp;
tmp->next = e->next;
tmp->peer = e->peer;
}
if (tmp->priority == PRIORITY_HINT)
ast_change_hint(e,tmp);
/* Destroy the old one */
e->datad(e->data);
free(e);
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
ast_change_hint(e, tmp);
/* And immediately return success. */
LOG;
return 0;
} 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->datad(tmp->data);
free(tmp);
ast_mutex_unlock(&con->lock);
return -1;
}
} else if (e->priority > tmp->priority) {
/* Slip ourselves in just before e */
if (ep) {
/* Easy enough, we're just in the peer list */
ep->peer = tmp;
tmp->peer = e;
} else if (el) {
/* We're the first extension in this peer list */
el->next = tmp;
tmp->next = e->next;
e->next = NULL;
tmp->peer = e;
} else {
/* We're the very first extension altogether */
tmp->next = con->root->next;
/* Con->root must always exist or we couldn't get here */
tmp->peer = con->root;
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
LOG;
return 0;
}
ep = e;
e = e->peer;
}
/* If we make it here, then it's time for us to go at the very end.
ep *must* be defined or we couldn't have gotten here. */
ep->peer = tmp;
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
/* And immediately return success. */
LOG;
return 0;
} else if (res > 0) {
/* Insert ourselves just before 'e'. We're the first extension of
this kind */
tmp->next = e;
if (el) {
/* We're in the list somewhere */
el->next = tmp;
} else {
/* We're at the top of the list */
con->root = tmp;
}
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
/* And immediately return success. */
LOG;
return 0;
}
el = e;
}
/* If we fall all the way through to here, then we need to be on the end. */
if (el)
el->next = tmp;
else
con->root = tmp;
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
struct async_stat {
pthread_t p;
struct ast_channel *chan;
char context[AST_MAX_CONTEXT];
char exten[AST_MAX_EXTENSION];
int priority;
int timeout;
char app[AST_MAX_EXTENSION];
};
static void *async_wait(void *data)
{
struct async_stat *as = data;
struct ast_channel *chan = as->chan;
int timeout = as->timeout;
int res;
struct ast_frame *f;
while (timeout && (chan->_state != AST_STATE_UP)) {
res = ast_waitfor(chan, timeout);
if (res < 1)
break;
if (timeout > -1)
timeout = res;
f = ast_read(chan);
if (!f)
break;
if (f->frametype == AST_FRAME_CONTROL) {
if ((f->subclass == AST_CONTROL_BUSY) ||
(f->subclass == AST_CONTROL_CONGESTION) )
break;
}
ast_frfree(f);
}
if (chan->_state == AST_STATE_UP) {
if (!ast_strlen_zero(as->app)) {
app = pbx_findapp(as->app);
if (app) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
pbx_exec(chan, app, as->appdata);
} else
ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
if (!ast_strlen_zero(as->context))
ast_copy_string(chan->context, as->context, sizeof(chan->context));
if (!ast_strlen_zero(as->exten))
ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
if (as->priority > 0)
chan->priority = as->priority;
/* Run the PBX */
if (ast_pbx_run(chan)) {
ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
} else {
/* PBX will have taken care of this */
chan = NULL;
}
}
}
free(as);
if (chan)
ast_hangup(chan);
return NULL;
}
Joshua Colp
committed
/*! Function to post an empty cdr after a spool call fails.
Joshua Colp
committed
* This function posts an empty cdr for a failed spool call
*
*/
int ast_pbx_outgoing_cdr_failed(void)
{
/* allocate a channel */
struct ast_channel *chan = ast_channel_alloc(0);
Russell Bryant
committed
if (!chan)
return -1; /* failure */
chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */
/* allocation of the cdr failed */
ast_channel_free(chan); /* free the channel */
return -1; /* return failure */
}
/* allocation of the cdr was successful */
ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
ast_cdr_start(chan->cdr); /* record the start and stop time */
ast_cdr_end(chan->cdr);
ast_cdr_failed(chan->cdr); /* set the status to failed */
ast_cdr_detach(chan->cdr); /* post and free the record */
ast_channel_free(chan); /* free the channel */
return 0; /* success */
}
int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
{
struct ast_channel *chan;
struct async_stat *as;
Martin Pycko
committed
struct outgoing_helper oh;
Martin Pycko
committed
LOAD_OH(oh);
chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
if (channel) {
*channel = chan;
if (chan)
ast_mutex_lock(&chan->lock);
}
if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
} else {
chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */
if (!chan->cdr) {
/* allocation of the cdr failed */
free(chan->pbx);
res = -1;
goto outgoing_exten_cleanup;
}
/* allocation of the cdr was successful */
ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
ast_cdr_start(chan->cdr);
}
Martin Pycko
committed
res = 0;
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
Martin Pycko
committed
if (channel)
ast_mutex_unlock(&chan->lock);
ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
if (channel)
*channel = NULL;
ast_hangup(chan);
res = -1;
}
} else {
if (ast_pbx_start(chan)) {
ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
*channel = NULL;
ast_mutex_unlock(&chan->lock);
}
} else {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
if(chan->cdr) { /* update the cdr */
/* here we update the status of the call, which sould be busy.
* if that fails then we set the status to failed */
if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
ast_cdr_failed(chan->cdr);
}
*channel = NULL;
ast_mutex_unlock(&chan->lock);
}
if (res < 0) { /* the call failed for some reason */
if (*reason == 0) { /* if the call failed (not busy or no answer)
* update the cdr with the failed message */
cdr_res = ast_pbx_outgoing_cdr_failed();
if (cdr_res != 0) {
res = cdr_res;
goto outgoing_exten_cleanup;
}
/* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
/* check if "failed" exists */
if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
chan = ast_channel_alloc(0);
if (chan) {
ast_string_field_set(chan, name, "OutgoingSpoolFailed");
if (!ast_strlen_zero(context))
ast_copy_string(chan->context, context, sizeof(chan->context));
set_ext_pri(chan, "failed", 1);
ast_set_variables(chan, vars);
if (account)
ast_cdr_setaccount(chan, account);
Russell Bryant
committed
}
Russell Bryant
committed
if (!(as = ast_calloc(1, sizeof(*as)))) {
res = -1;
goto outgoing_exten_cleanup;
}
chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
if (channel) {
*channel = chan;
if (chan)
ast_mutex_lock(&chan->lock);
}
res = -1;
goto outgoing_exten_cleanup;
ast_copy_string(as->context, context, sizeof(as->context));
set_ext_pri(as->chan, exten, priority);
ast_set_variables(chan, vars);
if (account)
ast_cdr_setaccount(chan, account);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
ast_log(LOG_WARNING, "Failed to start async wait\n");
free(as);
*channel = NULL;
ast_mutex_unlock(&chan->lock);
}
res = -1;
goto outgoing_exten_cleanup;
outgoing_exten_cleanup:
ast_variables_destroy(vars);
struct app_tmp {
char app[256];
char data[256];
struct ast_channel *chan;
pthread_t t;
};
/*! \brief run the application and free the descriptor once done */
static void *ast_pbx_run_app(void *data)
{
struct app_tmp *tmp = data;
struct ast_app *app;
app = pbx_findapp(tmp->app);
if (app) {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
pbx_exec(tmp->chan, app, tmp->data);
} else
ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
ast_hangup(tmp->chan);
free(tmp);
return NULL;
}
int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
{
struct ast_channel *chan;
struct app_tmp *tmp;
struct outgoing_helper oh;
memset(&oh, 0, sizeof(oh));
oh.vars = vars;
oh.account = account;
if (locked_channel)
*locked_channel = NULL;
if (ast_strlen_zero(app)) {
res = -1;
goto outgoing_app_cleanup;
}
chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
} else {
chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */
if(!chan->cdr) {
/* allocation of the cdr failed */
free(chan->pbx);
res = -1;
goto outgoing_app_cleanup;
}
/* allocation of the cdr was successful */
ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
ast_cdr_start(chan->cdr);
}
ast_set_variables(chan, vars);
if (account)
ast_cdr_setaccount(chan, account);
if (chan->_state == AST_STATE_UP) {
res = 0;
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
tmp = ast_calloc(1, sizeof(*tmp));
if (!tmp)
res = -1;
else {
ast_copy_string(tmp->app, app, sizeof(tmp->app));
if (appdata)
ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
if (locked_channel)
ast_mutex_unlock(&chan->lock);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (locked_channel)
ast_mutex_lock(&chan->lock);
if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
free(tmp);
if (locked_channel)
ast_mutex_unlock(&chan->lock);
} else {
if (locked_channel)
*locked_channel = chan;
}
}
}
} else {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
if (chan->cdr) { /* update the cdr */
/* here we update the status of the call, which sould be busy.
* if that fails then we set the status to failed */
if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
ast_cdr_failed(chan->cdr);
}
if (res < 0) { /* the call failed for some reason */
if (*reason == 0) { /* if the call failed (not busy or no answer)
* update the cdr with the failed message */
cdr_res = ast_pbx_outgoing_cdr_failed();
if (cdr_res != 0) {
res = cdr_res;
goto outgoing_app_cleanup;
}
struct async_stat *as;
Russell Bryant
committed
if (!(as = ast_calloc(1, sizeof(*as)))) {
res = -1;
goto outgoing_app_cleanup;
}
chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
res = -1;
goto outgoing_app_cleanup;
ast_copy_string(as->app, app, sizeof(as->app));
ast_copy_string(as->appdata, appdata, sizeof(as->appdata));
ast_set_variables(chan, vars);
if (account)
ast_cdr_setaccount(chan, account);
/* Start a new thread, and get something handling this channel. */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (locked_channel)
ast_mutex_lock(&chan->lock);
if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
ast_log(LOG_WARNING, "Failed to start async wait\n");
free(as);
if (locked_channel)
ast_mutex_unlock(&chan->lock);
res = -1;
goto outgoing_app_cleanup;
} else {
if (locked_channel)
*locked_channel = chan;
outgoing_app_cleanup:
ast_variables_destroy(vars);
static void destroy_exten(struct ast_exten *e)
{
if (e->priority == PRIORITY_HINT)
ast_remove_hint(e);
if (e->datad)
e->datad(e->data);
free(e);
}
void __ast_context_destroy(struct ast_context *con, const char *registrar)
struct ast_exten *e, *el, *en;
Mark Spencer
committed
ast_mutex_lock(&conlock);
if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
(!registrar || !strcasecmp(registrar, tmp->registrar))) {
/* Okay, let's lock the structure to be sure nobody else
is searching through it. */
if (ast_mutex_lock(&tmp->lock)) {
ast_log(LOG_WARNING, "Unable to lock context lock\n");
break;
}
if (tmpl)
tmpl->next = tmp->next;
else
contexts = tmp->next;
/* Okay, now we're safe to let it go -- in a sense, we were
ready to let it go as soon as we locked it. */
ast_mutex_unlock(&tmp->lock);
for (tmpi = tmp->includes; tmpi; ) {
/* Free includes */
tmpil = tmpi;
tmpi = tmpi->next;
free(tmpil);
ipl = ipi;
ipi = ipi->next;
free(ipl);
swl = sw;
sw = sw->next;
free(swl);
swl = sw;
}
for (e = tmp->root; e;) {
for (en = e->peer; en;) {
el = en;
en = en->peer;
destroy_exten(el);
}
el = e;
e = e->next;
destroy_exten(el);
}
ast_mutex_destroy(&tmp->lock);
if (!con) {
/* Might need to get another one -- restart */
tmp = contexts;
tmpl = NULL;
tmpil = NULL;
continue;
}
break;
Mark Spencer
committed
ast_mutex_unlock(&conlock);
void ast_context_destroy(struct ast_context *con, const char *registrar)
Mark Spencer
committed
__ast_context_destroy(con,registrar);
static void wait_for_hangup(struct ast_channel *chan, void *data)
if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0))
waittime = -1;
if (waittime > -1) {
ast_safe_sleep(chan, waittime * 1000);
} else do {
res = ast_waitfor(chan, -1);
if (res < 0)
return;
f = ast_read(chan);
if (f)
ast_frfree(f);
} while(f);
}
/*!
* \ingroup applications
*/
static int pbx_builtin_progress(struct ast_channel *chan, void *data)
{
ast_indicate(chan, AST_CONTROL_PROGRESS);
return 0;
}
/*!
* \ingroup applications
*/
static int pbx_builtin_ringing(struct ast_channel *chan, void *data)
{
ast_indicate(chan, AST_CONTROL_RINGING);
return 0;
}
/*!
* \ingroup applications