diff options
author | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-12-17 21:22:38 +0000 |
---|---|---|
committer | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-12-17 21:22:38 +0000 |
commit | 1719f54a06233a2b8d507a8887bc0ee5359b8221 (patch) | |
tree | 75eaae7c15ccd2389c4753b3b3621181017d8ec4 /apps/app_macro.c | |
parent | ab6cd0d10fc2ea14b05fa47ce4c9778576337af5 (diff) |
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: http://svn.digium.com/svn/asterisk/branches/1.6.1@165323 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_macro.c')
-rw-r--r-- | apps/app_macro.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/apps/app_macro.c b/apps/app_macro.c index c21c4190e..2d5983000 100644 --- a/apps/app_macro.c +++ b/apps/app_macro.c @@ -97,6 +97,30 @@ 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); + } + } +} static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid) { @@ -152,18 +176,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"))) { @@ -313,12 +351,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; } } @@ -391,31 +427,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) @@ -423,13 +458,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)); @@ -437,7 +472,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 */ @@ -447,12 +481,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); @@ -464,6 +496,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive) res = 0; } } + ast_channel_unlock(chan); return res; } |