aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_macro.c
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-12-17 21:18:57 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-12-17 21:18:57 +0000
commit39aab25c63d7c5827ef16ff6bc42ddd1045c3853 (patch)
tree7804244304303cacdf406e7bf0c85fd476786097 /apps/app_macro.c
parent59ba2416ac841b063f35c512cd2d7b7fcca09c3b (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.c76
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, &macro_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(&macro_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;
}