37 #include "asterisk/file.h"
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);
233 char runningapp[80], runningdata[1024];
234 char *oldargs[
MAX_ARGS + 1] = { NULL, };
237 char oldexten[256]=
"";
238 int oldpriority, gosub_level = 0;
239 char pc[80], depthc[12];
241 const char *inhangupc;
242 int offset, depth = 0, maxdepth = 7;
243 int setmacrocontext=0;
244 int autoloopflag, inhangup = 0;
245 struct ast_str *tmp_subst = NULL;
247 char *save_macro_exten;
248 char *save_macro_context;
249 char *save_macro_priority;
250 char *save_macro_offset;
254 ast_log(
LOG_WARNING,
"Macro() requires arguments. See \"core show application macro\" for help.\n");
274 sscanf(s,
"%30d", &maxdepth);
279 sscanf(s,
"%30d", &depth);
283 if (strcmp(chan->
exten,
"h") == 0)
287 sscanf(inhangupc,
"%30d", &inhangup);
291 if (depth >= maxdepth) {
292 ast_log(
LOG_ERROR,
"Macro(): possible infinite loop detected. Returning early.\n");
295 snprintf(depthc,
sizeof(depthc),
"%d", depth + 1);
299 macro =
strsep(&rest,
",");
305 snprintf(fullmacro,
sizeof(fullmacro),
"macro-%s", macro);
311 ast_log(
LOG_WARNING,
"Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
317 ast_debug(1,
"Locking macrolock for '%s'\n", fullmacro);
350 snprintf(pc,
sizeof(pc),
"%d", oldpriority);
359 chan->
exten[0] =
's';
360 chan->
exten[1] =
'\0';
369 snprintf(varname,
sizeof(varname),
"ARG%d", argc);
384 runningapp[0] =
'\0';
385 runningdata[0] =
'\0';
418 if (((res >=
'0') && (res <=
'9')) || ((res >=
'A') && (res <=
'F')) ||
419 (res ==
'*') || (res ==
'#')) {
421 ast_debug(1,
"Oooh, got something to jump out with ('%c')!\n", res);
435 ast_debug(1,
"Executed application: %s\n", runningapp);
437 if (!strcasecmp(runningapp,
"GOSUB")) {
439 ast_debug(1,
"Incrementing gosub_level\n");
440 }
else if (!strcasecmp(runningapp,
"GOSUBIF")) {
441 char *
cond, *app_arg;
445 cond =
strsep(&app2,
"?");
446 app_arg =
strsep(&app2,
":");
450 ast_debug(1,
"Incrementing gosub_level\n");
455 ast_debug(1,
"Incrementing gosub_level\n");
458 }
else if (!strcasecmp(runningapp,
"RETURN")) {
460 ast_debug(1,
"Decrementing gosub_level\n");
461 }
else if (!strcasecmp(runningapp,
"STACKPOP")) {
463 ast_debug(1,
"Decrementing gosub_level\n");
464 }
else if (!strncasecmp(runningapp,
"EXEC", 4)) {
466 char *tmp2, *tmp3 = NULL;
469 if (!strcasecmp(runningapp,
"EXECIF")) {
470 if ((tmp3 = strchr(tmp2,
'|'))) {
484 if (tmp3 && !strncasecmp(tmp3,
"GOSUB", 5)) {
486 ast_debug(1,
"Incrementing gosub_level\n");
487 }
else if (tmp3 && !strncasecmp(tmp3,
"RETURN", 6)) {
489 ast_debug(1,
"Decrementing gosub_level\n");
490 }
else if (tmp3 && !strncasecmp(tmp3,
"STACKPOP", 8)) {
492 ast_debug(1,
"Decrementing gosub_level\n");
496 if (gosub_level == 0 && strcasecmp(chan->
context, fullmacro)) {
497 ast_verb(2,
"Channel '%s' jumping out of macro '%s'\n", chan->
name, macro);
514 snprintf(depthc,
sizeof(depthc),
"%d", depth);
518 for (x = 1; x < argc; x++) {
520 snprintf(varname,
sizeof(varname),
"ARG%d", x);
533 if (save_macro_exten)
535 if (save_macro_context)
537 if (save_macro_priority)
540 if (setmacrocontext) {
546 if (!strcasecmp(chan->
context, fullmacro)) {
556 if (sscanf(offsets,
"%30d", &offset) == 1) {
567 if (save_macro_offset)
572 ast_debug(1,
"Unlocking macrolock for '%s'\n", fullmacro);
574 ast_log(
LOG_ERROR,
"Failed to unlock macro '%s' - that isn't good\n", fullmacro);
596 char *expr = NULL, *label_a = NULL, *label_b = NULL;
601 if ((label_a = strchr(expr,
'?'))) {
604 if ((label_b = strchr(label_a,
':'))) {
struct ast_include * ast_walk_context_includes(struct ast_context *con, struct ast_include *inc)
ast_include: include= support in extensions.conf
int ast_unlock_context(struct ast_context *con)
#define ast_channel_lock(chan)
static char exten[AST_MAX_EXTENSION]
Main Channel structure associated with a channel.
char * str
Subscriber phone number (Malloced)
int ast_get_extension_priority(struct ast_exten *exten)
#define AST_MODULE_INFO_STANDARD(keystr, desc)
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
struct ast_party_caller caller
Channel Caller ID information.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
char * strsep(char **str, const char *delims)
static struct ast_datastore_info macro_ds_info
#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 given context
static int load_module(void)
char context[AST_MAX_CONTEXT]
#define ast_set_flag(p, flag)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
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)
Structure for a data store type.
Configuration File Parser.
void * ast_get_extension_app_data(struct ast_exten *e)
int ast_rdlock_contexts(void)
Read locks the context list.
struct ast_str * ast_str_create(size_t init_len)
Create a malloc'ed dynamic length string.
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.
int ast_unregister_application(const char *app)
Unregister an application.
#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.
static char * exclusive_app
struct ast_party_id id
Caller party ID.
const char * ast_get_include_name(struct ast_include *include)
static int macro_exit_exec(struct ast_channel *chan, const char *data)
#define ast_debug(level,...)
Log a DEBUG message.
General Asterisk PBX channel definitions.
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
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.
struct ast_context * ast_walk_contexts(struct ast_context *con)
const char * ast_get_context_name(struct ast_context *con)
Core PBX routines and definitions.
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.
#define ast_strdupa(s)
duplicate a string in memory from the stack
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
int ast_unlock_contexts(void)
Unlocks contexts.
const ast_string_field name
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
const char * ast_get_extension_name(struct ast_exten *exten)
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
#define ast_channel_unlock(chan)
static int macroexclusive_exec(struct ast_channel *chan, const char *data)
char macrocontext[AST_MAX_CONTEXT]
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
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)
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...
char macroexten[AST_MAX_EXTENSION]
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive)
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_get_extension_matchcid(struct ast_exten *e)
Asterisk module definitions.
static int macro_exec(struct ast_channel *chan, const char *data)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
ast_context: An extension context
unsigned char valid
TRUE if the number information is valid/present.
int ast_context_unlockmacro(const char *macrocontext)
Unlocks the macrolock in the given context.
struct ast_context * ast_context_find(const char *name)
Find a context.
char exten[AST_MAX_EXTENSION]
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
struct ast_party_number number
Subscriber phone number.