Wed Jan 8 2020 09:49:53

Asterisk developer's documentation


app_macro.c File Reference

Dial plan macro Implementation. More...

#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"

Go to the source code of this file.

Macros

#define MACRO_EXIT_RESULT   1024
 
#define MAX_ARGS   80
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int _macro_exec (struct ast_channel *chan, const char *data, int exclusive)
 
static struct ast_extenfind_matching_priority (struct ast_context *c, const char *exten, int priority, const char *callerid)
 
static int load_module (void)
 
static int macro_exec (struct ast_channel *chan, const char *data)
 
static int macro_exit_exec (struct ast_channel *chan, const char *data)
 
static void macro_fixup (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 
static int macroexclusive_exec (struct ast_channel *chan, const char *data)
 
static int macroif_exec (struct ast_channel *chan, const char *data)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Macros" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static char * app = "Macro"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static char * exclusive_app = "MacroExclusive"
 
static char * exit_app = "MacroExit"
 
static char * if_app = "MacroIf"
 
static struct ast_datastore_info macro_ds_info
 

Detailed Description

Dial plan macro Implementation.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file app_macro.c.

Macro Definition Documentation

#define MACRO_EXIT_RESULT   1024

Definition at line 158 of file app_macro.c.

Referenced by _macro_exec(), and macro_exit_exec().

#define MAX_ARGS   80

Definition at line 155 of file app_macro.c.

Referenced by _macro_exec().

Function Documentation

static void __reg_module ( void  )
static

Definition at line 647 of file app_macro.c.

static void __unreg_module ( void  )
static

Definition at line 647 of file app_macro.c.

static int _macro_exec ( struct ast_channel chan,
const char *  data,
int  exclusive 
)
static

Definition at line 225 of file app_macro.c.

References app2, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_copy_string(), ast_datastore_alloc(), ast_debug, ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_free, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_log(), AST_MAX_CONTEXT, ast_rdlock_context(), ast_rdlock_contexts(), ast_set2_flag, ast_set_flag, ast_spawn_extension(), ast_str_buffer(), ast_str_create(), ast_str_substitute_variables(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_unlock_context(), ast_unlock_contexts(), ast_verb, ast_walk_contexts(), ast_channel::caller, cond, ast_channel::context, DATASTORE_INHERIT_FOREVER, ast_channel::exten, find_matching_priority(), ast_party_caller::id, ast_datastore::inheritance, LOG_ERROR, LOG_WARNING, MACRO_EXIT_RESULT, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, MAX_ARGS, ast_channel::name, ast_party_id::number, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), ast_channel::priority, S_COR, ast_party_number::str, strsep(), and ast_party_number::valid.

Referenced by macro_exec(), and macroexclusive_exec().

226 {
227  const char *s;
228  char *tmp;
229  char *cur, *rest;
230  char *macro;
231  char fullmacro[80];
232  char varname[80];
233  char runningapp[80], runningdata[1024];
234  char *oldargs[MAX_ARGS + 1] = { NULL, };
235  int argc, x;
236  int res=0;
237  char oldexten[256]="";
238  int oldpriority, gosub_level = 0;
239  char pc[80], depthc[12];
240  char oldcontext[AST_MAX_CONTEXT] = "";
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;
246 
247  char *save_macro_exten;
248  char *save_macro_context;
249  char *save_macro_priority;
250  char *save_macro_offset;
251  struct ast_datastore *macro_store = ast_channel_datastore_find(chan, &macro_ds_info, NULL);
252 
253  if (ast_strlen_zero(data)) {
254  ast_log(LOG_WARNING, "Macro() requires arguments. See \"core show application macro\" for help.\n");
255  return -1;
256  }
257 
258  do {
259  if (macro_store) {
260  break;
261  }
262  if (!(macro_store = ast_datastore_alloc(&macro_ds_info, NULL))) {
263  ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
264  break;
265  }
266  /* Just the existence of this datastore is enough. */
267  macro_store->inheritance = DATASTORE_INHERIT_FOREVER;
268  ast_channel_datastore_add(chan, macro_store);
269  } while (0);
270 
271  /* does the user want a deeper rabbit hole? */
272  ast_channel_lock(chan);
273  if ((s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION"))) {
274  sscanf(s, "%30d", &maxdepth);
275  }
276 
277  /* Count how many levels deep the rabbit hole goes */
278  if ((s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH"))) {
279  sscanf(s, "%30d", &depth);
280  }
281 
282  /* Used for detecting whether to return when a Macro is called from another Macro after hangup */
283  if (strcmp(chan->exten, "h") == 0)
284  pbx_builtin_setvar_helper(chan, "MACRO_IN_HANGUP", "1");
285 
286  if ((inhangupc = pbx_builtin_getvar_helper(chan, "MACRO_IN_HANGUP"))) {
287  sscanf(inhangupc, "%30d", &inhangup);
288  }
289  ast_channel_unlock(chan);
290 
291  if (depth >= maxdepth) {
292  ast_log(LOG_ERROR, "Macro(): possible infinite loop detected. Returning early.\n");
293  return 0;
294  }
295  snprintf(depthc, sizeof(depthc), "%d", depth + 1);
296 
297  tmp = ast_strdupa(data);
298  rest = tmp;
299  macro = strsep(&rest, ",");
300  if (ast_strlen_zero(macro)) {
301  ast_log(LOG_WARNING, "Invalid macro name specified\n");
302  return 0;
303  }
304 
305  snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
306  if (!ast_exists_extension(chan, fullmacro, "s", 1,
307  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
308  if (!ast_context_find(fullmacro))
309  ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
310  else
311  ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
312  return 0;
313  }
314 
315  /* If we are to run the macro exclusively, take the mutex */
316  if (exclusive) {
317  ast_debug(1, "Locking macrolock for '%s'\n", fullmacro);
318  ast_autoservice_start(chan);
319  if (ast_context_lockmacro(fullmacro)) {
320  ast_log(LOG_WARNING, "Failed to lock macro '%s' as in-use\n", fullmacro);
321  ast_autoservice_stop(chan);
322  return 0;
323  }
324  ast_autoservice_stop(chan);
325  }
326 
327  if (!(tmp_subst = ast_str_create(16))) {
328  return -1;
329  }
330 
331  /* Save old info */
332  oldpriority = chan->priority;
333  ast_copy_string(oldexten, chan->exten, sizeof(oldexten));
334  ast_copy_string(oldcontext, chan->context, sizeof(oldcontext));
335  if (ast_strlen_zero(chan->macrocontext)) {
336  ast_copy_string(chan->macrocontext, chan->context, sizeof(chan->macrocontext));
337  ast_copy_string(chan->macroexten, chan->exten, sizeof(chan->macroexten));
338  chan->macropriority = chan->priority;
339  setmacrocontext=1;
340  }
341  argc = 1;
342  /* Save old macro variables */
343  save_macro_exten = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_EXTEN"));
344  pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);
345 
346  save_macro_context = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"));
347  pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);
348 
349  save_macro_priority = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY"));
350  snprintf(pc, sizeof(pc), "%d", oldpriority);
351  pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
352 
353  save_macro_offset = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"));
354  pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
355 
356  pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
357 
358  /* Setup environment for new run */
359  chan->exten[0] = 's';
360  chan->exten[1] = '\0';
361  ast_copy_string(chan->context, fullmacro, sizeof(chan->context));
362  chan->priority = 1;
363 
364  ast_channel_lock(chan);
365  while((cur = strsep(&rest, ",")) && (argc < MAX_ARGS)) {
366  const char *argp;
367  /* Save copy of old arguments if we're overwriting some, otherwise
368  let them pass through to the other macro */
369  snprintf(varname, sizeof(varname), "ARG%d", argc);
370  if ((argp = pbx_builtin_getvar_helper(chan, varname))) {
371  oldargs[argc] = ast_strdup(argp);
372  }
373  pbx_builtin_setvar_helper(chan, varname, cur);
374  argc++;
375  }
376  ast_channel_unlock(chan);
377  autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
379  while (ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
380  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
381  struct ast_context *c;
382  struct ast_exten *e;
383  int foundx;
384  runningapp[0] = '\0';
385  runningdata[0] = '\0';
386 
387  /* What application will execute? */
388  if (ast_rdlock_contexts()) {
389  ast_log(LOG_WARNING, "Failed to lock contexts list\n");
390  } else {
391  for (c = ast_walk_contexts(NULL), e = NULL; c; c = ast_walk_contexts(c)) {
392  if (!strcmp(ast_get_context_name(c), chan->context)) {
393  if (ast_rdlock_context(c)) {
394  ast_log(LOG_WARNING, "Unable to lock context?\n");
395  } else {
396  e = find_matching_priority(c, chan->exten, chan->priority,
397  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
398  if (e) { /* This will only be undefined for pbx_realtime, which is majorly broken. */
399  ast_copy_string(runningapp, ast_get_extension_app(e), sizeof(runningapp));
400  ast_copy_string(runningdata, ast_get_extension_app_data(e), sizeof(runningdata));
401  }
403  }
404  break;
405  }
406  }
407  }
409 
410  /* Reset the macro depth, if it was changed in the last iteration */
411  pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
412 
413  res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority,
414  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
415  &foundx, 1);
416  if (res) {
417  /* Something bad happened, or a hangup has been requested. */
418  if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
419  (res == '*') || (res == '#')) {
420  /* Just return result as to the previous application as if it had been dialed */
421  ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
422  break;
423  }
424  switch(res) {
425  case MACRO_EXIT_RESULT:
426  res = 0;
427  goto out;
428  default:
429  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);
430  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);
431  goto out;
432  }
433  }
434 
435  ast_debug(1, "Executed application: %s\n", runningapp);
436 
437  if (!strcasecmp(runningapp, "GOSUB")) {
438  gosub_level++;
439  ast_debug(1, "Incrementing gosub_level\n");
440  } else if (!strcasecmp(runningapp, "GOSUBIF")) {
441  char *cond, *app_arg;
442  char *app2;
443  ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata);
444  app2 = ast_str_buffer(tmp_subst);
445  cond = strsep(&app2, "?");
446  app_arg = strsep(&app2, ":");
447  if (pbx_checkcondition(cond)) {
448  if (!ast_strlen_zero(app_arg)) {
449  gosub_level++;
450  ast_debug(1, "Incrementing gosub_level\n");
451  }
452  } else {
453  if (!ast_strlen_zero(app2)) {
454  gosub_level++;
455  ast_debug(1, "Incrementing gosub_level\n");
456  }
457  }
458  } else if (!strcasecmp(runningapp, "RETURN")) {
459  gosub_level--;
460  ast_debug(1, "Decrementing gosub_level\n");
461  } else if (!strcasecmp(runningapp, "STACKPOP")) {
462  gosub_level--;
463  ast_debug(1, "Decrementing gosub_level\n");
464  } else if (!strncasecmp(runningapp, "EXEC", 4)) {
465  /* Must evaluate args to find actual app */
466  char *tmp2, *tmp3 = NULL;
467  ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata);
468  tmp2 = ast_str_buffer(tmp_subst);
469  if (!strcasecmp(runningapp, "EXECIF")) {
470  if ((tmp3 = strchr(tmp2, '|'))) {
471  *tmp3++ = '\0';
472  }
473  if (!pbx_checkcondition(tmp2)) {
474  tmp3 = NULL;
475  }
476  } else {
477  tmp3 = tmp2;
478  }
479 
480  if (tmp3) {
481  ast_debug(1, "Last app: %s\n", tmp3);
482  }
483 
484  if (tmp3 && !strncasecmp(tmp3, "GOSUB", 5)) {
485  gosub_level++;
486  ast_debug(1, "Incrementing gosub_level\n");
487  } else if (tmp3 && !strncasecmp(tmp3, "RETURN", 6)) {
488  gosub_level--;
489  ast_debug(1, "Decrementing gosub_level\n");
490  } else if (tmp3 && !strncasecmp(tmp3, "STACKPOP", 8)) {
491  gosub_level--;
492  ast_debug(1, "Decrementing gosub_level\n");
493  }
494  }
495 
496  if (gosub_level == 0 && strcasecmp(chan->context, fullmacro)) {
497  ast_verb(2, "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
498  break;
499  }
500 
501  /* don't stop executing extensions when we're in "h" */
502  if (ast_check_hangup(chan) && !inhangup) {
503  ast_debug(1, "Extension %s, macroexten %s, priority %d returned normally even though call was hung up\n", chan->exten, chan->macroexten, chan->priority);
504  goto out;
505  }
506  chan->priority++;
507  }
508  out:
509 
510  /* Don't let the channel change now. */
511  ast_channel_lock(chan);
512 
513  /* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */
514  snprintf(depthc, sizeof(depthc), "%d", depth);
515  pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
516  ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
517 
518  for (x = 1; x < argc; x++) {
519  /* Restore old arguments and delete ours */
520  snprintf(varname, sizeof(varname), "ARG%d", x);
521  if (oldargs[x]) {
522  pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
523  ast_free(oldargs[x]);
524  } else {
525  pbx_builtin_setvar_helper(chan, varname, NULL);
526  }
527  }
528 
529  /* Restore macro variables */
530  pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
531  pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
532  pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
533  if (save_macro_exten)
534  ast_free(save_macro_exten);
535  if (save_macro_context)
536  ast_free(save_macro_context);
537  if (save_macro_priority)
538  ast_free(save_macro_priority);
539 
540  if (setmacrocontext) {
541  chan->macrocontext[0] = '\0';
542  chan->macroexten[0] = '\0';
543  chan->macropriority = 0;
544  }
545 
546  if (!strcasecmp(chan->context, fullmacro)) {
547  const char *offsets;
548 
549  /* If we're leaving the macro normally, restore original information */
550  chan->priority = oldpriority;
551  ast_copy_string(chan->context, oldcontext, sizeof(chan->context));
552  ast_copy_string(chan->exten, oldexten, sizeof(chan->exten));
553  if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
554  /* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
555  normally if there is any problem */
556  if (sscanf(offsets, "%30d", &offset) == 1) {
557  if (ast_exists_extension(chan, chan->context, chan->exten,
558  chan->priority + offset + 1,
559  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
560  chan->priority += offset;
561  }
562  }
563  }
564  }
565 
566  pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
567  if (save_macro_offset)
568  ast_free(save_macro_offset);
569 
570  /* Unlock the macro */
571  if (exclusive) {
572  ast_debug(1, "Unlocking macrolock for '%s'\n", fullmacro);
573  if (ast_context_unlockmacro(fullmacro)) {
574  ast_log(LOG_ERROR, "Failed to unlock macro '%s' - that isn't good\n", fullmacro);
575  res = 0;
576  }
577  }
578  ast_channel_unlock(chan);
579  ast_free(tmp_subst);
580 
581  return res;
582 }
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:11065
#define ast_channel_lock(chan)
Definition: channel.h:2466
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
#define MACRO_EXIT_RESULT
Definition: app_macro.c:158
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
char * strsep(char **str, const char *delims)
int priority
Definition: channel.h:841
#define MAX_ARGS
Definition: app_macro.c:155
#define ast_strdup(a)
Definition: astmm.h:109
static struct ast_datastore_info macro_ds_info
Definition: app_macro.c:167
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_context_lockmacro(const char *macrocontext)
locks the macrolock in the given given context
Definition: pbx.c:6306
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:11141
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition: pbx.c:10719
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
Definition: pbx.c:4468
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:11146
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:11042
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
Structure for a data store object.
Definition: datastore.h:54
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.
Definition: channel.c:2604
#define ast_verb(level,...)
Definition: logger.h:243
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int macropriority
Definition: channel.h:842
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
ast_cond_t cond
Definition: app_meetme.c:963
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:11174
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:11073
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:11047
const ast_string_field name
Definition: channel.h:787
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...
Definition: logger.c:1207
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
Definition: app_macro.c:190
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define AST_MAX_CONTEXT
Definition: channel.h:136
#define ast_free(a)
Definition: astmm.h:97
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:156
unsigned int inheritance
Definition: datastore.h:58
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)
Definition: pbx.c:5425
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...
Definition: pbx.c:10546
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
void * data
Definition: datastore.h:56
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static const char app2[]
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
ast_context: An extension context
Definition: pbx.c:955
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
int ast_context_unlockmacro(const char *macrocontext)
Unlocks the macrolock in the given context.
Definition: pbx.c:6327
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2971
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:11060
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static struct ast_exten* find_matching_priority ( struct ast_context c,
const char *  exten,
int  priority,
const char *  callerid 
)
static

Definition at line 190 of file app_macro.c.

References ast_extension_match(), ast_get_context_name(), ast_get_extension_cidmatch(), ast_get_extension_matchcid(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_include_name(), ast_walk_context_extensions(), ast_walk_context_includes(), ast_walk_contexts(), and ast_walk_extension_priorities().

Referenced by _macro_exec().

191 {
192  struct ast_exten *e;
193  struct ast_include *i;
194  struct ast_context *c2;
195 
196  for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
198  int needmatch = ast_get_extension_matchcid(e);
199  if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
200  (!needmatch)) {
201  /* This is the matching extension we want */
202  struct ast_exten *p;
203  for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
205  continue;
206  return p;
207  }
208  }
209  }
210  }
211 
212  /* No match; run through includes */
213  for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
214  for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
215  if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
216  e = find_matching_priority(c2, exten, priority, callerid);
217  if (e)
218  return e;
219  }
220  }
221  }
222  return NULL;
223 }
struct ast_include * ast_walk_context_includes(struct ast_context *con, struct ast_include *inc)
Definition: pbx.c:11203
ast_include: include= support in extensions.conf
Definition: pbx.c:904
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:11103
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
const char * ast_get_include_name(struct ast_include *include)
Definition: pbx.c:11093
int priority
Definition: pbx.c:888
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: pbx.c:11179
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition: pbx.c:11136
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:11174
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:11073
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:11197
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:11083
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
Definition: app_macro.c:190
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2943
int ast_get_extension_matchcid(struct ast_exten *e)
Definition: pbx.c:11131
ast_context: An extension context
Definition: pbx.c:955
static int load_module ( void  )
static

Definition at line 635 of file app_macro.c.

References ast_register_application_xml, macro_exec(), macro_exit_exec(), macroexclusive_exec(), and macroif_exec().

636 {
637  int res;
638 
643 
644  return res;
645 }
static char * if_app
Definition: app_macro.c:161
static int macroif_exec(struct ast_channel *chan, const char *data)
Definition: app_macro.c:594
static char * exit_app
Definition: app_macro.c:163
static char * exclusive_app
Definition: app_macro.c:162
static int macro_exit_exec(struct ast_channel *chan, const char *data)
Definition: app_macro.c:618
static int macroexclusive_exec(struct ast_channel *chan, const char *data)
Definition: app_macro.c:589
static char * app
Definition: app_macro.c:160
static int macro_exec(struct ast_channel *chan, const char *data)
Definition: app_macro.c:584
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int macro_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 584 of file app_macro.c.

References _macro_exec().

Referenced by load_module(), and macroif_exec().

585 {
586  return _macro_exec(chan, data, 0);
587 }
void * data
Definition: pbx.c:893
static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive)
Definition: app_macro.c:225
static int macro_exit_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 618 of file app_macro.c.

References MACRO_EXIT_RESULT.

Referenced by load_module().

619 {
620  return MACRO_EXIT_RESULT;
621 }
#define MACRO_EXIT_RESULT
Definition: app_macro.c:158
static void macro_fixup ( void *  data,
struct ast_channel old_chan,
struct ast_channel new_chan 
)
static

Definition at line 172 of file app_macro.c.

References pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().

173 {
174  int i;
175  char varname[10];
176  pbx_builtin_setvar_helper(new_chan, "MACRO_DEPTH", "0");
177  pbx_builtin_setvar_helper(new_chan, "MACRO_CONTEXT", NULL);
178  pbx_builtin_setvar_helper(new_chan, "MACRO_EXTEN", NULL);
179  pbx_builtin_setvar_helper(new_chan, "MACRO_PRIORITY", NULL);
180  pbx_builtin_setvar_helper(new_chan, "MACRO_OFFSET", NULL);
181  for (i = 1; i < 100; i++) {
182  snprintf(varname, sizeof(varname), "ARG%d", i);
183  while (pbx_builtin_getvar_helper(new_chan, varname)) {
184  /* Kill all levels of arguments */
185  pbx_builtin_setvar_helper(new_chan, varname, NULL);
186  }
187  }
188 }
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
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...
Definition: pbx.c:10546
static int macroexclusive_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 589 of file app_macro.c.

References _macro_exec().

Referenced by load_module().

590 {
591  return _macro_exec(chan, data, 1);
592 }
void * data
Definition: pbx.c:893
static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive)
Definition: app_macro.c:225
static int macroif_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 594 of file app_macro.c.

References ast_log(), ast_strdupa, LOG_WARNING, macro_exec(), and pbx_checkcondition().

Referenced by load_module().

595 {
596  char *expr = NULL, *label_a = NULL, *label_b = NULL;
597  int res = 0;
598 
599  expr = ast_strdupa(data);
600 
601  if ((label_a = strchr(expr, '?'))) {
602  *label_a = '\0';
603  label_a++;
604  if ((label_b = strchr(label_a, ':'))) {
605  *label_b = '\0';
606  label_b++;
607  }
608  if (pbx_checkcondition(expr))
609  res = macro_exec(chan, label_a);
610  else if (label_b)
611  res = macro_exec(chan, label_b);
612  } else
613  ast_log(LOG_WARNING, "Invalid Syntax.\n");
614 
615  return res;
616 }
#define LOG_WARNING
Definition: logger.h:144
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition: pbx.c:10719
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void * data
Definition: pbx.c:893
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...
Definition: logger.c:1207
static int macro_exec(struct ast_channel *chan, const char *data)
Definition: app_macro.c:584
static int unload_module ( void  )
static

Definition at line 623 of file app_macro.c.

References ast_unregister_application().

624 {
625  int res;
626 
631 
632  return res;
633 }
static char * if_app
Definition: app_macro.c:161
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static char * exit_app
Definition: app_macro.c:163
static char * exclusive_app
Definition: app_macro.c:162
static char * app
Definition: app_macro.c:160

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Macros" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 647 of file app_macro.c.

char* app = "Macro"
static

Definition at line 160 of file app_macro.c.

Definition at line 647 of file app_macro.c.

char* exclusive_app = "MacroExclusive"
static

Definition at line 162 of file app_macro.c.

char* exit_app = "MacroExit"
static

Definition at line 163 of file app_macro.c.

char* if_app = "MacroIf"
static

Definition at line 161 of file app_macro.c.

struct ast_datastore_info macro_ds_info
static
Initial value:
= {
.type = "MACRO",
.chan_fixup = macro_fixup,
}
static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: app_macro.c:172

Definition at line 167 of file app_macro.c.