Index: apps/app_dial.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_dial.c,v retrieving revision 1.87 diff -u -r1.87 app_dial.c --- apps/app_dial.c 17 Jul 2004 20:58:00 -0000 1.87 +++ apps/app_dial.c 19 Jul 2004 13:18:41 -0000 @@ -47,7 +47,7 @@ "Requests one or more channels and places specified outgoing calls on them.\n" "As soon as a channel answers, the Dial app will answer the originating\n" "channel (if it needs to be answered) and will bridge a call with the channel\n" -"which first answered. All other calls placed by the Dial app will be hung up\n" +"which first answered. All other calls placed by the Dial app will be hung up.\n" "If a timeout is not specified, the Dial application will wait indefinitely\n" "until either one of the called channels answers, the user hangs up, or all\n" "channels return busy or error. In general, the dialer will return 0 if it\n" @@ -436,6 +436,9 @@ char toast[80]; int play_to_caller=0,play_to_callee=0; int playargs=0, sentringing=0, moh=0; + char *varname; + int vartype; + int digit = 0; time_t start_time, answer_time, end_time; @@ -463,9 +466,12 @@ if (url) { *url = '\0'; url++; - ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url); + if (option_debug) + ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url); } else - ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n"); + if (option_debug) { + ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n"); + } /* /JDG */ } } @@ -727,27 +733,42 @@ continue; } } - /* If creating a SIP channel, look for a variable called */ - /* VXML_URL in the calling channel and copy it to the */ - /* new channel. */ - - /* Check for ALERT_INFO in the SetVar list. This is for */ - /* SIP distinctive ring as per the RFC. For Cisco 7960s, */ - /* SetVar(ALERT_INFO=) where x is an integer value 1-5. */ - /* However, the RFC says it should be a URL. -km- */ - headp=&chan->varshead; - AST_LIST_TRAVERSE(headp,current,entries) { - if (!strcasecmp(ast_var_name(current),"VXML_URL") || - !strcasecmp(ast_var_name(current), "ALERT_INFO") || - !strcasecmp(ast_var_name(current), "OSPTOKEN") || - !strcasecmp(ast_var_name(current), "OSPHANDLE")) - { - newvar=ast_var_assign(ast_var_name(current),ast_var_value(current)); - newheadp=&tmp->chan->varshead; - AST_LIST_INSERT_HEAD(newheadp,newvar,entries); + + /* Contitionally copy channel variables to the newly created channel */ + headp = &chan->varshead; + AST_LIST_TRAVERSE(headp, current, entries) { + varname = ast_var_full_name(current); + vartype = 0; + if (varname) { + if (varname[0] == '_') { + vartype = 1; + if (varname[1] == '_') + vartype = 2; + } + } + if (vartype == 1) { + newvar = ast_var_assign((char*)&(varname[1]), + ast_var_value(current)); + newheadp = &tmp->chan->varshead; + AST_LIST_INSERT_HEAD(newheadp, newvar, entries); + if (option_debug) + ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n", + ast_var_name(newvar)); + } else if (vartype == 2) { + newvar = ast_var_assign(ast_var_full_name(current), + ast_var_value(current)); + newheadp = &tmp->chan->varshead; + AST_LIST_INSERT_HEAD(newheadp, newvar, entries); + if (option_debug) + ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n", + ast_var_name(newvar)); + } else { + if (option_debug) + ast_log(LOG_DEBUG, "Not copying variable %s.\n", + ast_var_name(current)); } } - + tmp->chan->appl = "AppDial"; tmp->chan->data = "(Outgoing Line)"; tmp->chan->whentohangup = 0; Index: pbx.c =================================================================== RCS file: /usr/cvsroot/asterisk/pbx.c,v retrieving revision 1.139 diff -u -r1.139 pbx.c --- pbx.c 19 Jul 2004 00:30:39 -0000 1.139 +++ pbx.c 19 Jul 2004 13:18:49 -0000 @@ -55,6 +55,10 @@ #define EXT_DATA_SIZE 8192 #endif +#define VAR_NORMAL 1 +#define VAR_SOFTTRAN 2 +#define VAR_HARDTRAN 3 + struct ast_context; /* ast_exten: An extension */ @@ -166,7 +170,9 @@ static int pbx_builtin_saycharacters(struct ast_channel *, void *); static int pbx_builtin_sayphonetic(struct ast_channel *, void *); int pbx_builtin_setvar(struct ast_channel *, void *); +int pbx_builtin_setinheritvar(struct ast_channel *chan, void *data); void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value); +void pbx_builtin_setinheritvar_helper(struct ast_channel *chan, int type, char *name, char *value); char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name); static struct varshead globals; @@ -365,8 +371,16 @@ { "SetVar", pbx_builtin_setvar, "Set variable to value", - " Setvar(#n=value): Sets channel specific variable n to value" - }, + " SetVar(#n=value): Sets variable n to value" }, + + { "SetInheritVar", pbx_builtin_setinheritvar, + "Set the value and the inheritance type of a variable", + " SetInheritVar(once|forever|never, #n=value): Sets variable n to value. The \n" + "variable is marked as transferable, i.e. it will be transferred to the new \n" + "channel on a Dial(). The inheritance type can be 'once' (the variable \n" + "will be tranferred on the next Dial() only), 'forever' (the variable will be \n" + "transferred by all subsequent Dial() calls) or 'never' (the variable will not\n" + "be transferred on a subsequent Dial(), as in 'SetVar()'.\n" }, { "StripMSD", pbx_builtin_stripmsd, "Strip leading digits", @@ -4587,29 +4601,88 @@ return NULL; } -void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value) +void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value) { struct ast_var_t *newvariable; struct varshead *headp; + if (chan) - headp=&chan->varshead; + headp = &chan->varshead; else - headp=&globals; - - AST_LIST_TRAVERSE (headp,newvariable,entries) { - if (strcasecmp(ast_var_name(newvariable),name)==0) { + headp = &globals; + + if (name[0] == '_') { + ast_log(LOG_WARNING, "Invalid variable name '%s' (first char is '_').\n", name); + return; + } + + AST_LIST_TRAVERSE (headp, newvariable, entries) { + if (strcasecmp(ast_var_name(newvariable), name) == 0) { /* there is already such a variable, delete it */ - AST_LIST_REMOVE(headp,newvariable,ast_var_t,entries); + AST_LIST_REMOVE(headp, newvariable, ast_var_t, entries); ast_var_delete(newvariable); break; } } - + if (value) { if ((option_verbose > 1) && (headp == &globals)) - ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' to '%s'\n",name, value); - newvariable=ast_var_assign(name,value); - AST_LIST_INSERT_HEAD(headp,newvariable,entries); + ast_verbose(VERBOSE_PREFIX_3 "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_setinheritvar_helper(struct ast_channel *chan, int type, char *name, char *value) +{ + struct ast_var_t *newvariable; + struct varshead *headp; + char name_tmp[256] = {0}; + + if (chan) + headp = &chan->varshead; + else + headp = &globals; + + if (name[0] == '_') { + ast_log(LOG_WARNING, "Invalid variable name '%s' (first char is '_').\n", name); + return; + } + + switch (type) { + case VAR_NORMAL: + snprintf(name_tmp, sizeof(name_tmp) - 1, "%s", name); + break; + case VAR_SOFTTRAN: + snprintf(name_tmp, sizeof(name_tmp) - 1, "_%s", name); + break; + case VAR_HARDTRAN: + snprintf(name_tmp, sizeof(name_tmp) - 1, "__%s", name); + break; + default: + ast_log(LOG_WARNING, "Unknown variable type (%d).\n", type); + return; + } + + AST_LIST_TRAVERSE (headp, newvariable, entries) { + if (strcasecmp(ast_var_name(newvariable), name_tmp) == 0) { + /* there is already such a variable, delete it */ + AST_LIST_REMOVE(headp, newvariable, ast_var_t, entries); + ast_var_delete(newvariable); + break; + } + } + + if (value) { + if (option_verbose > 1) + if (headp == &globals) + ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' (type %d) to '%s'\n", + name, type, value); + else + ast_verbose(VERBOSE_PREFIX_3 "Setting variable '%s' (type %d) to '%s'\n", + name, type, value); + newvariable = ast_var_assign(name_tmp, value); + AST_LIST_INSERT_HEAD(headp, newvariable, entries); } } @@ -4618,41 +4691,85 @@ char *name; char *value; char *stringp=NULL; - + if (!data || 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(chan,name,value); - - return(0); + + stringp = data; + name = strsep(&stringp,"="); + value = strsep(&stringp,"\0"); + + pbx_builtin_setvar_helper(chan, name, value); + + return(0); } -static int pbx_builtin_setglobalvar(struct ast_channel *chan, void *data) +static int pbx_builtin_setinheritvar(struct ast_channel *chan, void *data) { + char *type; char *name; char *value; - char *stringp=NULL; - + int type_code; + char *stringp = NULL; + int i = 0; + if (!data || ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "Ignoring, since there is no type/variable to set\n"); + return 0; + } + + stringp = data; + type_code = VAR_NORMAL; + type = strsep(&stringp, "|"); + if (!stringp || ast_strlen_zero(stringp)) { 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); + if (!strcasecmp(type, "once")) { + type_code = VAR_SOFTTRAN; + } else if (!strcasecmp(type, "forever")) { + type_code = VAR_HARDTRAN; + } else if (!strcasecmp(type, "never")) { + type_code = VAR_NORMAL; + } else { + ast_log(LOG_WARNING, "Unknown variable type '%s'!\n", type); + return 0; + } + while (stringp[i] == ' ') i++; + stringp = &(stringp[i]); + name = strsep(&stringp, "="); + if (!stringp || ast_strlen_zero(stringp)) { + ast_log(LOG_WARNING, "Ignoring, since there is no value to set\n"); + return 0; + } + value = strsep(&stringp, "\0"); + + pbx_builtin_setinheritvar_helper(chan, type_code, name, value); + + return(0); } +static int pbx_builtin_setglobalvar(struct ast_channel *chan, void *data) +{ + char *name; + char *value; + char *stringp = NULL; + + if (!data || 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) { Index: chanvars.c =================================================================== RCS file: /usr/cvsroot/asterisk/chanvars.c,v retrieving revision 1.3 diff -u -r1.3 chanvars.c --- chanvars.c 16 May 2003 23:33:41 -0000 1.3 +++ chanvars.c 19 Jul 2004 13:18:50 -0000 @@ -70,6 +70,25 @@ char *ast_var_name(struct ast_var_t *var) { + char *name; + + if (var == NULL) + return NULL; + if (var->name == NULL) + return NULL; + /* Return the name without the initial underscores */ + if ((strlen(var->name) > 0) && (var->name[0] == '_')) { + if ((strlen(var->name) > 1) && (var->name[1] == '_')) + name = (char*)&(var->name[2]); + else + name = (char*)&(var->name[1]); + } else + name = var->name; + return name; +} + +char *ast_var_full_name(struct ast_var_t *var) +{ return (var != NULL ? var->name : NULL); } Index: include/asterisk/chanvars.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/chanvars.h,v retrieving revision 1.2 diff -u -r1.2 chanvars.h --- include/asterisk/chanvars.h 22 Oct 2002 15:31:47 -0000 1.2 +++ include/asterisk/chanvars.h 19 Jul 2004 13:18:50 -0000 @@ -25,6 +25,7 @@ struct ast_var_t *ast_var_assign(char *name,char *value); void ast_var_delete(struct ast_var_t *var); char *ast_var_name(struct ast_var_t *var); +char *ast_var_full_name(struct ast_var_t *var); char *ast_var_value(struct ast_var_t *var); #endif