Allow functions to be written to (bug #2278, with mods)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5296 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2005-03-29 06:16:49 +00:00
parent f966e5e186
commit eb91006b7c
6 changed files with 260 additions and 217 deletions

2
cdr.c
View File

@@ -204,7 +204,7 @@ void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *wor
} }
} }
int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, char *value, int recur) int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur)
{ {
struct ast_var_t *newvariable; struct ast_var_t *newvariable;
struct varshead *headp; struct varshead *headp;

View File

@@ -150,7 +150,7 @@ static int nosound=0;
/* ZZ */ /* ZZ */
static struct ast_channel *alsa_request(const char *type, int format, void *data, int *cause); static struct ast_channel *alsa_request(const char *type, int format, void *data, int *cause);
static int alsa_digit(struct ast_channel *c, char digit); static int alsa_digit(struct ast_channel *c, char digit);
static int alsa_text(struct ast_channel *c, char *text); static int alsa_text(struct ast_channel *c, const char *text);
static int alsa_hangup(struct ast_channel *c); static int alsa_hangup(struct ast_channel *c);
static int alsa_answer(struct ast_channel *c); static int alsa_answer(struct ast_channel *c);
static struct ast_frame *alsa_read(struct ast_channel *chan); static struct ast_frame *alsa_read(struct ast_channel *chan);
@@ -479,7 +479,7 @@ static int alsa_digit(struct ast_channel *c, char digit)
return 0; return 0;
} }
static int alsa_text(struct ast_channel *c, char *text) static int alsa_text(struct ast_channel *c, const char *text)
{ {
ast_mutex_lock(&alsalock); ast_mutex_lock(&alsalock);
ast_verbose( " << Console Received text %s >> \n", text); ast_verbose( " << Console Received text %s >> \n", text);

View File

@@ -3711,7 +3711,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
e->capability = capability; e->capability = capability;
e->parent = gw; e->parent = gw;
e->dtmfmode = dtmfmode; e->dtmfmode = dtmfmode;
if (!ep_reload && e->sub->rtp) if (!ep_reload && e->sub && e->sub->rtp)
e->dtmfmode |= MGCP_DTMF_INBAND; e->dtmfmode |= MGCP_DTMF_INBAND;
e->adsi = adsi; e->adsi = adsi;
e->type = TYPE_LINE; e->type = TYPE_LINE;

View File

@@ -89,7 +89,7 @@ struct ast_cdr {
}; };
extern void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur); extern void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur);
extern int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, char *value, int recur); extern int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur);
extern int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur); extern int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur);
extern void ast_cdr_free_vars(struct ast_cdr *cdr, int recur); extern void ast_cdr_free_vars(struct ast_cdr *cdr, int recur);
extern int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr); extern int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr);

View File

@@ -58,7 +58,8 @@ struct ast_custom_function_obj {
char *name; char *name;
char *desc; char *desc;
char *syntax; char *syntax;
char *(*function)(struct ast_channel *, char *, char *, char *, size_t); char *(*read)(struct ast_channel *, char *, char *, char *, size_t);
void (*write)(struct ast_channel *, char *, char *, const char *);
struct ast_custom_function_obj *next; struct ast_custom_function_obj *next;
}; };
@@ -577,8 +578,8 @@ struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw); struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw);
int pbx_builtin_serialize_variables(struct ast_channel *chan, char *buf, size_t size); int pbx_builtin_serialize_variables(struct ast_channel *chan, char *buf, size_t size);
extern char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name); extern char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name);
extern void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value); extern void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value);
extern void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp); extern void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp);
extern void pbx_builtin_clear_globals(void); extern void pbx_builtin_clear_globals(void);
extern int pbx_builtin_setvar(struct ast_channel *chan, void *data); extern int pbx_builtin_setvar(struct ast_channel *chan, void *data);

426
pbx.c
View File

@@ -89,7 +89,7 @@ struct ast_include {
char *rname; /* Context to include */ char *rname; /* Context to include */
const char *registrar; /* Registrar */ const char *registrar; /* Registrar */
int hastime; /* If time construct exists */ int hastime; /* If time construct exists */
struct ast_timing timing; /* time construct */ struct ast_timing timing; /* time construct */
struct ast_include *next; /* Link them together */ struct ast_include *next; /* Link them together */
char stuff[0]; char stuff[0];
}; };
@@ -191,8 +191,8 @@ static int pbx_builtin_saycharacters(struct ast_channel *, void *);
static int pbx_builtin_sayphonetic(struct ast_channel *, void *); static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
int pbx_builtin_setvar(struct ast_channel *, void *); int pbx_builtin_setvar(struct ast_channel *, void *);
static int pbx_builtin_importvar(struct ast_channel *, void *); static int pbx_builtin_importvar(struct ast_channel *, void *);
void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value); static char *ast_func_read(struct ast_channel *chan, const char *in, char *workspace, size_t len);
char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name); static void ast_func_write(struct ast_channel *chan, const char *in, const char *value);
static struct varshead globals; static struct varshead globals;
@@ -843,30 +843,7 @@ void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, c
if (c) if (c)
headp=&c->varshead; headp=&c->varshead;
*ret=NULL; *ret=NULL;
if (c && c->cdr && !strncasecmp(var, "CDR(", 4)) { /* ${CDR(NEET)} */ if ((first=strchr(var,':'))) { /* : Remove characters counting from end or start of string */
char *vtmp, *nt;
if ((vtmp = ast_strdupa((char *) var + 4)) && (nt = strchr(vtmp, ')'))) {
*nt = '\0';
ast_cdr_getvar(c->cdr, vtmp, ret, workspace, workspacelen, 1);
} else
ast_log(LOG_WARNING, "Invalid CDR variable.\n");
return;
} else if (!strncasecmp(var,"LEN(",4)) { /* ${LEN(<string>)} */
/* Now we have the variable name on cp3 */
int len=strlen(var);
int len_len=4;
if (strrchr(var,')')) {
char cp3[80];
strncpy(cp3, var, sizeof(cp3) - 1);
cp3[len-len_len-1]='\0';
sprintf(workspace,"%d",(int)strlen(cp3));
*ret = workspace;
} else {
/* length is zero */
*ret = "0";
}
} else if ((first=strchr(var,':'))) { /* : Remove characters counting from end or start of string */
strncpy(tmpvar, var, sizeof(tmpvar) - 1); strncpy(tmpvar, var, sizeof(tmpvar) - 1);
first = strchr(tmpvar, ':'); first = strchr(tmpvar, ':');
if (!first) if (!first)
@@ -1072,20 +1049,6 @@ icky:
} }
} }
} }
if (!(*ret)) {
int len=strlen(var);
int len_env=strlen("ENV(");
if (len > (len_env+1) && !strncasecmp(var,"ENV(",len_env) && !strcmp(var+len-1,")")) {
char cp3[80] = "";
strncpy(cp3, var, sizeof(cp3) - 1);
cp3[len-1]='\0';
*ret=getenv(cp3+len_env);
if (*ret) {
strncpy(workspace, *ret, workspacelen - 1);
*ret = workspace;
}
}
}
} }
} }
@@ -1155,33 +1118,86 @@ int ast_custom_function_register(struct ast_custom_function_obj *acf)
return -1; return -1;
} }
static char *ast_func(struct ast_channel *chan, char *in, char *workspace, size_t len) { char *ast_func_read(struct ast_channel *chan, const char *in, char *workspace, size_t len)
char *out = NULL; {
static char *ret = "0"; char *args = NULL, *function, *p;
char *ret = "0";
struct ast_custom_function_obj *acfptr; struct ast_custom_function_obj *acfptr;
if ((out = strchr(in, ' '))) { function = ast_strdupa(in);
*out = '\0'; if (function) {
out++; if ((args = strchr(function, '('))) {
*args = '\0';
if((acfptr = ast_custom_function_find_obj(in))) { args++;
/* run the custom function */ if ((p = strrchr(args, ')'))) {
return acfptr->function(chan, in, out, workspace, len); *p = '\0';
} else {
ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
}
} else {
ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
} }
if ((acfptr = ast_custom_function_find_obj(function))) {
/* run the custom function */
if (acfptr->read) {
return acfptr->read(chan, function, args, workspace, len);
} else {
ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
}
} else {
ast_log(LOG_ERROR, "Function %s not registered\n", function);
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
}
return ret;
}
static void ast_func_write(struct ast_channel *chan, const char *in, const char *value)
{
char *args = NULL, *function, *p;
struct ast_custom_function_obj *acfptr;
function = ast_strdupa(in);
if (function) {
if ((args = strchr(function, '('))) {
*args = '\0';
args++;
if ((p = strrchr(args, ')'))) {
*p = '\0';
} else {
ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
}
} else {
ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
}
if ((acfptr = ast_custom_function_find_obj(function))) {
/* run the custom function */
if (acfptr->write) {
acfptr->write(chan, function, args, value);
} else {
ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
}
} else {
ast_log(LOG_ERROR, "Function %s not registered\n", function);
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
} }
return strdup(ret);
} }
static char *builtin_function_isnull(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) static char *builtin_function_isnull(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{ {
char *ret_true = "1", *ret_false = "0"; char *ret_true = "1", *ret_false = "0";
return cmd ? ret_false : ret_true; return data && *data ? ret_false : ret_true;
} }
static char *builtin_function_exists(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) static char *builtin_function_exists(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{ {
char *ret_true = "1", *ret_false = "0"; char *ret_true = "1", *ret_false = "0";
return cmd ? ret_true : ret_false; return data && *data ? ret_true : ret_false;
} }
static char *builtin_function_if(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) static char *builtin_function_if(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
@@ -1219,35 +1235,88 @@ static char *builtin_function_if(struct ast_channel *chan, char *cmd, char *data
return ret; return ret;
} }
static char *builtin_function_env_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
char *ret = "";
if (data) {
ret = getenv(data);
if (!ret)
ret = "";
}
strncpy(buf, ret, len);
buf[len - 1] = '\0';
return buf;
}
static void builtin_function_env_write(struct ast_channel *chan, char *cmd, char *data, const char *value)
{
if (data && !ast_strlen_zero(data)) {
if (value && !ast_strlen_zero(value)) {
setenv(data, value, 1);
} else {
unsetenv(data);
}
}
}
static char *builtin_function_len(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
int length = 0;
if (data) {
length = strlen(data);
}
snprintf(buf, len, "%d", length);
return buf;
}
static char *builtin_function_cdr_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
char *ret;
if (chan && chan->cdr && data) {
ast_cdr_getvar(chan->cdr, data, &ret, buf, len, 1);
}
return ret;
}
static void builtin_function_cdr_write(struct ast_channel *chan, char *cmd, char *data, const char *value)
{
if (chan && chan->cdr && data) {
ast_cdr_setvar(chan->cdr, data, value, 1);
}
}
static char *builtin_function_regex(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) static char *builtin_function_regex(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{ {
char *ret_true = "1", *ret_false = "0", *ret; char *ret_true = "1", *ret_false = "0", *ret;
char *arg, *tmp; char *arg, *earg, *tmp, errstr[256] = "";
int errcode;
regex_t regexbuf; regex_t regexbuf;
ret = ret_false; /* convince me otherwise */ ret = ret_false; /* convince me otherwise */
if ((tmp = ast_strdupa(data)) && (arg = strchr(tmp, '"')) && (data = strchr(arg+1, '"'))) { tmp = ast_strdupa(data);
arg++; if (tmp) {
*data = '\0'; /* Regex in quotes */
data++; arg = strchr(tmp, '"');
if (arg) {
if(data[0] == ' ') { arg++;
data++; earg = strrchr(arg, '"');
if (earg) {
*earg = '\0';
}
} else { } else {
ast_log(LOG_WARNING, "Malformed input missing space in %s\n", cmd); arg = tmp;
ret = ret_false;
} }
if (regcomp(&regexbuf, arg, REG_EXTENDED | REG_NOSUB)) { if ((errcode = regcomp(&regexbuf, arg, REG_EXTENDED | REG_NOSUB))) {
ast_log(LOG_WARNING, "Malformed regex input %s\n", cmd); regerror(errcode, &regexbuf, errstr, sizeof(errstr));
ast_log(LOG_WARNING, "Malformed input %s(%s): %s\n", cmd, data, errstr);
ret = NULL; ret = NULL;
} else {
ret = regexec(&regexbuf, data, 0, NULL, 0) ? ret_false : ret_true;
} }
ret = regexec(&regexbuf, data, 0, NULL, 0) ? ret_false : ret_true;
regfree(&regexbuf); regfree(&regexbuf);
} else { } else {
ast_log(LOG_WARNING, "Malformed input %s\n", cmd); ast_log(LOG_ERROR, "Out of memory in %s(%s)\n", cmd, data);
} }
return ret; return ret;
@@ -1260,9 +1329,9 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
int length; int length;
char workspace[4096]; char workspace[4096];
char ltmp[4096], var[4096]; char ltmp[4096], var[4096];
char *nextvar, *nextexp, *nextfunc, *nextthing; char *nextvar, *nextexp, *nextthing;
char *vars, *vare; char *vars, *vare;
int pos, brackets, needsub, len, needfunc; int pos, brackets, needsub, len;
/* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
zero-filled */ zero-filled */
@@ -1272,7 +1341,6 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
pos = strlen(whereweare); pos = strlen(whereweare);
nextvar = NULL; nextvar = NULL;
nextexp = NULL; nextexp = NULL;
nextfunc = NULL;
nextthing = strchr(whereweare, '$'); nextthing = strchr(whereweare, '$');
if (nextthing) { if (nextthing) {
switch(nextthing[1]) { switch(nextthing[1]) {
@@ -1282,9 +1350,6 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
case '[': case '[':
nextexp = nextthing; nextexp = nextthing;
break; break;
case '(':
nextfunc = nextthing;
break;
} }
} }
/* If there is one, we only go that far */ /* If there is one, we only go that far */
@@ -1292,9 +1357,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
pos = nextvar - whereweare; pos = nextvar - whereweare;
else if (nextexp) else if (nextexp)
pos = nextexp - whereweare; pos = nextexp - whereweare;
else if (nextfunc) {
pos = nextfunc - whereweare;
}
/* Can't copy more than 'count' bytes */ /* Can't copy more than 'count' bytes */
if (pos > count) if (pos > count)
pos = count; pos = count;
@@ -1346,9 +1409,17 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
vars = var; vars = var;
} }
/* Retrieve variable value */
workspace[0] = '\0'; workspace[0] = '\0';
pbx_retrieve_variable(c,vars,&cp4, workspace, sizeof(workspace), headp);
if (var[len - 1] == ')') {
/* Evaluate function */
cp4 = ast_func_read(c, vars, workspace, sizeof(workspace));
ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4);
} else {
/* Retrieve variable value */
pbx_retrieve_variable(c, vars, &cp4, workspace, sizeof(workspace), headp);
}
if (cp4) { if (cp4) {
length = strlen(cp4); length = strlen(cp4);
if (length > count) if (length > count)
@@ -1357,7 +1428,6 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
count -= length; count -= length;
cp2 += length; cp2 += length;
} }
} else if (nextexp) { } else if (nextexp) {
/* We have an expression. Find the start and end, and determine /* We have an expression. Find the start and end, and determine
if we are going to have to recursively call ourselves on the if we are going to have to recursively call ourselves on the
@@ -1365,7 +1435,6 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
vars = vare = nextexp + 2; vars = vare = nextexp + 2;
brackets = 1; brackets = 1;
needsub = 0; needsub = 0;
needfunc = 0;
/* Find the end of it */ /* Find the end of it */
while(brackets && *vare) { while(brackets && *vare) {
@@ -1380,9 +1449,6 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
} else if ((vare[0] == '$') && (vare[1] == '{')) { } else if ((vare[0] == '$') && (vare[1] == '{')) {
needsub++; needsub++;
vare++; vare++;
} else if ((vare[0] == '$') && (vare[1] == '(')) {
needfunc++;
vare++;
} }
vare++; vare++;
} }
@@ -1399,7 +1465,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
var[len] = '\0'; var[len] = '\0';
/* Substitute if necessary */ /* Substitute if necessary */
if (needsub || needfunc) { if (needsub) {
memset(ltmp, 0, sizeof(ltmp)); memset(ltmp, 0, sizeof(ltmp));
pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1); pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
vars = ltmp; vars = ltmp;
@@ -1421,64 +1487,6 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
cp2 += length; cp2 += length;
free(cp4); free(cp4);
} }
} else if (nextfunc) {
/* We have a function. Find the start and end */
vars = vare = nextfunc + 2;
brackets = 1;
needsub = 0;
/* Find the end of it */
while(brackets && *vare) {
if ((vare[0] == '$') && (vare[1] == '(')) {
needsub++;
brackets++;
vare++;
} else if (vare[0] == '(') {
brackets++;
} else if (vare[0] == ')') {
brackets--;
} else if ((vare[0] == '$') && (vare[1] == '{')) {
needsub++;
vare++;
}
vare++;
}
if (brackets)
ast_log(LOG_NOTICE, "Error in extension logic (missing ')')\n");
len = vare - vars - 1;
/* Skip totally over variable name */
whereweare += ( len + 3);
/* Store variable name (and truncate) */
memset(var, 0, sizeof(var));
strncpy(var, vars, sizeof(var) - 1);
var[len] = '\0';
/* Substitute if necessary */
if (needsub) {
memset(ltmp, 0, sizeof(ltmp));
pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
vars = ltmp;
} else {
vars = var;
}
/* Evaluate expression */
cp4 = ast_func(c, vars, workspace, sizeof(workspace));
ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
if (cp4) {
length = strlen(cp4);
if (length > count)
length = count;
memcpy(cp2, cp4, length);
count -= length;
cp2 += length;
free(cp4);
}
} else } else
break; break;
} }
@@ -1494,8 +1502,8 @@ void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1,
pbx_substitute_variables_helper_full(NULL, cp1, cp2, count, headp); pbx_substitute_variables_helper_full(NULL, cp1, cp2, count, headp);
} }
static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) { static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
{
memset(passdata, 0, datalen); memset(passdata, 0, datalen);
/* No variables or expressions in e->data, so why scan it? */ /* No variables or expressions in e->data, so why scan it? */
@@ -1698,28 +1706,28 @@ static int ast_extension_state2(struct ast_exten *e)
res = ast_device_state(cur); res = ast_device_state(cur);
switch (res) { switch (res) {
case AST_DEVICE_NOT_INUSE: case AST_DEVICE_NOT_INUSE:
allunavailable = 0; allunavailable = 0;
allbusy = 0; allbusy = 0;
break; break;
case AST_DEVICE_INUSE: case AST_DEVICE_INUSE:
return AST_EXTENSION_INUSE; return AST_EXTENSION_INUSE;
case AST_DEVICE_BUSY: case AST_DEVICE_BUSY:
allunavailable = 0; allunavailable = 0;
allfree = 0; allfree = 0;
busy = 1; busy = 1;
break; break;
case AST_DEVICE_UNAVAILABLE: case AST_DEVICE_UNAVAILABLE:
case AST_DEVICE_INVALID: case AST_DEVICE_INVALID:
allbusy = 0; allbusy = 0;
allfree = 0; allfree = 0;
break; break;
default: default:
allunavailable = 0; allunavailable = 0;
allbusy = 0; allbusy = 0;
allfree = 0; allfree = 0;
} }
cur = rest; cur = rest;
} while (cur); } while (cur);
if (allfree) if (allfree)
@@ -1905,12 +1913,12 @@ int ast_extension_state_add(const char *context, const char *exten,
cblist->callback = callback; cblist->callback = callback;
cblist->data = data; cblist->data = data;
cblist->next = statecbs; cblist->next = statecbs;
statecbs = cblist; statecbs = cblist;
ast_mutex_unlock(&hintlock); ast_mutex_unlock(&hintlock);
return 0; return 0;
} }
if (!context || !exten) if (!context || !exten)
return -1; return -1;
@@ -1986,7 +1994,7 @@ int ast_extension_state_del(int id, ast_state_cb_type callback)
cblist = cblist->next; cblist = cblist->next;
} }
ast_mutex_lock(&hintlock); ast_mutex_lock(&hintlock);
return -1; return -1;
} }
@@ -2008,7 +2016,7 @@ int ast_extension_state_del(int id, ast_state_cb_type callback)
ast_mutex_unlock(&hintlock); ast_mutex_unlock(&hintlock);
return 0; return 0;
} }
cbprev = cblist; cbprev = cblist;
cblist = cblist->next; cblist = cblist->next;
} }
list = list->next; list = list->next;
@@ -2038,7 +2046,7 @@ static int ast_add_hint(struct ast_exten *e)
return -1; return -1;
} }
list = list->next; list = list->next;
} }
if (option_debug > 1) if (option_debug > 1)
ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
@@ -3115,7 +3123,7 @@ static int handle_show_applications(int fd, int argc, char *argv[])
ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>"); ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
} }
} }
if ((!like) && (!describing)) { if ((!like) && (!describing)) {
ast_cli(fd, " -= %d Applications Registered =-\n",total_apps); ast_cli(fd, " -= %d Applications Registered =-\n",total_apps);
} else { } else {
ast_cli(fd, " -= %d Applications Matching =-\n",total_match); ast_cli(fd, " -= %d Applications Matching =-\n",total_match);
@@ -3434,31 +3442,59 @@ static int handle_show_dialplan(int fd, int argc, char *argv[])
/* custom commands */ /* custom commands */
static struct ast_custom_function_obj regex_function = { static struct ast_custom_function_obj regex_function = {
.name = "regex", .name = "regex",
.desc = "Regular Expression: Returns 1 if data matches regular expression.", .desc = "Regular Expression: Returns 1 if data matches regular expression.",
.syntax = "$(regex \"<regular expression>\" <data>)", .syntax = "regex(\"<regular expression>\" <data>)",
.function = builtin_function_regex, .read = builtin_function_regex,
.write = NULL,
}; };
static struct ast_custom_function_obj isnull_function = { static struct ast_custom_function_obj isnull_function = {
.name = "isnull", .name = "isnull",
.desc = "NULL Test: Returns 1 if NULL or 0 otherwise", .desc = "NULL Test: Returns 1 if NULL or 0 otherwise",
.syntax = "$(isnull <data>)", .syntax = "isnull(<data>)",
.function = builtin_function_isnull, .read = builtin_function_isnull,
.write = NULL,
}; };
static struct ast_custom_function_obj exists_function = { static struct ast_custom_function_obj exists_function = {
.name = "exists", .name = "exists",
.desc = "Existance Test: Returns 1 if exists, 0 otherwise", .desc = "Existance Test: Returns 1 if exists, 0 otherwise",
.syntax = "$(exists <data>)", .syntax = "exists(<data>)",
.function = builtin_function_exists, .read = builtin_function_exists,
.write = NULL,
}; };
static struct ast_custom_function_obj if_function = { static struct ast_custom_function_obj if_function = {
.name = "if", .name = "if",
.desc = "Conditional: Returns the data following '?' if true else the data following ':'", .desc = "Conditional: Returns the data following '?' if true else the data following ':'",
.syntax = "$(if <expr>?<true>:<false>)", .syntax = "if(<expr>?<true>:<false>)",
.function = builtin_function_if, .read = builtin_function_if,
.write = NULL,
};
static struct ast_custom_function_obj env_function = {
.name = "ENV",
.desc = "Gets or sets the environment variable specified",
.syntax = "ENV(<envname>)",
.read = builtin_function_env_read,
.write = builtin_function_env_write,
};
static struct ast_custom_function_obj len_function = {
.name = "LEN",
.desc = "Returns the length of the arguments given",
.syntax = "LEN(<string>)",
.read = builtin_function_len,
.write = NULL,
};
static struct ast_custom_function_obj cdr_function = {
.name = "CDR",
.desc = "Gets or sets the CDR variable specified",
.syntax = "CDR(<cdrvarname>)",
.read = builtin_function_cdr_read,
.write = builtin_function_cdr_write,
}; };
@@ -3880,8 +3916,8 @@ static unsigned int get_month(char *mon)
int ast_build_timing(struct ast_timing *i, char *info_in) int ast_build_timing(struct ast_timing *i, char *info_in)
{ {
char info_save[256]; char info_save[256];
char *info; char *info;
char *c; char *c;
/* Check for empty just in case */ /* Check for empty just in case */
@@ -5126,7 +5162,7 @@ void __ast_context_destroy(struct ast_context *con, const char *registrar)
e = e->next; e = e->next;
destroy_exten(el); destroy_exten(el);
} }
ast_mutex_destroy(&tmp->lock); ast_mutex_destroy(&tmp->lock);
free(tmp); free(tmp);
if (!con) { if (!con) {
/* Might need to get another one -- restart */ /* Might need to get another one -- restart */
@@ -5542,7 +5578,7 @@ int pbx_builtin_serialize_variables(struct ast_channel *chan, char *buf, size_t
return total; return total;
} }
char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name) char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
{ {
struct ast_var_t *variables; struct ast_var_t *variables;
struct varshead *headp; struct varshead *headp;
@@ -5569,12 +5605,15 @@ char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name)
return NULL; return NULL;
} }
void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value) void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
{ {
struct ast_var_t *newvariable; struct ast_var_t *newvariable;
struct varshead *headp; struct varshead *headp;
if (name[strlen(name)-1] == ')')
return ast_func_write(chan, name, value);
if (chan) { if (chan) {
headp = &chan->varshead; headp = &chan->varshead;
if (!strncasecmp(name, "CDR(", 4)) { /* CDR VARS */ if (!strncasecmp(name, "CDR(", 4)) { /* CDR VARS */
@@ -5773,18 +5812,18 @@ static int pbx_builtin_saynumber(struct ast_channel *chan, void *data)
if (!data || ast_strlen_zero((char *)data)) { if (!data || ast_strlen_zero((char *)data)) {
ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
return -1; return -1;
} }
strncpy(tmp, (char *)data, sizeof(tmp)-1); strncpy(tmp, (char *)data, sizeof(tmp)-1);
number=tmp; number=tmp;
strsep(&number, "|"); strsep(&number, "|");
options = strsep(&number, "|"); options = strsep(&number, "|");
if (options) { if (options) {
if ( strcasecmp(options, "f") && strcasecmp(options,"m") && if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
strcasecmp(options, "c") && strcasecmp(options, "n") ) { strcasecmp(options, "c") && strcasecmp(options, "n") ) {
ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
return -1; return -1;
} }
} }
return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options); return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
@@ -5826,7 +5865,7 @@ int load_pbx(void)
ast_verbose( "Asterisk PBX Core Initializing\n"); ast_verbose( "Asterisk PBX Core Initializing\n");
ast_verbose( "Registering builtin applications:\n"); ast_verbose( "Registering builtin applications:\n");
} }
AST_LIST_HEAD_INIT(&globals); AST_LIST_HEAD_INIT(&globals);
ast_cli_register(&show_applications_cli); ast_cli_register(&show_applications_cli);
ast_cli_register(&show_functions_cli); ast_cli_register(&show_functions_cli);
ast_cli_register(&show_application_cli); ast_cli_register(&show_application_cli);
@@ -5837,6 +5876,9 @@ int load_pbx(void)
ast_custom_function_register(&isnull_function); ast_custom_function_register(&isnull_function);
ast_custom_function_register(&exists_function); ast_custom_function_register(&exists_function);
ast_custom_function_register(&if_function); ast_custom_function_register(&if_function);
ast_custom_function_register(&env_function);
ast_custom_function_register(&len_function);
ast_custom_function_register(&cdr_function);
/* Register builtin applications */ /* Register builtin applications */
for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {