158 #define MACRO_EXIT_RESULT 1024 160 static char *
app =
"Macro";
181 for (i = 1; i < 100; i++) {
182 snprintf(varname,
sizeof(varname),
"ARG%d", i);
191 int priority,
const char *callerid,
int iter,
int *had_error)
200 ast_log(
LOG_ERROR,
"Potential infinite loop detected, will not recurse further.\n");
244 char runningapp[80], runningdata[1024];
248 char oldexten[256]=
"";
249 int oldpriority, gosub_level = 0;
250 char pc[80], depthc[12];
252 const char *inhangupc;
253 int offset, depth = 0, maxdepth = 7;
254 int setmacrocontext=0;
255 int autoloopflag, inhangup = 0;
257 const char *my_macro_exten =
NULL;
258 char *save_macro_exten;
259 char *save_macro_context;
260 char *save_macro_priority;
261 char *save_macro_offset;
262 int save_in_subroutine;
264 int had_infinite_include_error = 0;
268 ast_log(
LOG_WARNING,
"Macro() requires arguments. See \"core show application macro\" for help.\n");
272 if (!deprecation_notice) {
273 deprecation_notice = 1;
274 ast_log(
LOG_WARNING,
"Macro() is deprecated and will be removed from a future version of Asterisk.\n");
294 sscanf(s,
"%30d", &maxdepth);
299 sscanf(s,
"%30d", &depth);
307 sscanf(inhangupc,
"%30d", &inhangup);
311 if (depth >= maxdepth) {
312 ast_log(
LOG_ERROR,
"Macro(): possible infinite loop detected. Returning early.\n");
315 snprintf(depthc,
sizeof(depthc),
"%d", depth + 1);
319 macro =
strsep(&rest,
",");
325 snprintf(fullmacro,
sizeof(fullmacro),
"macro-%s", macro);
339 my_macro_exten =
"s";
344 my_macro_exten =
"~~s~~";
348 if (!my_macro_exten) {
350 "Context '%s' for macro '%s' lacks 's' extension, priority 1\n",
357 ast_debug(1,
"Locking macrolock for '%s'\n", fullmacro);
391 snprintf(pc,
sizeof(pc),
"%d", oldpriority);
411 snprintf(varname,
sizeof(varname),
"ARG%d", argc);
427 runningapp[0] =
'\0';
428 runningdata[0] =
'\0';
442 0, &had_infinite_include_error);
463 if (((res >=
'0') && (res <=
'9')) || ((res >=
'A') && (res <=
'F')) ||
464 (res ==
'*') || (res ==
'#')) {
466 ast_debug(1,
"Oooh, got something to jump out with ('%c')!\n", res);
480 ast_debug(1,
"Executed application: %s\n", runningapp);
482 if (!strcasecmp(runningapp,
"GOSUB")) {
484 ast_debug(1,
"Incrementing gosub_level\n");
485 }
else if (!strcasecmp(runningapp,
"GOSUBIF")) {
486 char *
cond, *app_arg;
490 cond =
strsep(&app2,
"?");
491 app_arg =
strsep(&app2,
":");
495 ast_debug(1,
"Incrementing gosub_level\n");
500 ast_debug(1,
"Incrementing gosub_level\n");
503 }
else if (!strcasecmp(runningapp,
"RETURN")) {
505 ast_debug(1,
"Decrementing gosub_level\n");
506 }
else if (!strcasecmp(runningapp,
"STACKPOP")) {
508 ast_debug(1,
"Decrementing gosub_level\n");
509 }
else if (!strncasecmp(runningapp,
"EXEC", 4)) {
511 char *tmp2, *tmp3 =
NULL;
514 if (!strcasecmp(runningapp,
"EXECIF")) {
515 if ((tmp3 = strchr(tmp2,
'|'))) {
529 if (tmp3 && !strncasecmp(tmp3,
"GOSUB", 5)) {
531 ast_debug(1,
"Incrementing gosub_level\n");
532 }
else if (tmp3 && !strncasecmp(tmp3,
"RETURN", 6)) {
534 ast_debug(1,
"Decrementing gosub_level\n");
535 }
else if (tmp3 && !strncasecmp(tmp3,
"STACKPOP", 8)) {
537 ast_debug(1,
"Decrementing gosub_level\n");
548 ast_debug(1,
"Extension %s, macroexten %s, priority %d returned normally even though call was hung up\n",
562 snprintf(depthc,
sizeof(depthc),
"%d", depth);
567 for (x = 1; x < argc; x++) {
569 snprintf(varname,
sizeof(varname),
"ARG%d", x);
582 if (setmacrocontext) {
599 if (sscanf(offsets,
"%30d", &offset) == 1) {
614 ast_debug(1,
"Unlocking macrolock for '%s'\n", fullmacro);
616 ast_log(
LOG_ERROR,
"Failed to unlock macro '%s' - that isn't good\n", fullmacro);
643 if ((label_a = strchr(expr,
'?'))) {
646 if ((label_b = strchr(label_a,
':'))) {
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
ast_include: include= support in extensions.conf
int ast_unlock_context(struct ast_context *con)
static const struct ast_datastore_info macro_ds_info
#define ast_channel_lock(chan)
static char exten[AST_MAX_EXTENSION]
Main Channel structure associated with a channel.
int ast_get_extension_priority(struct ast_exten *exten)
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
#define MACRO_EXIT_RESULT
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
const char * ast_get_context_name(struct ast_context *con)
#define ast_set2_flag(p, value, flag)
#define ast_test_flag(p, flag)
static int macroif_exec(struct ast_channel *chan, const char *data)
int ast_context_lockmacro(const char *macrocontext)
locks the macrolock in the given context
static int load_module(void)
#define ast_set_flag(p, flag)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
void ast_channel_macrocontext_set(struct ast_channel *chan, const char *value)
const char * ast_get_extension_app(struct ast_exten *e)
static int unload_module(void)
int pbx_checkcondition(const char *condition)
Evaluate a condition.
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
struct ast_context * ast_walk_contexts(struct ast_context *con)
Structure for a data store type.
void * ast_get_extension_app_data(struct ast_exten *e)
int ast_rdlock_contexts(void)
Read locks the context list.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_unregister_application(const char *app)
Unregister an application.
int ast_channel_priority(const struct ast_channel *chan)
#define ast_verb(level,...)
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
static char * exclusive_app
void ast_channel_macropriority_set(struct ast_channel *chan, int value)
Configuration File Parser.
static void deprecation_notice(void)
static int macro_exit_exec(struct ast_channel *chan, const char *data)
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid, int iter, int *had_error)
#define ast_debug(level,...)
Log a DEBUG message.
struct ast_context * ast_context_find(const char *name)
Find a context.
General Asterisk PBX channel definitions.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
#define ast_strdupa(s)
duplicate a string in memory from the stack
const char * ast_get_extension_cidmatch(struct ast_exten *e)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
const char * ast_channel_exten(const struct ast_channel *chan)
Core PBX routines and definitions.
External configuration handlers (realtime and static configuration)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
int ast_context_includes_count(const struct ast_context *con)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
int ast_unlock_contexts(void)
Unlocks contexts.
#define AST_PBX_MAX_STACK
const char * ast_get_extension_name(struct ast_exten *exten)
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
#define ast_channel_unlock(chan)
static int macroexclusive_exec(struct ast_channel *chan, const char *data)
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
#define DATASTORE_INHERIT_FOREVER
void ast_channel_macroexten_set(struct ast_channel *chan, const char *value)
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
const char * ast_get_include_name(const struct ast_include *include)
char * strsep(char **str, const char *delims)
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
const char * ast_channel_name(const struct ast_channel *chan)
static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive)
const char * ast_channel_context(const struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
const char * ast_channel_macrocontext(const struct ast_channel *chan)
#define ASTERISK_GPL_KEY
The text the key() function should return.
void ast_channel_priority_set(struct ast_channel *chan, int value)
int ast_get_extension_matchcid(struct ast_exten *e)
Asterisk module definitions.
static int macro_exec(struct ast_channel *chan, const char *data)
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Extension Macros")
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
ast_context: An extension context - must remain in sync with fake_context
int ast_context_unlockmacro(const char *macrocontext)
Unlocks the macrolock in the given context.
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
const char * ast_channel_macroexten(const struct ast_channel *chan)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.