--- pbx.c.orig 2004-06-10 20:37:43.000000000 -0700 +++ pbx.c 2004-06-11 19:44:00.000000000 -0700 @@ -165,6 +165,7 @@ static int pbx_builtin_congestion(struct ast_channel *, void *); static int pbx_builtin_busy(struct ast_channel *, void *); static int pbx_builtin_setglobalvar(struct ast_channel *, void *); +static int pbx_builtin_getchanvar(struct ast_channel *, void *); static int pbx_builtin_noop(struct ast_channel *, void *); static int pbx_builtin_gotoif(struct ast_channel *, void *); static int pbx_builtin_gotoiftime(struct ast_channel *, void *); @@ -313,6 +314,11 @@ "Set variable to value", " SetGlobalVar(#n=value): Sets global variable n to value" }, + { "GetChanVar", pbx_builtin_getchanvar, +"Get A Channel Variable from any Channel", +" GetChanVar(#n=variable@channelname): Sets a channel variable n in this channel to\n" +"the value of a channel variable in another channel" }, + { "SetLanguage", pbx_builtin_setlanguage, "Sets user language", " SetLanguage(language): Set the channel language to 'language'. This\n" @@ -767,80 +773,33 @@ return NULL; } -static void pbx_substitute_variables_temp(struct ast_channel *c,const char *var,char **ret, char *workspace, int workspacelen) + +/* +* Check the builtin channel vars. +*/ + +static void pbx_check_builtin_chanvars(struct ast_channel *c, char **ret, char *workspace, int workspacelen, const char *var) { - char *first,*second; - char tmpvar[80] = ""; + int offset; time_t thistime; struct tm brokentime; - int offset,offset2; - struct ast_var_t *variables; - char *name, *num; /* for callerid name + num variables */ - struct varshead *headp=NULL; + char *callingfrom, *caller; /* for callerid name + num variables */ - if (c) - headp=&c->varshead; - *ret=NULL; - /* Now we have the variable name on cp3 */ - if (!strncasecmp(var,"LEN(",4)) { - 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",strlen(cp3)); - *ret = workspace; - } else { - /* length is zero */ - *ret = "0"; - } - } else if ((first=strchr(var,':'))) { - strncpy(tmpvar, var, sizeof(tmpvar) - 1); - first = strchr(tmpvar, ':'); - if (!first) - first = tmpvar + strlen(tmpvar); - *first='\0'; - pbx_substitute_variables_temp(c,tmpvar,ret,workspace,workspacelen - 1); - if (!(*ret)) return; - offset=atoi(first+1); - if ((second=strchr(first+1,':'))) { - *second='\0'; - offset2=atoi(second+1); - } else - offset2=strlen(*ret)-offset; - if (abs(offset)>strlen(*ret)) { - if (offset>=0) - offset=strlen(*ret); - else - offset=-strlen(*ret); - } - if ((offset<0 && offset2>-offset) || (offset>=0 && offset+offset2>strlen(*ret))) { - if (offset>=0) - offset2=strlen(*ret)-offset; - else - offset2=strlen(*ret)+offset; - } - if (offset>=0) - *ret+=offset; - else - *ret+=strlen(*ret)+offset; - (*ret)[offset2] = '\0'; - } else if (c && !strcmp(var, "CALLERIDNUM")) { + if (c && !strcmp(var, "CALLERIDNUM")) { if (c->callerid) strncpy(workspace, c->callerid, workspacelen - 1); - ast_callerid_parse(workspace, &name, &num); - if (num) { - ast_shrink_phone_number(num); - *ret = num; + ast_callerid_parse(workspace, &caller, &callingfrom); + if (callingfrom) { + ast_shrink_phone_number(callingfrom); + *ret = callingfrom; } else *ret = workspace; } else if (c && !strcmp(var, "CALLERIDNAME")) { if (c->callerid) strncpy(workspace, c->callerid, workspacelen - 1); - ast_callerid_parse(workspace, &name, &num); - if (name) - *ret = name; + ast_callerid_parse(workspace, &caller, &callingfrom); + if (caller) + *ret = caller; else *ret = workspace; } else if (c && !strcmp(var, "CALLERID")) { @@ -928,8 +887,74 @@ } else if (c && !strcmp(var, "LANGUAGE")) { strncpy(workspace, c->language, workspacelen - 1); *ret = workspace; - } else { - if (c) { + } +} + + +static void pbx_substitute_variables_temp(struct ast_channel *c,const char *var,char **ret, char *workspace, int workspacelen) +{ + char *first,*second; + char tmpvar[80] = ""; + int offset,offset2; + struct ast_var_t *variables; + struct varshead *headp=NULL; + + if (c) + headp=&c->varshead; + *ret=NULL; + /* Now we have the variable name on cp3 */ + if (!strncasecmp(var,"LEN(",4)) { + 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",strlen(cp3)); + *ret = workspace; + } else { + /* length is zero */ + *ret = "0"; + } + } else if ((first=strchr(var,':'))) { + strncpy(tmpvar, var, sizeof(tmpvar) - 1); + first = strchr(tmpvar, ':'); + if (!first) + first = tmpvar + strlen(tmpvar); + *first='\0'; + pbx_substitute_variables_temp(c,tmpvar,ret,workspace,workspacelen - 1); + if (!(*ret)) return; + offset=atoi(first+1); + if ((second=strchr(first+1,':'))) { + *second='\0'; + offset2=atoi(second+1); + } else + offset2=strlen(*ret)-offset; + if (abs(offset)>strlen(*ret)) { + if (offset>=0) + offset=strlen(*ret); + else + offset=-strlen(*ret); + } + if ((offset<0 && offset2>-offset) || (offset>=0 && offset+offset2>strlen(*ret))) { + if (offset>=0) + offset2=strlen(*ret)-offset; + else + offset2=strlen(*ret)+offset; + } + if (offset>=0) + *ret+=offset; + else + *ret+=strlen(*ret)+offset; + (*ret)[offset2] = '\0'; + }else { + /* Check builtin chan vars */ + + pbx_check_builtin_chanvars(c, ret, workspace, workspacelen, var); + + /* Check user-defined channel variables */ + + if(!(*ret) && (c)) { AST_LIST_TRAVERSE(headp,variables,entries) { #if 0 ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables)); @@ -976,6 +1001,7 @@ } } + void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count) { char *cp4; @@ -4529,6 +4555,119 @@ } +static int pbx_builtin_getchanvar(struct ast_channel *chan, void *data) +{ + char *channel = NULL; + char *source = NULL; + char *dest = NULL; + char *value = NULL; + char *stringp = NULL; + char workspace[128]; + struct ast_channel *otherchan = NULL; + struct ast_var_t *variables = NULL; + struct varshead *headp = NULL; + + + + /* Is there something to process */ + + if (!data || ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "GetChanVar: Ignoring, since there is no variable to set\n"); + return 0; + } + + /* Carve out the args */ + + stringp = data; + dest = strsep(&stringp, "="); + source = strsep(&stringp, "@"); + channel = strsep(&stringp, "\0"); + + /* Must have all parameters */ + + if((!dest) || (!channel) || (!source)){ + if(option_verbose >= 4) + ast_verbose(VERBOSE_PREFIX_4 "GetChanVar: Ignoring, one or more parameters missing\n"); + ast_log(LOG_WARNING, "GetChanVar: Ignoring, one or more parameters missing\n"); + return 0; + } + if(option_verbose >= 4){ + ast_verbose(VERBOSE_PREFIX_4 "GetChanVar: dest=%s\n", dest); + ast_verbose(VERBOSE_PREFIX_4 "GetChanVar: channel=%s\n", channel); + ast_verbose(VERBOSE_PREFIX_4 "GetChanVar: source=%s\n", source); + } + + + /* Try and look up the source channel */ + + otherchan = ast_channel_walk_locked(NULL); + while(otherchan) { + + if (!strcasecmp(channel, otherchan->name)) + break; + ast_mutex_unlock(&otherchan->lock); + + otherchan = ast_channel_walk_locked(otherchan); + } + + + /* Check to see we have a valid pointer to the other channel */ + + if(!otherchan){ + ast_log(LOG_WARNING, "GetChanVar: Can't find channel: %s\n", channel); + if(option_verbose >= 4) + ast_verbose(VERBOSE_PREFIX_4 "GetChanVar: Can't find channel: %s\n", channel); + return 0; + } + + + + /* Try to find the variable in the other channel's namespace */ + + headp=&otherchan->varshead; + + + /* Test for builtin chan vars first */ + + pbx_check_builtin_chanvars(otherchan, &value, workspace, sizeof(workspace), source); + + /* Then check user-defined chan vars */ + + if(!value){ + AST_LIST_TRAVERSE(headp, variables, entries) { + if (!strcasecmp(source, ast_var_name(variables))){ + value = ast_var_value(variables); + break; + } + } + } + + /* Unlock the other channel's mutex */ + + ast_mutex_unlock(&otherchan->lock); + + + + if(!value){ + ast_log(LOG_WARNING, "GetChanVar: Can't find %s in %s's namespace\n", source, channel); + return 0; + } + + if(option_verbose >= 4) + ast_verbose(VERBOSE_PREFIX_4 "GetChanVar: value=%s\n", value); + + + /* Now, create a variable in our namespace with a value equal to the variable in the other channel's namespace */ + + pbx_builtin_setvar_helper(chan, dest, value); + + return 0; + +} + + + + static int pbx_builtin_noop(struct ast_channel *chan, void *data) { return 0;