Wed Jan 8 2020 09:49:55

Asterisk developer's documentation


app_stack.c File Reference

Stack applications Gosub, Return, etc. More...

#include "asterisk.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/channel.h"
#include "asterisk/agi.h"

Go to the source code of this file.

Data Structures

struct  gosub_stack_frame
 
struct  gosub_stack_list
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void balance_stack (struct ast_channel *chan)
 
static const char * expand_gosub_args (struct ast_channel *chan, const char *args)
 
static int frame_set_var (struct ast_channel *chan, struct gosub_stack_frame *frame, const char *var, const char *value)
 
static struct gosub_stack_framegosub_allocate_frame (const char *context, const char *extension, int priority, unsigned char arguments)
 
static int gosub_exec (struct ast_channel *chan, const char *data)
 
static void gosub_free (void *data)
 
static void gosub_release_frame (struct ast_channel *chan, struct gosub_stack_frame *frame)
 
static int gosub_run (struct ast_channel *chan, const char *sub_args, int ignore_hangup)
 
static int gosubif_exec (struct ast_channel *chan, const char *data)
 
static int handle_gosub (struct ast_channel *chan, AGI *agi, int argc, const char *const *argv)
 
static int load_module (void)
 
static int local_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int local_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
 
static int peek_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int pop_exec (struct ast_channel *chan, const char *data)
 
static int return_exec (struct ast_channel *chan, const char *data)
 
static int stackpeek_read (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_LOAD_ORDER , .description = "Dialplan subroutines (Gosub, Return, etc)" , .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_APP_DEPEND, .nonoptreq = "res_agi", }
 
static const char app_gosub [] = "Gosub"
 
static const char app_gosubif [] = "GosubIf"
 
static const char app_pop [] = "StackPop"
 
static const char app_return [] = "Return"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static struct agi_command gosub_agi_command
 
static struct ast_custom_function local_function
 
static struct ast_custom_function peek_function
 
static struct ast_datastore_info stack_info
 
static struct ast_custom_function stackpeek_function
 

Detailed Description

Stack applications Gosub, Return, etc.

Author
Tilghman Lesher app_s.nosp@m.tack.nosp@m._v003.nosp@m.@the.nosp@m.-tilg.nosp@m.hman.nosp@m..com

Definition in file app_stack.c.

Function Documentation

static void __reg_module ( void  )
static

Definition at line 1274 of file app_stack.c.

static void __unreg_module ( void  )
static

Definition at line 1274 of file app_stack.c.

static void balance_stack ( struct ast_channel chan)
static

Definition at line 895 of file app_stack.c.

References ast_channel_datastore_find(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_datastore::data, gosub_stack_frame::entries, gosub_release_frame(), gosub_stack_frame::is_special, and LOG_WARNING.

Referenced by gosub_run(), and handle_gosub().

896 {
897  struct ast_datastore *stack_store;
898  struct gosub_stack_list *oldlist;
899  struct gosub_stack_frame *oldframe;
900  int found;
901 
902  stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
903  if (!stack_store) {
904  ast_log(LOG_WARNING, "No %s stack allocated.\n", app_gosub);
905  return;
906  }
907 
908  oldlist = stack_store->data;
909  AST_LIST_LOCK(oldlist);
910  do {
911  oldframe = AST_LIST_REMOVE_HEAD(oldlist, entries);
912  if (!oldframe) {
913  break;
914  }
915  found = oldframe->is_special;
916  gosub_release_frame(chan, oldframe);
917  } while (!found);
918  AST_LIST_UNLOCK(oldlist);
919 }
struct gosub_stack_frame::@64 entries
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static const char app_gosub[]
Definition: app_stack.c:208
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
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 struct ast_datastore_info stack_info
Definition: app_stack.c:215
unsigned int is_special
Definition: app_stack.c:227
void * data
Definition: datastore.h:56
static void gosub_release_frame(struct ast_channel *chan, struct gosub_stack_frame *frame)
Definition: app_stack.c:265
static const char* expand_gosub_args ( struct ast_channel chan,
const char *  args 
)
static

Definition at line 419 of file app_stack.c.

References ast_channel_lock, ast_channel_unlock, ast_debug, ast_log(), ast_malloc, ast_strdupa, ast_strlen_zero(), gosub_stack_frame::context, ast_channel::context, exten, ast_channel::exten, len(), LOG_WARNING, parse(), and strsep().

Referenced by load_module().

420 {
421  int len;
422  char *parse;
423  char *label;
424  char *new_args;
425  const char *context;
426  const char *exten;
427  const char *pri;
428 
429  /* Separate the context,exten,pri from the optional routine arguments. */
430  parse = ast_strdupa(args);
431  label = strsep(&parse, "(");
432  if (parse) {
433  char *endparen;
434 
435  endparen = strrchr(parse, ')');
436  if (endparen) {
437  *endparen = '\0';
438  } else {
439  ast_log(LOG_WARNING, "Ouch. No closing paren: '%s'?\n", args);
440  }
441  }
442 
443  /* Split context,exten,pri */
444  context = strsep(&label, ",");
445  exten = strsep(&label, ",");
446  pri = strsep(&label, ",");
447  if (!exten) {
448  /* Only a priority in this one */
449  pri = context;
450  exten = NULL;
451  context = NULL;
452  } else if (!pri) {
453  /* Only an extension and priority in this one */
454  pri = exten;
455  exten = context;
456  context = NULL;
457  }
458 
459  ast_channel_lock(chan);
460  if (ast_strlen_zero(exten)) {
461  exten = chan->exten;
462  }
463  if (ast_strlen_zero(context)) {
464  context = chan->context;
465  }
466  len = strlen(context) + strlen(exten) + strlen(pri) + 3;
467  if (!ast_strlen_zero(parse)) {
468  len += 2 + strlen(parse);
469  }
470  new_args = ast_malloc(len);
471  if (new_args) {
472  if (ast_strlen_zero(parse)) {
473  snprintf(new_args, len, "%s,%s,%s", context, exten, pri);
474  } else {
475  snprintf(new_args, len, "%s,%s,%s(%s)", context, exten, pri, parse);
476  }
477  }
478  ast_channel_unlock(chan);
479 
480  ast_debug(4, "Gosub args:%s new_args:%s\n", args, new_args ? new_args : "");
481 
482  return new_args;
483 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
char * strsep(char **str, const char *delims)
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define LOG_WARNING
Definition: logger.h:144
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
#define ast_malloc(a)
Definition: astmm.h:91
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static int frame_set_var ( struct ast_channel chan,
struct gosub_stack_frame frame,
const char *  var,
const char *  value 
)
static

Definition at line 234 of file app_stack.c.

References AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_var_assign(), ast_var_name(), EVENT_FLAG_DIALPLAN, manager_event, pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

Referenced by gosub_exec(), and local_write().

235 {
236  struct ast_var_t *variables;
237  int found = 0;
238 
239  /* Does this variable already exist? */
240  AST_LIST_TRAVERSE(&frame->varshead, variables, entries) {
241  if (!strcmp(var, ast_var_name(variables))) {
242  found = 1;
243  break;
244  }
245  }
246 
247  if (!found) {
248  if ((variables = ast_var_assign(var, ""))) {
249  AST_LIST_INSERT_HEAD(&frame->varshead, variables, entries);
250  }
252  } else {
254  }
255 
257  "Channel: %s\r\n"
258  "Variable: LOCAL(%s)\r\n"
259  "Value: %s\r\n"
260  "Uniqueid: %s\r\n",
261  chan->name, var, value, chan->uniqueid);
262  return 0;
263 }
struct varshead varshead
Definition: app_stack.c:224
const ast_string_field uniqueid
Definition: channel.h:787
struct ast_var_t * ast_var_assign(const char *name, const char *value)
Definition: chanvars.c:41
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:69
#define var
Definition: ast_expr2f.c:606
void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, without removing any previously set value...
Definition: pbx.c:10513
int value
Definition: syslog.c:39
#define EVENT_FLAG_DIALPLAN
Definition: manager.h:82
const ast_string_field name
Definition: channel.h:787
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
struct ast_var_t::@158 entries
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
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static struct gosub_stack_frame* gosub_allocate_frame ( const char *  context,
const char *  extension,
int  priority,
unsigned char  arguments 
)
static

Definition at line 284 of file app_stack.c.

References gosub_stack_frame::arguments, ast_calloc, AST_LIST_HEAD_INIT_NOLOCK, and gosub_stack_frame::priority.

Referenced by gosub_exec().

285 {
286  struct gosub_stack_frame *new = NULL;
287  int len_extension = strlen(extension), len_context = strlen(context);
288 
289  if ((new = ast_calloc(1, sizeof(*new) + 2 + len_extension + len_context))) {
290  AST_LIST_HEAD_INIT_NOLOCK(&new->varshead);
291  strcpy(new->extension, extension);
292  new->context = new->extension + len_extension + 1;
293  strcpy(new->context, context);
294  new->priority = priority;
295  new->arguments = arguments;
296  }
297  return new;
298 }
unsigned char arguments
Definition: app_stack.c:223
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:666
#define ast_calloc(a, b)
Definition: astmm.h:82
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int gosub_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 485 of file app_stack.c.

References gosub_stack_frame::arguments, AST_APP_ARG, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_datastore_alloc(), ast_datastore_free(), ast_debug, AST_DECLARE_APP_ARGS, ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, AST_LIST_FIRST, AST_LIST_HEAD_INIT, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_parseable_goto(), AST_STANDARD_RAW_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::caller, ast_channel::context, ast_datastore::data, gosub_stack_frame::entries, ast_channel::exten, frame_set_var(), gosub_allocate_frame(), ast_party_caller::id, LOG_ERROR, LOG_WARNING, ast_channel::name, ast_party_id::number, orig_exten(), parse(), ast_channel::priority, S_COR, ast_party_number::str, strsep(), and ast_party_number::valid.

Referenced by gosub_run(), gosubif_exec(), handle_gosub(), and load_module().

486 {
487  struct ast_datastore *stack_store;
488  struct gosub_stack_list *oldlist;
489  struct gosub_stack_frame *newframe;
490  struct gosub_stack_frame *lastframe;
491  char argname[15];
492  char *parse;
493  char *label;
494  char *caller_id;
495  char *orig_context;
496  char *orig_exten;
497  char *dest_context;
498  char *dest_exten;
499  int orig_priority;
500  int dest_priority;
501  int i;
502  int max_argc = 0;
503  AST_DECLARE_APP_ARGS(args2,
504  AST_APP_ARG(argval)[100];
505  );
506 
507  if (ast_strlen_zero(data)) {
508  ast_log(LOG_ERROR, "%s requires an argument: %s([[context,]exten,]priority[(arg1[,...][,argN])])\n", app_gosub, app_gosub);
509  return -1;
510  }
511 
512  /*
513  * Separate the arguments from the label
514  *
515  * NOTE: You cannot use ast_app_separate_args for this, because
516  * '(' cannot be used as a delimiter.
517  */
518  parse = ast_strdupa(data);
519  label = strsep(&parse, "(");
520  if (parse) {
521  char *endparen;
522 
523  endparen = strrchr(parse, ')');
524  if (endparen) {
525  *endparen = '\0';
526  } else {
527  ast_log(LOG_WARNING, "Ouch. No closing paren: '%s'?\n", data);
528  }
529  AST_STANDARD_RAW_ARGS(args2, parse);
530  } else {
531  args2.argc = 0;
532  }
533 
534  ast_channel_lock(chan);
535  orig_context = ast_strdupa(chan->context);
536  orig_exten = ast_strdupa(chan->exten);
537  orig_priority = chan->priority;
538  ast_channel_unlock(chan);
539 
540  if (ast_parseable_goto(chan, label)) {
541  ast_log(LOG_ERROR, "%s address is invalid: '%s'\n", app_gosub, data);
542  goto error_exit;
543  }
544 
545  ast_channel_lock(chan);
546  dest_context = ast_strdupa(chan->context);
547  dest_exten = ast_strdupa(chan->exten);
548  dest_priority = chan->priority;
549  if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) {
550  ++dest_priority;
551  }
552  caller_id = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
553  if (caller_id) {
554  caller_id = ast_strdupa(caller_id);
555  }
556  ast_channel_unlock(chan);
557 
558  if (!ast_exists_extension(chan, dest_context, dest_exten, dest_priority, caller_id)) {
559  ast_log(LOG_ERROR, "Attempt to reach a non-existent destination for %s: (Context:%s, Extension:%s, Priority:%d)\n",
560  app_gosub, dest_context, dest_exten, dest_priority);
561  goto error_exit;
562  }
563 
564  /* Now we know that we're going to a new location */
565 
566  ast_channel_lock(chan);
567 
568  /* Find stack datastore return list. */
569  if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
570  ast_debug(1, "Channel %s has no datastore, so we're allocating one.\n",
571  chan->name);
572  stack_store = ast_datastore_alloc(&stack_info, NULL);
573  if (!stack_store) {
574  ast_log(LOG_ERROR, "Unable to allocate new datastore. %s failed.\n",
575  app_gosub);
576  goto error_exit_locked;
577  }
578 
579  oldlist = ast_calloc(1, sizeof(*oldlist));
580  if (!oldlist) {
581  ast_log(LOG_ERROR, "Unable to allocate datastore list head. %s failed.\n",
582  app_gosub);
583  ast_datastore_free(stack_store);
584  goto error_exit_locked;
585  }
586  AST_LIST_HEAD_INIT(oldlist);
587 
588  stack_store->data = oldlist;
589  ast_channel_datastore_add(chan, stack_store);
590  } else {
591  oldlist = stack_store->data;
592  }
593 
594  if ((lastframe = AST_LIST_FIRST(oldlist))) {
595  max_argc = lastframe->arguments;
596  }
597 
598  /* Mask out previous Gosub arguments in this invocation */
599  if (args2.argc > max_argc) {
600  max_argc = args2.argc;
601  }
602 
603  /* Create the return address */
604  newframe = gosub_allocate_frame(orig_context, orig_exten, orig_priority + 1, max_argc);
605  if (!newframe) {
606  goto error_exit_locked;
607  }
608 
609  /* Set our arguments */
610  for (i = 0; i < max_argc; i++) {
611  snprintf(argname, sizeof(argname), "ARG%d", i + 1);
612  frame_set_var(chan, newframe, argname, i < args2.argc ? args2.argval[i] : "");
613  ast_debug(1, "Setting '%s' to '%s'\n", argname, i < args2.argc ? args2.argval[i] : "");
614  }
615  snprintf(argname, sizeof(argname), "%u", args2.argc);
616  frame_set_var(chan, newframe, "ARGC", argname);
617 
618  /* And finally, save our return address */
619  AST_LIST_LOCK(oldlist);
620  AST_LIST_INSERT_HEAD(oldlist, newframe, entries);
621  AST_LIST_UNLOCK(oldlist);
622  ast_channel_unlock(chan);
623 
624  return 0;
625 
626 error_exit:
627  ast_channel_lock(chan);
628 
629 error_exit_locked:
630  /* Restore the original dialplan location. */
631  ast_copy_string(chan->context, orig_context, sizeof(chan->context));
632  ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
633  chan->priority = orig_priority;
634  ast_channel_unlock(chan);
635  return -1;
636 }
struct gosub_stack_frame::@64 entries
#define ast_channel_lock(chan)
Definition: channel.h:2466
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
static const char app_gosub[]
Definition: app_stack.c:208
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
char * strsep(char **str, const char *delims)
int priority
Definition: channel.h:841
#define ast_test_flag(p, flag)
Definition: utils.h:63
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
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
static int frame_set_var(struct ast_channel *chan, struct gosub_stack_frame *frame, const char *var, const char *value)
Definition: app_stack.c:234
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct gosub_stack_frame * gosub_allocate_frame(const char *context, const char *extension, int priority, unsigned char arguments)
Definition: app_stack.c:284
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:11326
#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
static char * orig_exten(int fd, const char *chan, const char *data)
orginate from extension
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
unsigned char arguments
Definition: app_stack.c:223
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
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
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:611
static struct ast_datastore_info stack_info
Definition: app_stack.c:215
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_STANDARD_RAW_ARGS(args, parse)
Definition: app.h:606
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static void gosub_free ( void *  data)
static

Definition at line 300 of file app_stack.c.

References ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, gosub_stack_frame::entries, and gosub_release_frame().

301 {
302  struct gosub_stack_list *oldlist = data;
303  struct gosub_stack_frame *oldframe;
304 
305  AST_LIST_LOCK(oldlist);
306  while ((oldframe = AST_LIST_REMOVE_HEAD(oldlist, entries))) {
307  gosub_release_frame(NULL, oldframe);
308  }
309  AST_LIST_UNLOCK(oldlist);
310  AST_LIST_HEAD_DESTROY(oldlist);
311  ast_free(oldlist);
312 }
struct gosub_stack_frame::@64 entries
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:638
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
static void gosub_release_frame(struct ast_channel *chan, struct gosub_stack_frame *frame)
Definition: app_stack.c:265
static void gosub_release_frame ( struct ast_channel chan,
struct gosub_stack_frame frame 
)
static

Definition at line 265 of file app_stack.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_var_delete(), ast_var_name(), gosub_stack_frame::entries, pbx_builtin_setvar_helper(), and gosub_stack_frame::varshead.

Referenced by balance_stack(), gosub_free(), pop_exec(), and return_exec().

266 {
267  struct ast_var_t *vardata;
268 
269  /* If chan is not defined, then we're calling it as part of gosub_free,
270  * and the channel variables will be deallocated anyway. Otherwise, we're
271  * just releasing a single frame, so we need to clean up the arguments for
272  * that frame, so that we re-expose the variables from the previous frame
273  * that were hidden by this one.
274  */
275  while ((vardata = AST_LIST_REMOVE_HEAD(&frame->varshead, entries))) {
276  if (chan)
277  pbx_builtin_setvar_helper(chan, ast_var_name(vardata), NULL);
278  ast_var_delete(vardata);
279  }
280 
281  ast_free(frame);
282 }
struct varshead varshead
Definition: app_stack.c:224
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:69
void ast_var_delete(struct ast_var_t *var)
Definition: chanvars.c:63
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct ast_var_t::@158 entries
#define ast_free(a)
Definition: astmm.h:97
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 gosub_run ( struct ast_channel chan,
const char *  sub_args,
int  ignore_hangup 
)
static

Definition at line 936 of file app_stack.c.

References ast_channel::_softhangup, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_copy_string(), ast_debug, AST_FLAG_IN_AUTOLOOP, AST_LIST_FIRST, ast_log(), ast_set2_flag, ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), AST_SOFTHANGUP_UNBRIDGE, ast_spawn_extension(), ast_strdupa, ast_test_flag, ast_verb, balance_stack(), ast_channel::caller, ast_channel::context, ast_datastore::data, ast_channel::exten, gosub_exec(), ast_party_caller::id, gosub_stack_frame::is_special, LOG_ERROR, LOG_NOTICE, ast_channel::name, ast_party_id::number, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), ast_channel::priority, S_COR, S_OR, ast_party_number::str, and ast_party_number::valid.

Referenced by load_module().

937 {
938  const char *saved_context;
939  const char *saved_exten;
940  int saved_priority;
941  int saved_hangup_flags;
942  int saved_autoloopflag;
943  int res;
944 
945  ast_channel_lock(chan);
946 
947  ast_verb(3, "%s Internal %s(%s) start\n", chan->name, app_gosub, sub_args);
948 
949  /* Save non-hangup softhangup flags. */
950  saved_hangup_flags = chan->_softhangup
952  if (saved_hangup_flags) {
954  }
955 
956  /* Save autoloop flag */
957  saved_autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
959 
960  /* Save current dialplan location */
961  saved_context = ast_strdupa(chan->context);
962  saved_exten = ast_strdupa(chan->exten);
963  saved_priority = chan->priority;
964 
965  ast_debug(4, "%s Original location: %s,%s,%d\n", chan->name,
966  saved_context, saved_exten, saved_priority);
967 
968  ast_channel_unlock(chan);
969  res = gosub_exec(chan, sub_args);
970  ast_debug(4, "%s exited with status %d\n", app_gosub, res);
971  ast_channel_lock(chan);
972  if (!res) {
973  struct ast_datastore *stack_store;
974 
975  /* Mark the return location as special. */
976  stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
977  if (!stack_store) {
978  /* Should never happen! */
979  ast_log(LOG_ERROR, "No %s stack!\n", app_gosub);
980  res = -1;
981  } else {
982  struct gosub_stack_list *oldlist;
983  struct gosub_stack_frame *cur;
984 
985  oldlist = stack_store->data;
986  cur = AST_LIST_FIRST(oldlist);
987  cur->is_special = 1;
988  }
989  }
990  if (!res) {
991  int found = 0; /* set if we find at least one match */
992 
993  /*
994  * Run gosub body autoloop.
995  *
996  * Note that this loop is inverted from the normal execution
997  * loop because we just executed the Gosub application as the
998  * first extension of the autoloop.
999  */
1000  do {
1001  /* Check for hangup. */
1002  if (chan->_softhangup & AST_SOFTHANGUP_UNBRIDGE) {
1003  saved_hangup_flags |= AST_SOFTHANGUP_UNBRIDGE;
1005  }
1006  if (ast_check_hangup(chan)) {
1007  if (chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
1008  ast_log(LOG_ERROR, "%s An async goto just messed up our execution location.\n",
1009  chan->name);
1010  break;
1011  }
1012  if (!ignore_hangup) {
1013  break;
1014  }
1015  }
1016 
1017  /* Next dialplan priority. */
1018  ++chan->priority;
1019 
1020  ast_channel_unlock(chan);
1021  res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority,
1022  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
1023  &found, 1);
1024  ast_channel_lock(chan);
1025  } while (!res);
1026  if (found && res) {
1027  /* Something bad happened, or a hangup has been requested. */
1028  ast_debug(1, "Spawn extension (%s,%s,%d) exited with %d on '%s'\n",
1029  chan->context, chan->exten, chan->priority, res, chan->name);
1030  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
1031  chan->context, chan->exten, chan->priority, chan->name);
1032  }
1033 
1034  /* Did the routine return? */
1035  if (chan->priority == saved_priority
1036  && !strcmp(chan->context, saved_context)
1037  && !strcmp(chan->exten, saved_exten)) {
1038  ast_verb(3, "%s Internal %s(%s) complete GOSUB_RETVAL=%s\n",
1039  chan->name, app_gosub, sub_args,
1040  S_OR(pbx_builtin_getvar_helper(chan, "GOSUB_RETVAL"), ""));
1041  } else {
1042  ast_log(LOG_NOTICE, "%s Abnormal '%s(%s)' exit. Popping routine return locations.\n",
1043  chan->name, app_gosub, sub_args);
1044  balance_stack(chan);
1045  pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", "");
1046  }
1047 
1048  /* We executed the requested subroutine to the best of our ability. */
1049  res = 0;
1050  }
1051 
1052  ast_debug(4, "%s Ending location: %s,%s,%d\n", chan->name,
1053  chan->context, chan->exten, chan->priority);
1054 
1055  /* Restore dialplan location */
1056  if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
1057  ast_copy_string(chan->context, saved_context, sizeof(chan->context));
1058  ast_copy_string(chan->exten, saved_exten, sizeof(chan->exten));
1059  chan->priority = saved_priority;
1060  }
1061 
1062  /* Restore autoloop flag */
1063  ast_set2_flag(chan, saved_autoloopflag, AST_FLAG_IN_AUTOLOOP);
1064 
1065  /* Restore non-hangup softhangup flags. */
1066  if (saved_hangup_flags) {
1067  ast_softhangup_nolock(chan, saved_hangup_flags);
1068  }
1069 
1070  ast_channel_unlock(chan);
1071 
1072  return res;
1073 }
static void balance_stack(struct ast_channel *chan)
Definition: app_stack.c:895
#define ast_channel_lock(chan)
Definition: channel.h:2466
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
static const char app_gosub[]
Definition: app_stack.c:208
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int priority
Definition: channel.h:841
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
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
static int gosub_exec(struct ast_channel *chan, const char *data)
Definition: app_stack.c:485
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
#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_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
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
int _softhangup
Definition: channel.h:832
#define LOG_NOTICE
Definition: logger.h:133
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2733
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static struct ast_datastore_info stack_info
Definition: app_stack.c:215
unsigned int is_special
Definition: app_stack.c:227
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
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
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int gosubif_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 638 of file app_stack.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_RAW_ARGS, ast_strdupa, ast_strlen_zero(), cond, gosub_exec(), LOG_WARNING, and pbx_checkcondition().

Referenced by load_module().

639 {
640  char *args;
641  int res=0;
643  AST_APP_ARG(ition);
644  AST_APP_ARG(labels);
645  );
646  AST_DECLARE_APP_ARGS(label,
647  AST_APP_ARG(iftrue);
648  AST_APP_ARG(iffalse);
649  );
650 
651  if (ast_strlen_zero(data)) {
652  ast_log(LOG_WARNING, "GosubIf requires an argument: GosubIf(cond?label1(args):label2(args)\n");
653  return 0;
654  }
655 
656  args = ast_strdupa(data);
657  AST_NONSTANDARD_RAW_ARGS(cond, args, '?');
658  if (cond.argc != 2) {
659  ast_log(LOG_WARNING, "GosubIf requires an argument: GosubIf(cond?label1(args):label2(args)\n");
660  return 0;
661  }
662 
663  AST_NONSTANDARD_RAW_ARGS(label, cond.labels, ':');
664 
665  if (pbx_checkcondition(cond.ition)) {
666  if (!ast_strlen_zero(label.iftrue))
667  res = gosub_exec(chan, label.iftrue);
668  } else if (!ast_strlen_zero(label.iffalse)) {
669  res = gosub_exec(chan, label.iffalse);
670  }
671 
672  return res;
673 }
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition: pbx.c:10719
static int gosub_exec(struct ast_channel *chan, const char *data)
Definition: app_stack.c:485
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 ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
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
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_NONSTANDARD_RAW_ARGS(args, parse, sep)
Definition: app.h:621
static int handle_gosub ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const *  argv 
)
static

Definition at line 1075 of file app_stack.c.

References ast_agi_send(), ast_asprintf, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_exists_extension(), ast_findlabel_extension(), AST_FLAG_IN_AUTOLOOP, ast_free, AST_LIST_FIRST, ast_log(), ast_pbx_run_args(), ast_set2_flag, ast_set_flag, ast_strdupa, ast_test_flag, ast_verb, balance_stack(), ast_channel::caller, ast_channel::context, ast_datastore::data, ast_channel::exten, agi_state::fd, free, gosub_exec(), ast_party_caller::id, gosub_stack_frame::is_special, LOG_ERROR, LOG_NOTICE, ast_channel::name, ast_pbx_args::no_hangup_chan, ast_party_id::number, ast_channel::pbx, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), gosub_stack_frame::priority, ast_channel::priority, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, S_COR, S_OR, ast_party_number::str, and ast_party_number::valid.

1076 {
1077  int res;
1078  int priority;
1079  int old_autoloopflag;
1080  int old_priority;
1081  const char *old_context;
1082  const char *old_extension;
1083  char *gosub_args;
1084 
1085  if (argc < 4 || argc > 5) {
1086  return RESULT_SHOWUSAGE;
1087  }
1088 
1089  ast_debug(1, "Gosub called with %d arguments: 0:%s 1:%s 2:%s 3:%s 4:%s\n", argc, argv[0], argv[1], argv[2], argv[3], argc == 5 ? argv[4] : "");
1090 
1091  if (sscanf(argv[3], "%30d", &priority) != 1 || priority < 1) {
1092  /* Lookup the priority label */
1093  priority = ast_findlabel_extension(chan, argv[1], argv[2], argv[3],
1094  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
1095  if (priority < 0) {
1096  ast_log(LOG_ERROR, "Priority '%s' not found in '%s@%s'\n", argv[3], argv[2], argv[1]);
1097  ast_agi_send(agi->fd, chan, "200 result=-1 Gosub label not found\n");
1098  return RESULT_FAILURE;
1099  }
1100  } else if (!ast_exists_extension(chan, argv[1], argv[2], priority,
1101  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
1102  ast_agi_send(agi->fd, chan, "200 result=-1 Gosub label not found\n");
1103  return RESULT_FAILURE;
1104  }
1105 
1106  if (argc == 5) {
1107  if (ast_asprintf(&gosub_args, "%s,%s,%d(%s)", argv[1], argv[2], priority, argv[4]) < 0) {
1108  gosub_args = NULL;
1109  }
1110  } else {
1111  if (ast_asprintf(&gosub_args, "%s,%s,%d", argv[1], argv[2], priority) < 0) {
1112  gosub_args = NULL;
1113  }
1114  }
1115  if (!gosub_args) {
1116  ast_agi_send(agi->fd, chan, "503 result=-2 Memory allocation failure\n");
1117  return RESULT_FAILURE;
1118  }
1119 
1120  ast_channel_lock(chan);
1121 
1122  ast_verb(3, "%s AGI %s(%s) start\n", chan->name, app_gosub, gosub_args);
1123 
1124  /* Save autoloop flag */
1125  old_autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
1127 
1128  /* Save previous location, since we're going to change it */
1129  old_context = ast_strdupa(chan->context);
1130  old_extension = ast_strdupa(chan->exten);
1131  old_priority = chan->priority;
1132 
1133  ast_debug(4, "%s Original location: %s,%s,%d\n", chan->name,
1134  old_context, old_extension, old_priority);
1135  ast_channel_unlock(chan);
1136 
1137  res = gosub_exec(chan, gosub_args);
1138  if (!res) {
1139  struct ast_datastore *stack_store;
1140 
1141  /* Mark the return location as special. */
1142  ast_channel_lock(chan);
1143  stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
1144  if (!stack_store) {
1145  /* Should never happen! */
1146  ast_log(LOG_ERROR, "No %s stack!\n", app_gosub);
1147  res = -1;
1148  } else {
1149  struct gosub_stack_list *oldlist;
1150  struct gosub_stack_frame *cur;
1151 
1152  oldlist = stack_store->data;
1153  cur = AST_LIST_FIRST(oldlist);
1154  cur->is_special = 1;
1155  }
1156  ast_channel_unlock(chan);
1157  }
1158  if (!res) {
1159  struct ast_pbx *pbx;
1160  struct ast_pbx_args args;
1161  int abnormal_exit;
1162 
1163  memset(&args, 0, sizeof(args));
1164  args.no_hangup_chan = 1;
1165 
1166  ast_channel_lock(chan);
1167 
1168  /* Next dialplan priority. */
1169  ++chan->priority;
1170 
1171  /* Suppress warning about PBX already existing */
1172  pbx = chan->pbx;
1173  chan->pbx = NULL;
1174  ast_channel_unlock(chan);
1175 
1176  ast_agi_send(agi->fd, chan, "100 result=0 Trying...\n");
1177  ast_pbx_run_args(chan, &args);
1178 
1179  ast_channel_lock(chan);
1180  ast_free(chan->pbx);
1181  chan->pbx = pbx;
1182 
1183  /* Did the routine return? */
1184  if (chan->priority == old_priority
1185  && !strcmp(chan->context, old_context)
1186  && !strcmp(chan->exten, old_extension)) {
1187  ast_verb(3, "%s AGI %s(%s) complete GOSUB_RETVAL=%s\n",
1188  chan->name, app_gosub, gosub_args,
1189  S_OR(pbx_builtin_getvar_helper(chan, "GOSUB_RETVAL"), ""));
1190  abnormal_exit = 0;
1191  } else {
1192  ast_log(LOG_NOTICE, "%s Abnormal AGI %s(%s) exit. Popping routine return locations.\n",
1193  chan->name, app_gosub, gosub_args);
1194  balance_stack(chan);
1195  pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", "");
1196  abnormal_exit = 1;
1197  }
1198  ast_channel_unlock(chan);
1199 
1200  ast_agi_send(agi->fd, chan, "200 result=0 Gosub complete%s\n",
1201  abnormal_exit ? " (abnormal exit)" : "");
1202  } else {
1203  ast_agi_send(agi->fd, chan, "200 result=%d Gosub failed\n", res);
1204  }
1205 
1206  /* Must use free because the memory was allocated by asprintf(). */
1207  free(gosub_args);
1208 
1209  ast_channel_lock(chan);
1210  ast_debug(4, "%s Ending location: %s,%s,%d\n", chan->name,
1211  chan->context, chan->exten, chan->priority);
1212 
1213  /* Restore previous location */
1214  ast_copy_string(chan->context, old_context, sizeof(chan->context));
1215  ast_copy_string(chan->exten, old_extension, sizeof(chan->exten));
1216  chan->priority = old_priority;
1217 
1218  /* Restore autoloop flag */
1219  ast_set2_flag(chan, old_autoloopflag, AST_FLAG_IN_AUTOLOOP);
1220  ast_channel_unlock(chan);
1221 
1222  return RESULT_SUCCESS;
1223 }
static void balance_stack(struct ast_channel *chan)
Definition: app_stack.c:895
Options for ast_pbx_run()
Definition: pbx.h:336
#define ast_channel_lock(chan)
Definition: channel.h:2466
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
static const char app_gosub[]
Definition: app_stack.c:208
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int priority
Definition: channel.h:841
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RESULT_SHOWUSAGE
Definition: cli.h:40
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
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
static int gosub_exec(struct ast_channel *chan, const char *data)
Definition: app_stack.c:485
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_asprintf(a, b, c...)
Definition: astmm.h:121
Definition: pbx.h:179
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:5906
#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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
#define free(a)
Definition: astmm.h:94
static struct @350 args
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:5405
int fd
Definition: agi.h:35
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
#define LOG_NOTICE
Definition: logger.h:133
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_free(a)
Definition: astmm.h:97
static struct ast_datastore_info stack_info
Definition: app_stack.c:215
unsigned int is_special
Definition: app_stack.c:227
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
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
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
#define RESULT_SUCCESS
Definition: cli.h:39
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define RESULT_FAILURE
Definition: cli.h:41
struct ast_pbx * pbx
Definition: channel.h:761
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int load_module ( void  )
static

Definition at line 1245 of file app_stack.c.

References ast_agi_register(), ast_custom_function_register, ast_install_stack_functions(), ast_register_application_xml, expand_gosub_args(), gosub_agi_command, gosub_exec(), gosub_run(), gosubif_exec(), local_function, ast_app_stack_funcs::module, peek_function, pop_exec(), return_exec(), ast_app_stack_funcs::run_sub, ast_module_info::self, and stackpeek_function.

1246 {
1247  /* Setup the stack application callback functions. */
1248  static struct ast_app_stack_funcs funcs = {
1249  .run_sub = gosub_run,
1250  .expand_sub_args = expand_gosub_args,
1251  };
1252 
1254 
1262 
1263  funcs.module = ast_module_info->self,
1265 
1266  return 0;
1267 }
static const char app_gosub[]
Definition: app_stack.c:208
int ast_agi_register(struct ast_module *mod, agi_command *cmd)
Registers an AGI command.
Definition: res_agi.c:3123
static int pop_exec(struct ast_channel *chan, const char *data)
Definition: app_stack.c:314
static int gosub_exec(struct ast_channel *chan, const char *data)
Definition: app_stack.c:485
static int return_exec(struct ast_channel *chan, const char *data)
Definition: app_stack.c:349
static struct ast_custom_function stackpeek_function
Definition: app_stack.c:878
static int gosubif_exec(struct ast_channel *chan, const char *data)
Definition: app_stack.c:638
static const char * expand_gosub_args(struct ast_channel *chan, const char *args)
Definition: app_stack.c:419
static const char app_return[]
Definition: app_stack.c:210
struct ast_module * self
Definition: module.h:227
int(* run_sub)(struct ast_channel *chan, const char *args, int ignore_hangup)
Callback for the routine to run a subroutine on a channel.
Definition: app.h:184
void * module
Definition: app.h:170
static struct ast_custom_function peek_function
Definition: app_stack.c:788
Stack applications callback functions.
Definition: app.h:165
static int gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_hangup)
Definition: app_stack.c:936
static struct agi_command gosub_agi_command
Definition: app_stack.c:1225
void ast_install_stack_functions(const struct ast_app_stack_funcs *funcs)
Set stack application function callbacks.
Definition: app.c:319
static const char app_pop[]
Definition: app_stack.c:211
static const char app_gosubif[]
Definition: app_stack.c:209
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static struct ast_custom_function local_function
Definition: app_stack.c:747
static int local_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 675 of file app_stack.c.

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_var_name(), ast_datastore::data, gosub_stack_frame::entries, LOG_WARNING, pbx_builtin_getvar_helper(), S_OR, and gosub_stack_frame::varshead.

676 {
677  struct ast_datastore *stack_store;
678  struct gosub_stack_list *oldlist;
679  struct gosub_stack_frame *frame;
680  struct ast_var_t *variables;
681 
682  if (!chan) {
683  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
684  return -1;
685  }
686 
687  ast_channel_lock(chan);
688  if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
689  ast_channel_unlock(chan);
690  return -1;
691  }
692 
693  oldlist = stack_store->data;
694  AST_LIST_LOCK(oldlist);
695  if (!(frame = AST_LIST_FIRST(oldlist))) {
696  /* Not within a Gosub routine */
697  AST_LIST_UNLOCK(oldlist);
698  ast_channel_unlock(chan);
699  return -1;
700  }
701 
702  AST_LIST_TRAVERSE(&frame->varshead, variables, entries) {
703  if (!strcmp(data, ast_var_name(variables))) {
704  const char *tmp;
705  tmp = pbx_builtin_getvar_helper(chan, data);
706  ast_copy_string(buf, S_OR(tmp, ""), len);
707  break;
708  }
709  }
710  AST_LIST_UNLOCK(oldlist);
711  ast_channel_unlock(chan);
712  return 0;
713 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
struct varshead varshead
Definition: app_stack.c:224
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:69
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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
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
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
struct ast_var_t::@158 entries
static struct ast_datastore_info stack_info
Definition: app_stack.c:215
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
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static int local_write ( struct ast_channel chan,
const char *  cmd,
char *  var,
const char *  value 
)
static

Definition at line 715 of file app_stack.c.

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_datastore::data, frame_set_var(), LOG_ERROR, and LOG_WARNING.

716 {
717  struct ast_datastore *stack_store;
718  struct gosub_stack_list *oldlist;
719  struct gosub_stack_frame *frame;
720 
721  if (!chan) {
722  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
723  return -1;
724  }
725 
726  ast_channel_lock(chan);
727  if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
728  ast_log(LOG_ERROR, "Tried to set LOCAL(%s), but we aren't within a Gosub routine\n", var);
729  ast_channel_unlock(chan);
730  return -1;
731  }
732 
733  oldlist = stack_store->data;
734  AST_LIST_LOCK(oldlist);
735  frame = AST_LIST_FIRST(oldlist);
736 
737  if (frame) {
738  frame_set_var(chan, frame, var, value);
739  }
740 
741  AST_LIST_UNLOCK(oldlist);
742  ast_channel_unlock(chan);
743 
744  return 0;
745 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define var
Definition: ast_expr2f.c:606
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
static int frame_set_var(struct ast_channel *chan, struct gosub_stack_frame *frame, const char *var, const char *value)
Definition: app_stack.c:234
int value
Definition: syslog.c:39
#define LOG_ERROR
Definition: logger.h:155
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
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static struct ast_datastore_info stack_info
Definition: app_stack.c:215
void * data
Definition: datastore.h:56
static int peek_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 753 of file app_stack.c.

References args, AST_APP_ARG, ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_TRAVERSE, ast_log(), AST_STANDARD_RAW_ARGS, ast_strlen_zero(), ast_var_name(), ast_var_value(), gosub_stack_frame::entries, LOG_ERROR, name, and ast_channel::varshead.

754 {
755  int found = 0, n;
756  struct ast_var_t *variables;
758  AST_APP_ARG(n);
759  AST_APP_ARG(name);
760  );
761 
762  if (!chan) {
763  ast_log(LOG_ERROR, "LOCAL_PEEK must be called on an active channel\n");
764  return -1;
765  }
766 
768 
769  if (ast_strlen_zero(args.n) || ast_strlen_zero(args.name)) {
770  ast_log(LOG_ERROR, "LOCAL_PEEK requires parameters n and varname\n");
771  return -1;
772  }
773 
774  n = atoi(args.n);
775  *buf = '\0';
776 
777  ast_channel_lock(chan);
778  AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
779  if (!strcmp(args.name, ast_var_name(variables)) && ++found > n) {
780  ast_copy_string(buf, ast_var_value(variables), len);
781  break;
782  }
783  }
784  ast_channel_unlock(chan);
785  return 0;
786 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:89
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:69
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static const char name[]
struct ast_var_t::@158 entries
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_STANDARD_RAW_ARGS(args, parse)
Definition: app.h:606
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
struct varshead varshead
Definition: channel.h:817
static int pop_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 314 of file app_stack.c.

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_debug, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_datastore::data, gosub_stack_frame::entries, gosub_release_frame(), gosub_stack_frame::is_special, and LOG_WARNING.

Referenced by load_module().

315 {
316  struct ast_datastore *stack_store;
317  struct gosub_stack_frame *oldframe;
318  struct gosub_stack_list *oldlist;
319  int res = 0;
320 
321  ast_channel_lock(chan);
322  if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
323  ast_log(LOG_WARNING, "%s called with no gosub stack allocated.\n", app_pop);
324  ast_channel_unlock(chan);
325  return 0;
326  }
327 
328  oldlist = stack_store->data;
329  AST_LIST_LOCK(oldlist);
330  oldframe = AST_LIST_FIRST(oldlist);
331  if (oldframe) {
332  if (oldframe->is_special) {
333  ast_debug(1, "%s attempted to pop special return location.\n", app_pop);
334 
335  /* Abort the special routine dialplan execution. Dialplan programming error. */
336  res = -1;
337  } else {
338  AST_LIST_REMOVE_HEAD(oldlist, entries);
339  gosub_release_frame(chan, oldframe);
340  }
341  } else {
342  ast_debug(1, "%s called with an empty gosub stack\n", app_pop);
343  }
344  AST_LIST_UNLOCK(oldlist);
345  ast_channel_unlock(chan);
346  return res;
347 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
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
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static struct ast_datastore_info stack_info
Definition: app_stack.c:215
unsigned int is_special
Definition: app_stack.c:227
void * data
Definition: datastore.h:56
static const char app_pop[]
Definition: app_stack.c:211
static void gosub_release_frame(struct ast_channel *chan, struct gosub_stack_frame *frame)
Definition: app_stack.c:265
static int return_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 349 of file app_stack.c.

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_test_flag, gosub_stack_frame::context, ast_channel::context, ast_datastore::data, gosub_stack_frame::entries, ast_channel::exten, gosub_stack_frame::extension, gosub_release_frame(), gosub_stack_frame::is_special, LOG_ERROR, pbx_builtin_setvar_helper(), gosub_stack_frame::priority, ast_channel::priority, and S_OR.

Referenced by load_module().

350 {
351  struct ast_datastore *stack_store;
352  struct gosub_stack_frame *oldframe;
353  struct gosub_stack_list *oldlist;
354  const char *retval = data;
355  int res = 0;
356 
357  ast_channel_lock(chan);
358  if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
359  ast_log(LOG_ERROR, "Return without Gosub: stack is unallocated\n");
360  ast_channel_unlock(chan);
361  return -1;
362  }
363 
364  oldlist = stack_store->data;
365  AST_LIST_LOCK(oldlist);
366  oldframe = AST_LIST_REMOVE_HEAD(oldlist, entries);
367  AST_LIST_UNLOCK(oldlist);
368 
369  if (!oldframe) {
370  ast_log(LOG_ERROR, "Return without Gosub: stack is empty\n");
371  ast_channel_unlock(chan);
372  return -1;
373  }
374  if (oldframe->is_special) {
375  /* Exit from special routine. */
376  res = -1;
377  }
378 
379  /*
380  * We cannot use ast_explicit_goto() because we MUST restore
381  * what was there before. Channels that do not have a PBX may
382  * not have the context or exten set.
383  */
384  ast_copy_string(chan->context, oldframe->context, sizeof(chan->context));
385  ast_copy_string(chan->exten, oldframe->extension, sizeof(chan->exten));
386  if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) {
387  --oldframe->priority;
388  }
389  chan->priority = oldframe->priority;
390 
391  gosub_release_frame(chan, oldframe);
392 
393  /* Set a return value, if any */
394  pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", S_OR(retval, ""));
395  ast_channel_unlock(chan);
396  return res;
397 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int priority
Definition: channel.h:841
#define ast_test_flag(p, flag)
Definition: utils.h:63
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define LOG_ERROR
Definition: logger.h:155
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
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static struct ast_datastore_info stack_info
Definition: app_stack.c:215
unsigned int is_special
Definition: app_stack.c:227
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
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
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
char extension[0]
Definition: app_stack.c:229
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static void gosub_release_frame(struct ast_channel *chan, struct gosub_stack_frame *frame)
Definition: app_stack.c:265
static int stackpeek_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  str,
ssize_t  len 
)
static

Definition at line 793 of file app_stack.c.

References args, AST_APP_ARG, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_skip_blanks(), AST_STANDARD_APP_ARGS, ast_str_set(), ast_strdupa, ast_strlen_zero(), ast_true(), gosub_stack_frame::context, ast_datastore::data, gosub_stack_frame::entries, gosub_stack_frame::extension, LOG_ERROR, and gosub_stack_frame::priority.

794 {
795  struct ast_datastore *stack_store;
796  struct gosub_stack_list *oldlist;
797  struct gosub_stack_frame *frame;
798  int n;
800  AST_APP_ARG(n);
801  AST_APP_ARG(which);
802  AST_APP_ARG(suppress);
803  );
804 
805  if (!chan) {
806  ast_log(LOG_ERROR, "STACK_PEEK must be called on an active channel\n");
807  return -1;
808  }
809 
810  data = ast_strdupa(data);
812 
813  if (ast_strlen_zero(args.n) || ast_strlen_zero(args.which)) {
814  ast_log(LOG_ERROR, "STACK_PEEK requires parameters n and which\n");
815  return -1;
816  }
817 
818  n = atoi(args.n);
819  if (n <= 0) {
820  ast_log(LOG_ERROR, "STACK_PEEK must be called with a positive peek value\n");
821  return -1;
822  }
823 
824  ast_channel_lock(chan);
825  if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
826  if (!ast_true(args.suppress)) {
827  ast_log(LOG_ERROR, "STACK_PEEK called on a channel without a gosub stack\n");
828  }
829  ast_channel_unlock(chan);
830  return -1;
831  }
832 
833  oldlist = stack_store->data;
834 
835  AST_LIST_LOCK(oldlist);
836  AST_LIST_TRAVERSE(oldlist, frame, entries) {
837  if (--n == 0) {
838  break;
839  }
840  }
841 
842  if (!frame) {
843  /* Too deep */
844  if (!ast_true(args.suppress)) {
845  ast_log(LOG_ERROR, "Stack peek of '%s' is more stack frames than I have\n", args.n);
846  }
847  AST_LIST_UNLOCK(oldlist);
848  ast_channel_unlock(chan);
849  return -1;
850  }
851 
852  args.which = ast_skip_blanks(args.which);
853 
854  switch (args.which[0]) {
855  case 'l': /* label */
856  ast_str_set(str, len, "%s,%s,%d", frame->context, frame->extension, frame->priority - 1);
857  break;
858  case 'c': /* context */
859  ast_str_set(str, len, "%s", frame->context);
860  break;
861  case 'e': /* extension */
862  ast_str_set(str, len, "%s", frame->extension);
863  break;
864  case 'p': /* priority */
865  ast_str_set(str, len, "%d", frame->priority - 1);
866  break;
867  default:
868  ast_log(LOG_ERROR, "Unknown argument '%s' to STACK_PEEK\n", args.which);
869  break;
870  }
871 
872  AST_LIST_UNLOCK(oldlist);
873  ast_channel_unlock(chan);
874 
875  return 0;
876 }
struct gosub_stack_frame::@64 entries
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
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
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:97
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
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static struct ast_datastore_info stack_info
Definition: app_stack.c:215
void * data
Definition: datastore.h:56
char extension[0]
Definition: app_stack.c:229
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static int unload_module ( void  )
static

Definition at line 1228 of file app_stack.c.

References ast_agi_unregister(), ast_custom_function_unregister(), ast_install_stack_functions(), ast_unregister_application(), gosub_agi_command, local_function, peek_function, ast_module_info::self, and stackpeek_function.

1229 {
1231 
1233 
1241 
1242  return 0;
1243 }
static const char app_gosub[]
Definition: app_stack.c:208
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
static struct ast_custom_function stackpeek_function
Definition: app_stack.c:878
static const char app_return[]
Definition: app_stack.c:210
struct ast_module * self
Definition: module.h:227
static struct ast_custom_function peek_function
Definition: app_stack.c:788
static struct agi_command gosub_agi_command
Definition: app_stack.c:1225
void ast_install_stack_functions(const struct ast_app_stack_funcs *funcs)
Set stack application function callbacks.
Definition: app.c:319
static const char app_pop[]
Definition: app_stack.c:211
static const char app_gosubif[]
Definition: app_stack.c:209
int ast_agi_unregister(struct ast_module *mod, agi_command *cmd)
Unregisters an AGI command.
Definition: res_agi.c:3169
static struct ast_custom_function local_function
Definition: app_stack.c:747

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_LOAD_ORDER , .description = "Dialplan subroutines (Gosub, Return, etc)" , .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_APP_DEPEND, .nonoptreq = "res_agi", }
static

Definition at line 1274 of file app_stack.c.

const char app_gosub[] = "Gosub"
static

Definition at line 208 of file app_stack.c.

const char app_gosubif[] = "GosubIf"
static

Definition at line 209 of file app_stack.c.

const char app_pop[] = "StackPop"
static

Definition at line 211 of file app_stack.c.

const char app_return[] = "Return"
static

Definition at line 210 of file app_stack.c.

Definition at line 1274 of file app_stack.c.

struct agi_command gosub_agi_command
static
Initial value:
=
{ { "gosub", NULL }, handle_gosub, NULL, NULL, 0 }
static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, const char *const *argv)
Definition: app_stack.c:1075

Definition at line 1225 of file app_stack.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function local_function
static
Initial value:
= {
.name = "LOCAL",
.write = local_write,
.read = local_read,
}
static int local_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
Definition: app_stack.c:715
static int local_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: app_stack.c:675

Definition at line 747 of file app_stack.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function peek_function
static
Initial value:
= {
.name = "LOCAL_PEEK",
.read = peek_read,
}
static int peek_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: app_stack.c:753

Definition at line 788 of file app_stack.c.

Referenced by load_module(), and unload_module().

struct ast_datastore_info stack_info
static
Initial value:
= {
.type = "GOSUB",
.destroy = gosub_free,
}
static void gosub_free(void *data)
Definition: app_stack.c:300

Definition at line 215 of file app_stack.c.

struct ast_custom_function stackpeek_function
static
Initial value:
= {
.name = "STACK_PEEK",
.read2 = stackpeek_read,
}
static int stackpeek_read(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
Definition: app_stack.c:793

Definition at line 878 of file app_stack.c.

Referenced by load_module(), and unload_module().