287 sprintf(local_buffer,
"LOCAL(%s)",
var);
314 int len_extension = strlen(
extension) + 1;
315 int len_context = strlen(
context) + 1;
317 if ((
new =
ast_calloc(1,
sizeof(*
new) + len_extension + len_context))) {
320 new->context =
new->extension + len_extension;
357 oldlist = stack_store->
data;
383 const char *
retval = data;
393 oldlist = stack_store->
data;
460 label =
strsep(&parse,
"(");
464 endparen = strrchr(parse,
')');
474 exten =
strsep(&label,
",");
475 pri =
strsep(&label,
",");
495 len = strlen(
context) + strlen(exten) + strlen(pri) + 3;
497 len += 2 + strlen(parse);
502 snprintf(new_args,
len,
"%s,%s,%s",
context, exten, pri);
504 snprintf(new_args,
len,
"%s,%s,%s(%s)",
context, exten, pri, parse);
509 ast_debug(4,
"Gosub args:%s new_args:%s\n",
args, new_args ? new_args :
"");
528 int orig_in_subroutine;
549 label =
strsep(&parse,
"(");
553 endparen = strrchr(parse,
')');
591 ast_log(
LOG_ERROR,
"%s attempted to reach non-existent destination '%s,%s,%d' from '%s,%s,%d'",
592 app_gosub, dest_context, dest_exten, dest_priority, orig_context,
orig_exten, orig_priority);
602 ast_debug(1,
"Channel %s has no datastore, so we're allocating one.\n",
608 goto error_exit_locked;
616 goto error_exit_locked;
620 stack_store->
data = oldlist;
623 oldlist = stack_store->
data;
631 if (args2.argc > max_argc) {
632 max_argc = args2.argc;
638 goto error_exit_locked;
642 for (i = 0; i < max_argc; i++) {
643 snprintf(argname,
sizeof(argname),
"ARG%d", i + 1);
644 frame_set_var(chan, newframe, argname, i < args2.argc ? args2.argval[i] :
"");
645 ast_debug(1,
"Setting '%s' to '%s'\n", argname, i < args2.argc ? args2.argval[i] :
"");
647 snprintf(argname,
sizeof(argname),
"%u", args2.argc);
686 ast_log(
LOG_WARNING,
"GosubIf requires an argument: GosubIf(cond?label1(args):label2(args)\n");
692 if (
cond.argc != 2) {
693 ast_log(
LOG_WARNING,
"GosubIf requires an argument: GosubIf(cond?label1(args):label2(args)\n");
727 oldlist = stack_store->
data;
767 oldlist = stack_store->
data;
823 .
name =
"LOCAL_PEEK",
854 ast_log(
LOG_ERROR,
"STACK_PEEK must be called with a positive peek value\n");
861 ast_log(
LOG_ERROR,
"STACK_PEEK called on a channel without a gosub stack\n");
867 oldlist = stack_store->
data;
888 switch (
args.which[0]) {
913 .
name =
"STACK_PEEK",
939 oldlist = stack_store->
data;
968 const char *saved_context;
969 const char *saved_exten;
971 int saved_hangup_flags;
972 int saved_autoloopflag;
973 int saved_in_subroutine;
978 ast_verb(3,
"%s Internal %s(%s) start\n",
984 if (saved_hangup_flags) {
1001 saved_context, saved_exten, saved_priority);
1020 oldlist = stack_store->
data;
1039 ast_log(
LOG_ERROR,
"%s An async goto just messed up our execution location.\n",
1061 ast_debug(1,
"Spawn extension (%s,%s,%d) exited with %d on '%s'\n",
1064 ast_verb(2,
"Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
1073 ast_verb(3,
"%s Internal %s(%s) complete GOSUB_RETVAL=%s\n",
1077 ast_log(
LOG_WARNING,
"%s Abnormal '%s(%s)' exit. Popping routine return locations.\n",
1105 if (saved_hangup_flags) {
1118 int old_autoloopflag;
1119 int old_in_subroutine;
1121 const char *old_context;
1122 const char *old_extension;
1125 if (argc < 4 || argc > 5) {
1129 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] :
"");
1136 ast_log(
LOG_ERROR,
"Priority '%s' not found in '%s@%s'\n", argv[3], argv[2], argv[1]);
1137 ast_agi_send(agi->
fd, chan,
"200 result=-1 Gosub label not found\n");
1142 ast_agi_send(agi->
fd, chan,
"200 result=-1 Gosub label not found\n");
1156 ast_agi_send(agi->
fd, chan,
"503 result=-2 Memory allocation failure\n");
1177 old_context, old_extension, old_priority);
1195 oldlist = stack_store->
data;
1207 args.no_hangup_chan = 1;
1230 ast_verb(3,
"%s AGI %s(%s) complete GOSUB_RETVAL=%s\n",
1235 ast_log(
LOG_NOTICE,
"%s Abnormal AGI %s(%s) exit. Popping routine return locations.\n",
1244 abnormal_exit ?
" (abnormal exit)" :
"");
1246 ast_agi_send(agi->
fd, chan,
"200 result=%d Gosub failed\n", res);
1320 .optional_modules =
"res_agi",
AGI Extension interfaces - Asterisk Gateway Interface.
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
int ast_agi_register(struct ast_module *mod, agi_command *cmd)
Registers an AGI command.
int ast_agi_unregister(agi_command *cmd)
Unregisters an AGI command.
static void gosub_release_frame(struct ast_channel *chan, struct gosub_stack_frame *frame)
static int gosubif_exec(struct ast_channel *chan, const char *data)
static struct ast_custom_function local_function
static int gosub_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 gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_hangup)
static const char * expand_gosub_args(struct ast_channel *chan, const char *args)
static int stackpeek_read(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
static int local_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
static struct agi_command gosub_agi_command
static int local_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int return_exec(struct ast_channel *chan, const char *data)
static void gosub_free(void *data)
static const char app_return[]
static const char app_gosub[]
static struct ast_custom_function peek_function
static int frame_set_var(struct ast_channel *chan, struct gosub_stack_frame *frame, const char *var, const char *value)
static struct gosub_stack_frame * gosub_allocate_frame(const char *context, const char *extension, int priority, int in_subroutine, unsigned char arguments)
static void balance_stack(struct ast_channel *chan)
static const struct ast_datastore_info stack_info
static const char app_gosubif[]
static const char app_pop[]
static int load_module(void)
static int peek_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int unload_module(void)
static struct ast_custom_function stackpeek_function
static int pop_exec(struct ast_channel *chan, const char *data)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define ast_channel_lock(chan)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
@ AST_SOFTHANGUP_ASYNCGOTO
void ast_channel_context_set(struct ast_channel *chan, const char *value)
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
@ AST_FLAG_SUBROUTINE_EXEC
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
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.
const char * ast_var_name(const struct ast_var_t *var)
#define ast_var_assign(name, value)
const char * ast_var_value(const struct ast_var_t *var)
void ast_var_delete(struct ast_var_t *var)
#define ast_datastore_alloc(info, uid)
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_publish_varset for a channel.
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_STANDARD_RAW_ARGS(args, parse)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
void ast_install_stack_functions(const struct ast_app_stack_funcs *funcs)
Set stack application function callbacks.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_RAW_ARGS(args, parse, sep)
char * strsep(char **str, const char *delims)
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Core PBX routines and definitions.
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.
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
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.
#define ast_custom_function_register(acf)
Register a custom function.
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
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.
int pbx_checkcondition(const char *condition)
Evaluate a condition.
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
static char * orig_exten(int fd, const char *chan, const char *data)
orginate from extension
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
static force_inline int attribute_pure ast_strlen_zero(const char *s)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Stack applications callback functions.
int(* run_sub)(struct ast_channel *chan, const char *args, int ignore_hangup)
Callback for the routine to run a subroutine on a channel.
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Structure for a data store type.
Structure for a data store object.
Options for ast_pbx_run()
Support for dynamic strings.
struct ast_var_t::@211 entries
structure to hold extensions
unsigned int in_subroutine
struct gosub_stack_frame::@81 entries
#define ast_test_flag(p, flag)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_set2_flag(p, value, flag)
#define ast_set_flag(p, flag)