From 475abaedf1988f317b364862ff31bca5dcd4288f Mon Sep 17 00:00:00 2001 From: Tilghman Lesher Date: Wed, 17 Dec 2008 21:21:19 +0000 Subject: [PATCH] Merged revisions 165319 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r165319 | tilghman | 2008-12-17 15:18:57 -0600 (Wed, 17 Dec 2008) | 11 lines Merged revisions 165317 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r165317 | tilghman | 2008-12-17 15:14:37 -0600 (Wed, 17 Dec 2008) | 4 lines Reverse the fix from issue #6176 and add proper handling for that issue. (Closes issue #13962, closes issue #13363) Fixed by myself (license 14) ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@165321 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_macro.c | 74 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/apps/app_macro.c b/apps/app_macro.c index 68bbf16a4b..cdd6ef0b12 100644 --- a/apps/app_macro.c +++ b/apps/app_macro.c @@ -97,7 +97,32 @@ static char *if_synopsis = "Conditional Macro Implementation"; static char *exclusive_synopsis = "Exclusive Macro Implementation"; static char *exit_synopsis = "Exit From Macro"; +static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan); +struct ast_datastore_info macro_ds_info = { + .type = "MACRO", + .chan_fixup = macro_fixup, +}; + +static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan) +{ + int i; + char varname[10]; + pbx_builtin_setvar_helper(new_chan, "MACRO_DEPTH", "0"); + pbx_builtin_setvar_helper(new_chan, "MACRO_CONTEXT", NULL); + pbx_builtin_setvar_helper(new_chan, "MACRO_EXTEN", NULL); + pbx_builtin_setvar_helper(new_chan, "MACRO_PRIORITY", NULL); + pbx_builtin_setvar_helper(new_chan, "MACRO_OFFSET", NULL); + for (i = 1; i < 100; i++) { + snprintf(varname, sizeof(varname), "ARG%d", i); + while (pbx_builtin_getvar_helper(new_chan, varname)) { + /* Kill all levels of arguments */ + pbx_builtin_setvar_helper(new_chan, varname, NULL); + } + } +} + +>>>>>>> .merge-right.r165319 static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid) { struct ast_exten *e; @@ -152,18 +177,32 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) const char *inhangupc; int offset, depth = 0, maxdepth = 7; int setmacrocontext=0; - int autoloopflag, dead = 0, inhangup = 0; + int autoloopflag, inhangup = 0; char *save_macro_exten; char *save_macro_context; char *save_macro_priority; char *save_macro_offset; + struct ast_datastore *macro_store = ast_channel_datastore_find(chan, ¯o_ds_info, NULL); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Macro() requires arguments. See \"core show application macro\" for help.\n"); return -1; } + do { + if (macro_store) { + break; + } + if (!(macro_store = ast_channel_datastore_alloc(¯o_ds_info, NULL))) { + ast_log(LOG_WARNING, "Unable to allocate new datastore.\n"); + break; + } + /* Just the existence of this datastore is enough. */ + macro_store->inheritance = DATASTORE_INHERIT_FOREVER; + ast_channel_datastore_add(chan, macro_store); + } while (0); + /* does the user want a deeper rabbit hole? */ s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION"); if (s) @@ -307,12 +346,10 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) case AST_PBX_KEEPALIVE: ast_debug(2, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name); ast_verb(2, "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name); - dead = 1; goto out; default: ast_debug(2, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro); ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro); - dead = 1; goto out; } } @@ -385,31 +422,30 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) chan->priority++; } out: + + /* Don't let the channel change now. */ + ast_channel_lock(chan); + /* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */ snprintf(depthc, sizeof(depthc), "%d", depth); - if (!dead) { - pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); - ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); - } + pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); + ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); for (x = 1; x < argc; x++) { /* Restore old arguments and delete ours */ snprintf(varname, sizeof(varname), "ARG%d", x); if (oldargs[x]) { - if (!dead) - pbx_builtin_setvar_helper(chan, varname, oldargs[x]); + pbx_builtin_setvar_helper(chan, varname, oldargs[x]); ast_free(oldargs[x]); - } else if (!dead) { + } else { pbx_builtin_setvar_helper(chan, varname, NULL); } } /* Restore macro variables */ - if (!dead) { - pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten); - pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context); - pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority); - } + pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten); + pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context); + pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority); if (save_macro_exten) ast_free(save_macro_exten); if (save_macro_context) @@ -417,13 +453,13 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) if (save_macro_priority) ast_free(save_macro_priority); - if (!dead && setmacrocontext) { + if (setmacrocontext) { chan->macrocontext[0] = '\0'; chan->macroexten[0] = '\0'; chan->macropriority = 0; } - if (!dead && !strcasecmp(chan->context, fullmacro)) { + if (!strcasecmp(chan->context, fullmacro)) { /* If we're leaving the macro normally, restore original information */ chan->priority = oldpriority; ast_copy_string(chan->context, oldcontext, sizeof(chan->context)); @@ -443,8 +479,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) } } - if (!dead) - pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset); + pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset); if (save_macro_offset) ast_free(save_macro_offset); @@ -456,6 +491,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) res = 0; } } + ast_channel_unlock(chan); return res; }