Fix macro formatting (bug #3275)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4710 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2005-01-08 18:45:13 +00:00
parent 51cab9e7cc
commit 3a49a959ca

View File

@@ -36,20 +36,21 @@ static char *tdesc = "Extension Macros";
static char *descrip = static char *descrip =
" Macro(macroname|arg1|arg2...): Executes a macro using the context\n" " Macro(macroname|arg1|arg2...): Executes a macro using the context\n"
"'macro-<macroname>', jumping to the 's' extension of that context and\n" "'macro-<macroname>', jumping to the 's' extension of that context and\n"
"executing each step, then returning when the steps end. The calling\n" "executing each step, then returning when the steps end. \n"
"extension, context, and priority are stored in ${MACRO_EXTEN}, \n" "The calling extension, context, and priority are stored in ${MACRO_EXTEN}, \n"
"${MACRO_CONTEXT} and ${MACRO_PRIORITY} respectively. Arguments become\n" "${MACRO_CONTEXT} and ${MACRO_PRIORITY} respectively. Arguments become\n"
"${ARG1}, ${ARG2}, etc in the macro context. Macro returns -1 if\n" "${ARG1}, ${ARG2}, etc in the macro context.\n"
"any step in the macro returns -1, and 0 otherwise. If you Goto out\n" "If you Goto out of the Macro context, the Macro will terminate and control\n"
"of the Macro context, the Macro will terminate and control will be return\n" "will be returned at the location of the Goto.\n"
"at the location of the Goto. Otherwise if ${MACRO_OFFSET} is set at\n" "Macro returns -1 if any step in the macro returns -1, and 0 otherwise.\n"
"termination, Macro will attempt to continue at priority\n" "If ${MACRO_OFFSET} is set at termination, Macro will attempt to continue\n"
"MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.\n"; "at priority MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.\n";
static char *if_descrip = static char *if_descrip =
" MacroIf(<expr>?label_a[|arg1][:label_b[|arg1]]):\n" " MacroIf(<expr>?macroname_a[|arg1][:macroname_b[|arg1]])\n"
"Executes macro defined in <label_a> if <expr> is true\n" "Executes macro defined in <macroname_a> if <expr> is true\n"
"(otherwise <label_b> if provided)\n"; "(otherwise <macroname_b> if provided)\n"
"Arguments and return values as in application macro()\n";
static char *exit_descrip = static char *exit_descrip =
" MacroExit():\n" " MacroExit():\n"
@@ -72,184 +73,192 @@ LOCAL_USER_DECL;
static int macro_exec(struct ast_channel *chan, void *data) static int macro_exec(struct ast_channel *chan, void *data)
{ {
char *tmp; char *tmp;
char *cur, *rest; char *cur, *rest;
char *macro; char *macro;
char fullmacro[80]; char fullmacro[80];
char varname[80]; char varname[80];
char *oldargs[MAX_ARGS + 1] = { NULL, }; char *oldargs[MAX_ARGS + 1] = { NULL, };
int argc, x; int argc, x;
int res=0; int res=0;
char oldexten[256]=""; char oldexten[256]="";
int oldpriority; int oldpriority;
char pc[80]; char pc[80];
char oldcontext[256] = ""; char oldcontext[256] = "";
char *offsets; char *offsets;
int offset; int offset;
int setmacrocontext=0; int setmacrocontext=0;
char *save_macro_exten; char *save_macro_exten;
char *save_macro_context; char *save_macro_context;
char *save_macro_priority; char *save_macro_priority;
char *save_macro_offset; char *save_macro_offset;
struct localuser *u; struct localuser *u;
if (!data || ast_strlen_zero(data)) { if (!data || ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Invalid Macro incantation\n"); ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n");
return 0; return 0;
} }
tmp = ast_strdupa((char *) data); tmp = ast_strdupa((char *) data);
rest = tmp; rest = tmp;
macro = strsep(&rest, "|"); macro = strsep(&rest, "|");
if (!macro || ast_strlen_zero(macro)) { if (!macro || ast_strlen_zero(macro)) {
ast_log(LOG_WARNING, "Invalid macro name specified\n"); ast_log(LOG_WARNING, "Invalid macro name specified\n");
return 0; return 0;
} }
snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro); snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) { if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) {
if (!ast_context_find(fullmacro)) if (!ast_context_find(fullmacro))
ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro); ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
else else
ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro); ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
return 0; return 0;
} }
LOCAL_USER_ADD(u); LOCAL_USER_ADD(u);
/* Save old info */ /* Save old info */
oldpriority = chan->priority; oldpriority = chan->priority;
strncpy(oldexten, chan->exten, sizeof(oldexten) - 1); strncpy(oldexten, chan->exten, sizeof(oldexten) - 1);
strncpy(oldcontext, chan->context, sizeof(oldcontext) - 1); strncpy(oldcontext, chan->context, sizeof(oldcontext) - 1);
if (ast_strlen_zero(chan->macrocontext)) { if (ast_strlen_zero(chan->macrocontext)) {
strncpy(chan->macrocontext, chan->context, sizeof(chan->macrocontext) - 1); strncpy(chan->macrocontext, chan->context, sizeof(chan->macrocontext) - 1);
strncpy(chan->macroexten, chan->exten, sizeof(chan->macroexten) - 1); strncpy(chan->macroexten, chan->exten, sizeof(chan->macroexten) - 1);
chan->macropriority = chan->priority; chan->macropriority = chan->priority;
setmacrocontext=1; setmacrocontext=1;
} }
argc = 1; argc = 1;
/* Save old macro variables */ /* Save old macro variables */
save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN"); save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN");
if (save_macro_exten) save_macro_exten = strdup(save_macro_exten); if (save_macro_exten)
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten); save_macro_exten = strdup(save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);
save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"); save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT");
if (save_macro_context) save_macro_context = strdup(save_macro_context); if (save_macro_context)
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext); save_macro_context = strdup(save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);
save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY"); save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY");
if (save_macro_priority) save_macro_priority = strdup(save_macro_priority); if (save_macro_priority)
snprintf(pc, sizeof(pc), "%d", oldpriority); save_macro_priority = strdup(save_macro_priority);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc); snprintf(pc, sizeof(pc), "%d", oldpriority);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"); save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET");
if (save_macro_offset) save_macro_offset = strdup(save_macro_offset); if (save_macro_offset)
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL); save_macro_offset = strdup(save_macro_offset);
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
/* Setup environment for new run */ /* Setup environment for new run */
chan->exten[0] = 's'; chan->exten[0] = 's';
chan->exten[1] = '\0'; chan->exten[1] = '\0';
strncpy(chan->context, fullmacro, sizeof(chan->context) - 1); strncpy(chan->context, fullmacro, sizeof(chan->context) - 1);
chan->priority = 1; chan->priority = 1;
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) { while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
/* Save copy of old arguments if we're overwriting some, otherwise /* Save copy of old arguments if we're overwriting some, otherwise
let them pass through to the other macro */ let them pass through to the other macro */
snprintf(varname, sizeof(varname), "ARG%d", argc); snprintf(varname, sizeof(varname), "ARG%d", argc);
oldargs[argc] = pbx_builtin_getvar_helper(chan, varname); oldargs[argc] = pbx_builtin_getvar_helper(chan, varname);
if (oldargs[argc]) if (oldargs[argc])
oldargs[argc] = strdup(oldargs[argc]); oldargs[argc] = strdup(oldargs[argc]);
pbx_builtin_setvar_helper(chan, varname, cur); pbx_builtin_setvar_helper(chan, varname, cur);
argc++; argc++;
} }
while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) { if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) {
/* Something bad happened, or a hangup has been requested. */ /* Something bad happened, or a hangup has been requested. */
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) || if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
(res == '*') || (res == '#')) { (res == '*') || (res == '#')) {
/* Just return result as to the previous application as if it had been dialed */ /* Just return result as to the previous application as if it had been dialed */
ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
break;
}
switch(res) {
case MACRO_EXIT_RESULT:
res = 0;
goto out;
case AST_PBX_KEEPALIVE:
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
goto out;
break;
default:
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
goto out;
}
}
if (strcasecmp(chan->context, fullmacro)) {
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
break; break;
} }
switch(res) { /* don't stop executing extensions when we're in "h" */
case MACRO_EXIT_RESULT: if (chan->_softhangup && strcasecmp(oldexten,"h")) {
res = 0; ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
goto out; chan->exten, chan->priority);
case AST_PBX_KEEPALIVE:
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
goto out;
break;
default:
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
goto out; goto out;
} }
} chan->priority++;
if (strcasecmp(chan->context, fullmacro)) { }
if (option_verbose > 1) out:
ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro); for (x=1; x<argc; x++) {
break; /* Restore old arguments and delete ours */
} snprintf(varname, sizeof(varname), "ARG%d", x);
/* don't stop executing extensions when we're in "h" */ if (oldargs[x]) {
if (chan->_softhangup && strcasecmp(oldexten,"h")) { pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", free(oldargs[x]);
chan->exten, chan->priority); } else {
goto out; pbx_builtin_setvar_helper(chan, varname, NULL);
} }
chan->priority++; }
}
out:
for (x=1;x<argc;x++) {
/* Restore old arguments and delete ours */
snprintf(varname, sizeof(varname), "ARG%d", x);
if (oldargs[x]) {
pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
free(oldargs[x]);
} else {
pbx_builtin_setvar_helper(chan, varname, NULL);
}
}
/* Restore macro variables */ /* Restore macro variables */
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten); pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
if (save_macro_exten) free(save_macro_exten); if (save_macro_exten)
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context); free(save_macro_exten);
if (save_macro_context) free(save_macro_context); pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority); if (save_macro_context)
if (save_macro_priority) free(save_macro_priority); free(save_macro_context);
if (setmacrocontext) { pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
chan->macrocontext[0] = '\0'; if (save_macro_priority)
chan->macroexten[0] = '\0'; free(save_macro_priority);
chan->macropriority = 0; if (setmacrocontext) {
} chan->macrocontext[0] = '\0';
chan->macroexten[0] = '\0';
chan->macropriority = 0;
}
if (!strcasecmp(chan->context, fullmacro)) { if (!strcasecmp(chan->context, fullmacro)) {
/* If we're leaving the macro normally, restore original information */ /* If we're leaving the macro normally, restore original information */
chan->priority = oldpriority; chan->priority = oldpriority;
strncpy(chan->context, oldcontext, sizeof(chan->context) - 1); strncpy(chan->context, oldcontext, sizeof(chan->context) - 1);
if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) { if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */ /* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
strncpy(chan->exten, oldexten, sizeof(chan->exten) - 1); strncpy(chan->exten, oldexten, sizeof(chan->exten) - 1);
if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) { 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 /* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
normally if there is any problem */ normally if there is any problem */
if (sscanf(offsets, "%d", &offset) == 1) { if (sscanf(offsets, "%d", &offset) == 1) {
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) { if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) {
chan->priority += offset; chan->priority += offset;
}
} }
} }
} }
} }
}
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset); pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
if (save_macro_offset) free(save_macro_offset); if (save_macro_offset)
LOCAL_USER_REMOVE(u); free(save_macro_offset);
return res; LOCAL_USER_REMOVE(u);
return res;
} }
static int macroif_exec(struct ast_channel *chan, void *data) static int macroif_exec(struct ast_channel *chan, void *data)
@@ -286,6 +295,7 @@ int unload_module(void)
{ {
STANDARD_HANGUP_LOCALUSERS; STANDARD_HANGUP_LOCALUSERS;
ast_unregister_application(if_app); ast_unregister_application(if_app);
ast_unregister_application(exit_app);
return ast_unregister_application(app); return ast_unregister_application(app);
} }