Newer
Older
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_copy_string(chan->name, "OutgoingSpoolFailed", sizeof(chan->name));
if (!ast_strlen_zero(context))
ast_copy_string(chan->context, context, sizeof(chan->context));
ast_copy_string(chan->exten, "failed", sizeof(chan->exten));
ast_set_variables(chan, vars);
ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
}
}
} else {
as = malloc(sizeof(struct async_stat));
if (!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));
ast_copy_string(as->exten, exten, sizeof(as->exten));
as->priority = priority;
as->timeout = timeout;
ast_set_variables(chan, vars);
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);
if (channel)
*channel = NULL;
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;
};
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, 1);
} 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, struct ast_channel **locked_channel)
{
struct ast_channel *chan;
struct async_stat *as;
struct app_tmp *tmp;
struct outgoing_helper oh;
memset(&oh, 0, sizeof(oh));
oh.vars = vars;
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 */
ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
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 (chan->_state == AST_STATE_UP) {
res = 0;
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
tmp = malloc(sizeof(struct app_tmp));
if (tmp) {
memset(tmp, 0, sizeof(struct app_tmp));
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;
ast_log(LOG_ERROR, "Out of memory :(\n");
res = -1;
}
} 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;
}
} else {
as = malloc(sizeof(struct async_stat));
if (!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);
/* 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");
return;
}
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;
}
Mark Spencer
committed
ast_mutex_unlock(&conlock);
return;
}
tmpl = tmp;
tmp = tmp->next;
}
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
*/
static int pbx_builtin_busy(struct ast_channel *chan, void *data)
{
ast_indicate(chan, AST_CONTROL_BUSY);
Kevin P. Fleming
committed
ast_setstate(chan, AST_STATE_BUSY);
wait_for_hangup(chan, data);
/*!
* \ingroup applications
*/
static int pbx_builtin_congestion(struct ast_channel *chan, void *data)
{
ast_indicate(chan, AST_CONTROL_CONGESTION);
Kevin P. Fleming
committed
ast_setstate(chan, AST_STATE_BUSY);
wait_for_hangup(chan, data);
/*!
* \ingroup applications
*/
static int pbx_builtin_answer(struct ast_channel *chan, void *data)
int delay = 0;
int res;
if (chan->_state == AST_STATE_UP)
delay = 0;
else if (!ast_strlen_zero(data))
delay = atoi(data);
res = ast_answer(chan);
if (res)
return res;
if (delay)
res = ast_safe_sleep(chan, delay);
return res;
AST_APP_OPTIONS(resetcdr_opts, {
AST_APP_OPTION('w', AST_CDR_FLAG_POSTED),
AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED),
AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),
});
/*!
* \ingroup applications
*/
static int pbx_builtin_resetcdr(struct ast_channel *chan, void *data)
{
char *args;
struct ast_flags flags = { 0 };
if (!ast_strlen_zero(data)) {
args = ast_strdupa(data);
if (!args) {
ast_log(LOG_ERROR, "Out of memory!\n");
return -1;
}
ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
}
ast_cdr_reset(chan->cdr, &flags);
/*!
* \ingroup applications
*/
static int pbx_builtin_setamaflags(struct ast_channel *chan, void *data)
{
/* Copy the AMA Flags as specified */
if (data)
ast_cdr_setamaflags(chan, (char *)data);
else
ast_cdr_setamaflags(chan, "");
return 0;
}
/*!
* \ingroup applications
*/
static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
{
/* Just return non-zero and it will hang up */
return -1;
}
/*!
* \ingroup applications
*/
static int pbx_builtin_gotoiftime(struct ast_channel *chan, void *data)
{
int res=0;
char *s, *ts;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n <time range>|<days of week>|<days of month>|<months>?[[context|]extension|]priority\n");
return -1;
}
if ((s = ast_strdupa((char *) data))) {
ts = s;
/* Separate the Goto path */
strsep(&ts,"?");
/* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
if (ast_build_timing(&timing, s) && ast_check_timing(&timing))
res = pbx_builtin_goto(chan, (void *)ts);
} else {
ast_log(LOG_ERROR, "Memory Error!\n");
}
return res;
}
/*!
* \ingroup applications
*/
static int pbx_builtin_execiftime(struct ast_channel *chan, void *data)
{
int res = 0;
char *ptr1, *ptr2;
struct ast_timing timing;
struct ast_app *app;
const char *usage = "ExecIfTime requires an argument:\n <time range>|<days of week>|<days of month>|<months>?<appname>[|<appargs>]";
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "%s\n", usage);
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
ptr1 = ast_strdupa(data);
if (!ptr1) {
ast_log(LOG_ERROR, "Out of Memory!\n");
return -1;
}
ptr2 = ptr1;
/* Separate the Application data ptr1 is the time spec ptr2 is the app|data */
strsep(&ptr2,"?");
if(!ast_build_timing(&timing, ptr1)) {
ast_log(LOG_WARNING, "Invalid Time Spec: %s\nCorrect usage: %s\n", ptr1, usage);
res = -1;
}
if (!res && ast_check_timing(&timing)) {
if (!ptr2) {
ast_log(LOG_WARNING, "%s\n", usage);
}
/* ptr2 is now the app name
we're done with ptr1 now so recycle it and use it to point to the app args */
if((ptr1 = strchr(ptr2, '|'))) {
*ptr1 = '\0';
ptr1++;
Russell Bryant
committed
}
if ((app = pbx_findapp(ptr2))) {
res = pbx_exec(chan, app, ptr1 ? ptr1 : "", 1);
} else {
ast_log(LOG_WARNING, "Cannot locate application %s\n", ptr2);
res = -1;
/*!
* \ingroup applications
*/
static int pbx_builtin_wait(struct ast_channel *chan, void *data)
if (data && atof((char *)data)) {
ms = atof((char *)data) * 1000;
/*!
* \ingroup applications
*/
static int pbx_builtin_waitexten(struct ast_channel *chan, void *data)
{
Mark Spencer
committed
int ms, res, argc;
char *args;
char *argv[2];
char *options = NULL;
char *timeout = NULL;
struct ast_flags flags = {0};
char *opts[1] = { NULL };
Mark Spencer
committed
args = ast_strdupa(data);
if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
Mark Spencer
committed
if (argc > 0) {
timeout = argv[0];
if (argc > 1)
options = argv[1];
}
}
if (options)
ast_app_parse_options(waitexten_opts, &flags, opts, options);
Mark Spencer
committed
if (ast_test_flag(&flags, WAITEXTEN_MOH))
ast_moh_start(chan, opts[0]);
Mark Spencer
committed
Mark Spencer
committed
if (timeout && atof((char *)timeout))
ms = atof((char *)timeout) * 1000;
else if (chan->pbx)
ms = chan->pbx->rtimeout * 1000;
else
ms = 10000;
res = ast_waitfordigit(chan, ms);
if (!res) {
Mark Spencer
committed
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) {
Mark Spencer
committed
ast_verbose(VERBOSE_PREFIX_3 "Timeout on %s, continuing...\n", chan->name);
} else if (ast_exists_extension(chan, chan->context, "t", 1, chan->cid.cid_num)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Timeout on %s, going to 't'\n", chan->name);
ast_copy_string(chan->exten, "t", sizeof(chan->exten));
chan->priority = 0;
} else {
ast_log(LOG_WARNING, "Timeout but no rule 't' in context '%s'\n", chan->context);
res = -1;
}
Mark Spencer
committed
if (ast_test_flag(&flags, WAITEXTEN_MOH))
ast_moh_stop(chan);
/*!
* \ingroup applications
*/
static int pbx_builtin_background(struct ast_channel *chan, void *data)
Mark Spencer
committed
int argc;
Kevin P. Fleming
committed
char *argv[4];
Mark Spencer
committed
char *options = NULL;
char *filename = NULL;
char *front = NULL, *back = NULL;
Mark Spencer
committed
char *lang = NULL;
Kevin P. Fleming
committed
char *context = NULL;
Mark Spencer
committed
struct ast_flags flags = {0};
if ((argc = ast_app_separate_args(parse, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
switch (argc) {
case 4:
context = argv[3];
case 3:
lang = argv[2];
case 2:
options = argv[1];
case 1:
Mark Spencer
committed
filename = argv[0];
Mark Spencer
committed
ast_log(LOG_WARNING, "Background requires an argument (filename)\n");
Mark Spencer
committed
}
}
if (!lang)
lang = chan->language;
Kevin P. Fleming
committed
if (!context)
context = chan->context;
Mark Spencer
committed
if (options) {
if (!strcasecmp(options, "skip"))
flags.flags = BACKGROUND_SKIP;
else if (!strcasecmp(options, "noanswer"))
flags.flags = BACKGROUND_NOANSWER;
else
ast_app_parse_options(background_opts, &flags, NULL, options);
Mark Spencer
committed
}
/* Answer if need be */
if (chan->_state != AST_STATE_UP) {
Mark Spencer
committed
if (ast_test_flag(&flags, BACKGROUND_SKIP)) {
Mark Spencer
committed
} else if (!ast_test_flag(&flags, BACKGROUND_NOANSWER)) {
res = ast_answer(chan);
}
}
if (!res) {
/* Stop anything playing */
ast_stopstream(chan);
/* Stream a file */
front = filename;
while(!res && front) {
if((back = strchr(front, '&'))) {
*back = '\0';
back++;
}
res = ast_streamfile(chan, front, lang);
if (!res) {
Kevin P. Fleming
committed
if (ast_test_flag(&flags, BACKGROUND_PLAYBACK)) {
res = ast_waitstream(chan, "");
} else {
if (ast_test_flag(&flags, BACKGROUND_MATCHEXTEN)) {
res = ast_waitstream_exten(chan, context);
} else {
res = ast_waitstream(chan, AST_DIGIT_ANY);
}
}
ast_stopstream(chan);
} else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char*)data);
res = 0;
break;
}
front = back;
Kevin P. Fleming
committed
if (context != chan->context && res) {
snprintf(chan->exten, sizeof(chan->exten), "%c", res);
ast_copy_string(chan->context, context, sizeof(chan->context));
chan->priority = 0;
return 0;
} else {
return res;
}
/*! Goto
* \ingroup applications
*/
static int pbx_builtin_goto(struct ast_channel *chan, void *data)
int res;
res = ast_parseable_goto(chan, (const char *) data);
if (!res && (option_verbose > 2))
ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1);
int pbx_builtin_serialize_variables(struct ast_channel *chan, char *buf, size_t size)
{
struct ast_var_t *variables;
const char *var, *val;
Kevin P. Fleming
committed
if (!chan)
return 0;
memset(buf, 0, size);
AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
if(variables &&
(var=ast_var_name(variables)) && (val=ast_var_value(variables)) &&
!ast_strlen_zero(var) && !ast_strlen_zero(val)) {
if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
Kevin P. Fleming
committed
} else
total++;
} else
break;
}
return total;
}
const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
struct ast_var_t *variables;
struct varshead *headp;
if (chan)
headp=&chan->varshead;
AST_LIST_TRAVERSE(headp,variables,entries) {
if (!strcmp(name, ast_var_name(variables)))
return ast_var_value(variables);
}
if (headp != &globals) {
/* Check global variables if we haven't already */
headp = &globals;
AST_LIST_TRAVERSE(headp,variables,entries) {
if (!strcmp(name, ast_var_name(variables)))
return ast_var_value(variables);
}
}
}
void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
{
struct ast_var_t *newvariable;
struct varshead *headp;
if (name[strlen(name)-1] == ')') {
ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
return ast_func_write(chan, name, value);
}
headp = (chan) ? &chan->varshead : &globals;
if (value) {
if ((option_verbose > 1) && (headp == &globals))
ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
newvariable = ast_var_assign(name, value);
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
}
}
void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
struct varshead *headp;
Mark Spencer
committed
const char *nametail = name;
if (name[strlen(name)-1] == ')')
return ast_func_write(chan, name, value);
Kevin P. Fleming
committed
headp = (chan) ? &chan->varshead : &globals;
Mark Spencer
committed
/* For comparison purposes, we have to strip leading underscores */
if (*nametail == '_') {
nametail++;
if (*nametail == '_')
nametail++;
}
AST_LIST_TRAVERSE (headp, newvariable, entries) {
Mark Spencer
committed
if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
/* there is already such a variable, delete it */
AST_LIST_REMOVE(headp, newvariable, entries);
ast_var_delete(newvariable);
break;
}
}
if (value) {
if ((option_verbose > 1) && (headp == &globals))
Kevin P. Fleming
committed
ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
newvariable = ast_var_assign(name, value);
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
Martin Pycko
committed
int pbx_builtin_setvar(struct ast_channel *chan, void *data)
Kevin P. Fleming
committed
char *name, *value, *mydata;
int argc;
char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */
int global = 0;
int x;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
Kevin P. Fleming
committed
return 0;
}
Kevin P. Fleming
committed
mydata = ast_strdupa(data);
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
Kevin P. Fleming
committed
/* check for a trailing flags argument */
if ((argc > 1) && !strchr(argv[argc-1], '=')) {
argc--;
if (strchr(argv[argc], 'g'))
global = 1;
Kevin P. Fleming
committed
for (x = 0; x < argc; x++) {
name = argv[x];
if ((value = strchr(name, '='))) {
*value = '\0';
value++;
pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
} else
ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
}
int pbx_builtin_importvar(struct ast_channel *chan, void *data)
{
char *name;
char *value;
char *stringp=NULL;
char *channel;
Kevin P. Fleming
committed
struct ast_channel *chan2;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
return 0;
}
stringp = ast_strdupa(data);
name = strsep(&stringp,"=");
channel = strsep(&stringp,"|");
value = strsep(&stringp,"\0");
if (channel && value && name) {
Kevin P. Fleming
committed
chan2 = ast_get_channel_by_name_locked(channel);
if (chan2) {
s = alloca(strlen(value) + 4);
if (s) {
sprintf(s, "${%s}", value);
pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
}
ast_mutex_unlock(&chan2->lock);
}
pbx_builtin_setvar_helper(chan, name, tmp);
}
return(0);
}
static int pbx_builtin_setglobalvar(struct ast_channel *chan, void *data)
{
char *name;
char *value;
char *stringp = NULL;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
return 0;
}
stringp = data;
name = strsep(&stringp, "=");
value = strsep(&stringp, "\0");
pbx_builtin_setvar_helper(NULL, name, value);
return(0);
}
static int pbx_builtin_noop(struct ast_channel *chan, void *data)
{
return 0;
}
void pbx_builtin_clear_globals(void)
{
struct ast_var_t *vardata;
while (!AST_LIST_EMPTY(&globals)) {
vardata = AST_LIST_REMOVE_HEAD(&globals, entries);
ast_var_delete(vardata);
}
}
static int pbx_checkcondition(char *condition)
{
if (condition) {
if (*condition == '\0') {
/* Empty strings are false */
return 0;
} else if (*condition >= '0' && *condition <= '9') {
/* Numbers are evaluated for truth */
return atoi(condition);
} else {
/* Strings are true */
return 1;
}
} else {
/* NULL is also false */
return 0;
}
}
static int pbx_builtin_gotoif(struct ast_channel *chan, void *data)
{
char *condition, *branch1, *branch2, *branch;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
s = ast_strdupa(data);
stringp = s;
condition = strsep(&stringp,"?");
branch1 = strsep(&stringp,":");
branch2 = strsep(&stringp,"");
branch = pbx_checkcondition(condition) ? branch1 : branch2;
if (ast_strlen_zero(branch)) {
ast_log(LOG_DEBUG, "Not taking any branch\n");
rc = pbx_builtin_goto(chan, branch);
static int pbx_builtin_saynumber(struct ast_channel *chan, void *data)
{
int res = 0;
Mark Spencer
committed
char tmp[256];
char *number = (char *) NULL;
char *options = (char *) NULL;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
return -1;
}
ast_copy_string(tmp, (char *) data, sizeof(tmp));
number=tmp;
strsep(&number, "|");
options = strsep(&number, "|");
if (options) {
Mark Spencer
committed
if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
strcasecmp(options, "c") && strcasecmp(options, "n") ) {
ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
return -1;