diff options
author | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-12-17 21:18:57 +0000 |
---|---|---|
committer | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-12-17 21:18:57 +0000 |
commit | 39aab25c63d7c5827ef16ff6bc42ddd1045c3853 (patch) | |
tree | 7804244304303cacdf406e7bf0c85fd476786097 /apps/app_macro.c | |
parent | 59ba2416ac841b063f35c512cd2d7b7fcca09c3b (diff) |
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: http://svn.digium.com/svn/asterisk/trunk@165319 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_macro.c')
-rw-r--r-- | apps/app_macro.c | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/apps/app_macro.c b/apps/app_macro.c index 6d9b412f9..73d62d9d7 100644 --- a/apps/app_macro.c +++ b/apps/app_macro.c @@ -155,6 +155,31 @@ static char *if_app = "MacroIf"; static char *exclusive_app = "MacroExclusive"; static char *exit_app = "MacroExit"; +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); + } + } +} + static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid) { struct ast_exten *e; @@ -209,18 +234,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? */ ast_channel_lock(chan); if ((s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION"))) { @@ -370,12 +409,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; } } @@ -448,31 +485,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) @@ -480,13 +516,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)); @@ -494,7 +530,6 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) /* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */ const char *offsets; ast_copy_string(chan->exten, oldexten, sizeof(chan->exten)); - ast_channel_lock(chan); if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) { /* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue normally if there is any problem */ @@ -504,12 +539,10 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) } } } - ast_channel_unlock(chan); } } - 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); @@ -521,6 +554,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) res = 0; } } + ast_channel_unlock(chan); return res; } |