Core PBX routines and definitions. More...
#include "asterisk/channel.h"
#include "asterisk/sched.h"
#include "asterisk/devicestate.h"
#include "asterisk/chanvars.h"
#include "asterisk/hashtab.h"
#include "asterisk/stringfields.h"
#include "asterisk/xmldoc.h"
#include "asterisk/frame_defs.h"
Go to the source code of this file.
Data Structures | |
struct | ast_custom_function |
Data structure associated with a custom dialplan function. More... | |
struct | ast_pbx |
struct | ast_pbx_args |
Options for ast_pbx_run(). More... | |
struct | ast_switch |
struct | ast_timing |
struct | pbx_find_info |
Defines | |
#define | ast_custom_function_register(acf) __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function. | |
#define | ast_custom_function_register_escalating(acf, escalation) __ast_custom_function_register_escalating(acf, escalation, ast_module_info->self) |
Register a custom function which requires escalated privileges. | |
#define | AST_MAX_APP 32 |
#define | AST_PBX_GOTO_FAILED -3 |
#define | AST_PBX_KEEP 0 |
#define | AST_PBX_MAX_STACK 128 |
#define | AST_PBX_REPLACE 1 |
#define | PRIORITY_HINT -1 |
#define | STATUS_NO_CONTEXT 1 |
#define | STATUS_NO_EXTENSION 2 |
#define | STATUS_NO_LABEL 4 |
#define | STATUS_NO_PRIORITY 3 |
#define | STATUS_SUCCESS 5 |
Typedefs | |
typedef void(* | ast_state_cb_destroy_type )(int id, void *data) |
Typedef for devicestate and hint callback removal indication callback. | |
typedef int(* | ast_state_cb_type )(char *context, char *id, enum ast_extension_states state, void *data) |
Typedef for devicestate and hint callbacks. | |
typedef int( | ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
All switch functions have the same interface, so define a type for them. | |
Enumerations | |
enum | ast_custom_function_escalation { AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, AST_CFE_BOTH } |
Description of the ways in which a function may escalate privileges. More... | |
enum | ast_ext_matchcid_types { AST_EXT_MATCHCID_OFF = 0, AST_EXT_MATCHCID_ON = 1, AST_EXT_MATCHCID_ANY = 2 } |
extension matchcid types More... | |
enum | ast_extension_states { AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0, AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4 } |
Extension states. More... | |
enum | ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 } |
The result codes when starting the PBX on a channel with ast_pbx_start. More... | |
enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22, E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
Register a custom function. | |
int | __ast_custom_function_register_escalating (struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod) |
Register a custom function which requires escalated privileges. | |
int | ast_active_calls (void) |
Retrieve the number of active calls. | |
int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add and extension to an extension context. | |
int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add an extension to an extension context, this time with an ast_context *. | |
int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
Set the channel to next execute the specified dialplan location. | |
int | ast_async_goto_by_name (const char *chan, const char *context, const char *exten, int priority) |
Set the channel to next execute the specified dialplan location. | |
int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_build_timing (struct ast_timing *i, const char *info) |
Construct a timing bitmap, for use in time-based conditionals. | |
int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks for a valid matching extension. | |
int | ast_check_timing (const struct ast_timing *i) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified. | |
int | ast_check_timing2 (const struct ast_timing *i, const struct timeval tv) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified. | |
char * | ast_complete_applications (const char *line, const char *word, int state) |
Command completion for the list of installed applications. | |
int | ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
Add an ignorepat. | |
int | ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
Add a context include. | |
int | ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar) |
Add a context include. | |
int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
Add a switch. | |
int | ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar) |
Adds a switch (first param is a ast_context). | |
void | ast_context_destroy (struct ast_context *con, const char *registrar) |
Destroy a context (matches the specified context (or ANY context if NULL). | |
struct ast_context * | ast_context_find (const char *name) |
Find a context. | |
struct ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
Register a new context or find an existing one. | |
int | ast_context_lockmacro (const char *macrocontext) |
locks the macrolock in the given given context | |
int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
Remove a context include. | |
int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
Removes an include by an ast_context structure. | |
int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
Remove a switch. | |
int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
This function locks given context, removes switch, unlock context and return. | |
int | ast_context_unlockmacro (const char *macrocontext) |
Unlocks the macrolock in the given context. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
struct ast_custom_function * | ast_custom_function_find (const char *name) |
int | ast_custom_function_unregister (struct ast_custom_function *acf) |
Unregister a custom function. | |
int | ast_destroy_timing (struct ast_timing *i) |
Deallocates memory structures associated with a timing bitmap. | |
enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
Map devstate to an extension state. | |
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 | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_extension_close (const char *pattern, const char *data, int needmore) |
int | ast_extension_cmp (const char *a, const char *b) |
Determine if one extension should match before another. | |
int | ast_extension_match (const char *pattern, const char *extension) |
Determine if a given extension matches a given pattern (in NXX format). | |
int | ast_extension_patmatch (const char *pattern, const char *data) |
int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
Uses hint and devicestate callback to get the state of an extension. | |
const char * | ast_extension_state2str (int extension_state) |
Return string representation of the state of an extension. | |
int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data) |
Registers a state change callback. | |
int | ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data) |
Registers a state change callback with destructor. | |
int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
Deletes a registered state change callback by ID. | |
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. | |
int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
Find the priority of an extension that has the specified label. | |
int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
executes a read operation on a function | |
int | ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen) |
executes a read operation on a function | |
int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
executes a write operation on a function | |
int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
If an extension hint exists, return non-zero. | |
int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
int | ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
enum ast_pbx_result | ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args) |
Execute the PBX in the current thread. | |
enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
Create a new thread and start the PBX. | |
int | ast_processed_calls (void) |
Retrieve the total number of calls processed through the PBX since last restart. | |
int | ast_rdlock_context (struct ast_context *con) |
Read locks a given context. | |
int | ast_rdlock_contexts (void) |
Read locks the context list. | |
int | ast_register_switch (struct ast_switch *sw) |
Register an alternative dialplan switch. | |
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_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten) |
If an extension hint exists, return non-zero. | |
int | ast_thread_inhibit_escalations (void) |
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect. | |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts (void) |
Unlocks contexts. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
int | ast_wrlock_context (struct ast_context *con) |
Write locks a given context. | |
int | ast_wrlock_contexts (void) |
Write locks the context list. | |
void | pbx_builtin_clear_globals (void) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
Return a pointer to the value of the corresponding channel variable. | |
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_builtin_raise_exception (struct ast_channel *chan, const char *data) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
Create a human-readable string, specifying all variables and their corresponding values. | |
int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *data) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
Execute an application. | |
struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
struct ast_app * | pbx_findapp (const char *app) |
Look up an application. | |
void | pbx_live_dangerously (int new_live_dangerously) |
Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.). | |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
Retrieve the value of a builtin variable or variable from the channel variable stack. | |
int | pbx_set_autofallthrough (int newval) |
int | pbx_set_extenpatternmatchnew (int newval) |
void | pbx_set_overrideswitch (const char *newval) |
Registrar info functions ... | |
const char * | ast_get_context_registrar (struct ast_context *c) |
const char * | ast_get_extension_registrar (struct ast_exten *e) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
Other Extension stuff | |
const char * | ast_get_extension_app (struct ast_exten *e) |
void * | ast_get_extension_app_data (struct ast_exten *e) |
const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
const char * | ast_get_extension_label (struct ast_exten *e) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
int | ast_get_extension_priority (struct ast_exten *exten) |
Substitution routines, using dynamic string buffers | |
const char * | ast_str_retrieve_variable (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var) |
void | ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ) |
void | ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used) |
void | ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ) |
Walking functions ... | |
struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
struct ast_context * | ast_walk_contexts (struct ast_context *con) |
struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
Substitution routines, using static string buffers | |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
| |
#define | AST_PBX_ERROR 1 |
#define | AST_PBX_HANGUP -1 |
Special return values from applications to the PBX. | |
#define | AST_PBX_INCOMPLETE 12 |
#define | AST_PBX_OK 0 |
int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
Simply remove extension from context. | |
int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar) |
int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked) |
const char * | ast_get_context_name (struct ast_context *con) |
struct ast_context * | ast_get_extension_context (struct ast_exten *exten) |
const char * | ast_get_extension_name (struct ast_exten *exten) |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *include) |
const char * | ast_get_switch_data (struct ast_sw *sw) |
int | ast_get_switch_eval (struct ast_sw *sw) |
const char * | ast_get_switch_name (struct ast_sw *sw) |
int | ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b) |
hashtable functions for contexts | |
unsigned int | ast_hashtab_hash_contexts (const void *obj) |
Core PBX routines and definitions.
Definition in file pbx.h.
#define ast_custom_function_register | ( | acf | ) | __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function.
Definition at line 1164 of file pbx.h.
Referenced by load_module(), and reload().
#define ast_custom_function_register_escalating | ( | acf, | |||
escalation | ) | __ast_custom_function_register_escalating(acf, escalation, ast_module_info->self) |
Register a custom function which requires escalated privileges.
Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).
Definition at line 1173 of file pbx.h.
Referenced by load_module().
#define AST_MAX_APP 32 |
Max length of an application
Definition at line 39 of file pbx.h.
Referenced by handle_show_function(), print_app_docs(), sla_build_station(), and sla_station_destructor().
#define AST_PBX_ERROR 1 |
#define AST_PBX_GOTO_FAILED -3 |
Definition at line 41 of file pbx.h.
Referenced by __ast_goto_if_exists().
#define AST_PBX_HANGUP -1 |
#define AST_PBX_INCOMPLETE 12 |
Return to PBX matching, allowing more digits for the extension
Definition at line 50 of file pbx.h.
Referenced by __ast_pbx_run(), dial_exec_full(), pbx_builtin_incomplete(), and retrydial_exec().
#define PRIORITY_HINT -1 |
Special Priority for a hint
Definition at line 53 of file pbx.h.
Referenced by add_extensions(), add_priority(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_space(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), pbx_load_config(), print_ext(), sla_build_station(), and sla_station_destructor().
typedef void(* ast_state_cb_destroy_type)(int id, void *data) |
typedef int(* ast_state_cb_type)(char *context, char *id, enum ast_extension_states state, void *data) |
typedef int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Description of the ways in which a function may escalate privileges.
Definition at line 1154 of file pbx.h.
01154 { 01155 AST_CFE_NONE, 01156 AST_CFE_READ, 01157 AST_CFE_WRITE, 01158 AST_CFE_BOTH, 01159 };
extension matchcid types
Definition at line 76 of file pbx.h.
00076 { 00077 AST_EXT_MATCHCID_OFF = 0, /*!< Match only extensions with matchcid=0 */ 00078 AST_EXT_MATCHCID_ON = 1, /*!< Match only extensions with matchcid=1 AND cidmatch matches */ 00079 AST_EXT_MATCHCID_ANY = 2, /*!< Match both - used only in functions manipulating ast_exten's */ 00080 };
enum ast_extension_states |
Extension states.
Definition at line 60 of file pbx.h.
00060 { 00061 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */ 00062 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */ 00063 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */ 00064 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */ 00065 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ 00066 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ 00067 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ 00068 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ 00069 };
enum ast_pbx_result |
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition at line 299 of file pbx.h.
00299 { 00300 AST_PBX_SUCCESS = 0, 00301 AST_PBX_FAILED = -1, 00302 AST_PBX_CALL_LIMIT = -2, 00303 };
enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows.
E_MATCHMORE | |
E_CANMATCH | |
E_MATCH | |
E_MATCH_MASK | |
E_SPAWN | |
E_FINDLABEL | |
E_MATCHMORE | |
E_CANMATCH | |
E_MATCH | |
E_MATCH_MASK | |
E_SPAWN | |
E_FINDLABEL |
Definition at line 1251 of file pbx.h.
01251 { 01252 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01253 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01254 E_MATCH = 0x02, /* extension is an exact match */ 01255 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01256 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01257 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01258 };
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3900 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by __ast_custom_function_register_escalating(), and load_pbx().
03901 { 03902 struct ast_custom_function *cur; 03903 char tmps[80]; 03904 03905 if (!acf) { 03906 return -1; 03907 } 03908 03909 acf->mod = mod; 03910 #ifdef AST_XML_DOCS 03911 acf->docsrc = AST_STATIC_DOC; 03912 #endif 03913 03914 if (acf_retrieve_docs(acf)) { 03915 return -1; 03916 } 03917 03918 AST_RWLIST_WRLOCK(&acf_root); 03919 03920 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03921 if (!strcmp(acf->name, cur->name)) { 03922 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03923 AST_RWLIST_UNLOCK(&acf_root); 03924 return -1; 03925 } 03926 } 03927 03928 /* Store in alphabetical order */ 03929 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03930 if (strcasecmp(acf->name, cur->name) < 0) { 03931 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03932 break; 03933 } 03934 } 03935 AST_RWLIST_TRAVERSE_SAFE_END; 03936 03937 if (!cur) { 03938 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03939 } 03940 03941 AST_RWLIST_UNLOCK(&acf_root); 03942 03943 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03944 03945 return 0; 03946 }
int __ast_custom_function_register_escalating | ( | struct ast_custom_function * | acf, | |
enum ast_custom_function_escalation | escalation, | |||
struct ast_module * | mod | |||
) |
Register a custom function which requires escalated privileges.
Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).
Definition at line 3948 of file pbx.c.
References __ast_custom_function_register(), ast_custom_escalating_function::acf, ast_calloc, AST_CFE_BOTH, AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, ast_custom_function_unregister(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_custom_escalating_function::read_escalates, and ast_custom_escalating_function::write_escalates.
03949 { 03950 struct ast_custom_escalating_function *acf_escalation = NULL; 03951 int res; 03952 03953 res = __ast_custom_function_register(acf, mod); 03954 if (res != 0) { 03955 return -1; 03956 } 03957 03958 if (escalation == AST_CFE_NONE) { 03959 /* No escalations; no need to do anything else */ 03960 return 0; 03961 } 03962 03963 acf_escalation = ast_calloc(1, sizeof(*acf_escalation)); 03964 if (!acf_escalation) { 03965 ast_custom_function_unregister(acf); 03966 return -1; 03967 } 03968 03969 acf_escalation->acf = acf; 03970 switch (escalation) { 03971 case AST_CFE_NONE: 03972 break; 03973 case AST_CFE_READ: 03974 acf_escalation->read_escalates = 1; 03975 break; 03976 case AST_CFE_WRITE: 03977 acf_escalation->write_escalates = 1; 03978 break; 03979 case AST_CFE_BOTH: 03980 acf_escalation->read_escalates = 1; 03981 acf_escalation->write_escalates = 1; 03982 break; 03983 } 03984 03985 AST_RWLIST_WRLOCK(&escalation_root); 03986 AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list); 03987 AST_RWLIST_UNLOCK(&escalation_root); 03988 03989 return 0; 03990 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5885 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05886 { 05887 return countcalls; 05888 }
int ast_add_extension | ( | const char * | context, | |
int | replace, | |||
const char * | extension, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
const char * | application, | |||
void * | data, | |||
void(*)(void *) | datad, | |||
const char * | registrar | |||
) |
Add and extension to an extension context.
context | context to add the extension to | |
replace | ||
extension | extension to add | |
priority | priority level of extension addition | |
label | extension label | |
callerid | pattern to match CallerID, or NULL to match any CallerID | |
application | application to run on the extension with that priority level | |
data | data to pass to the application | |
datad | ||
registrar | who registered the extension |
0 | success | |
-1 | failure |
Definition at line 8645 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().
08648 { 08649 int ret = -1; 08650 struct ast_context *c; 08651 08652 c = find_context_locked(context); 08653 if (c) { 08654 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08655 application, data, datad, registrar); 08656 ast_unlock_contexts(); 08657 } 08658 08659 return ret; 08660 }
int ast_add_extension2 | ( | struct ast_context * | con, | |
int | replace, | |||
const char * | extension, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
const char * | application, | |||
void * | data, | |||
void(*)(void *) | datad, | |||
const char * | registrar | |||
) |
Add an extension to an extension context, this time with an ast_context *.
Add an extension to an extension context, this time with an ast_context *.
We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.
The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.
EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set
Definition at line 9006 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
09010 { 09011 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 09012 application, data, datad, registrar, 1); 09013 }
int ast_async_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Set the channel to next execute the specified dialplan location.
Definition at line 8685 of file pbx.c.
References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmf(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().
08686 { 08687 int res = 0; 08688 struct ast_channel *tmpchan; 08689 struct { 08690 char *accountcode; 08691 char *exten; 08692 char *context; 08693 char *linkedid; 08694 char *name; 08695 struct ast_cdr *cdr; 08696 int amaflags; 08697 int state; 08698 format_t readformat; 08699 format_t writeformat; 08700 } tmpvars = { 0, }; 08701 08702 ast_channel_lock(chan); 08703 if (chan->pbx) { /* This channel is currently in the PBX */ 08704 ast_explicit_goto(chan, context, exten, priority + 1); 08705 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08706 ast_channel_unlock(chan); 08707 return res; 08708 } 08709 08710 /* In order to do it when the channel doesn't really exist within 08711 * the PBX, we have to make a new channel, masquerade, and start the PBX 08712 * at the new location */ 08713 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08714 tmpvars.exten = ast_strdupa(chan->exten); 08715 tmpvars.context = ast_strdupa(chan->context); 08716 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08717 tmpvars.name = ast_strdupa(chan->name); 08718 tmpvars.amaflags = chan->amaflags; 08719 tmpvars.state = chan->_state; 08720 tmpvars.writeformat = chan->writeformat; 08721 tmpvars.readformat = chan->readformat; 08722 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08723 08724 ast_channel_unlock(chan); 08725 08726 /* Do not hold any channel locks while calling channel_alloc() since the function 08727 * locks the channel container when linking the new channel in. */ 08728 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08729 ast_cdr_discard(tmpvars.cdr); 08730 return -1; 08731 } 08732 08733 /* copy the cdr info over */ 08734 if (tmpvars.cdr) { 08735 ast_cdr_discard(tmpchan->cdr); 08736 tmpchan->cdr = tmpvars.cdr; 08737 tmpvars.cdr = NULL; 08738 } 08739 08740 /* Make formats okay */ 08741 tmpchan->readformat = tmpvars.readformat; 08742 tmpchan->writeformat = tmpvars.writeformat; 08743 08744 /* Setup proper location. Never hold another channel lock while calling this function. */ 08745 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08746 08747 /* Masquerade into tmp channel */ 08748 if (ast_channel_masquerade(tmpchan, chan)) { 08749 /* Failed to set up the masquerade. It's probably chan_local 08750 * in the middle of optimizing itself out. Sad. :( */ 08751 ast_hangup(tmpchan); 08752 tmpchan = NULL; 08753 res = -1; 08754 } else { 08755 ast_do_masquerade(tmpchan); 08756 /* Start the PBX going on our stolen channel */ 08757 if (ast_pbx_start(tmpchan)) { 08758 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08759 ast_hangup(tmpchan); 08760 res = -1; 08761 } 08762 } 08763 08764 return res; 08765 }
int ast_async_goto_by_name | ( | const char * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Set the channel to next execute the specified dialplan location.
Definition at line 8767 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08768 { 08769 struct ast_channel *chan; 08770 int res = -1; 08771 08772 if ((chan = ast_channel_get_by_name(channame))) { 08773 res = ast_async_goto(chan, context, exten, priority); 08774 chan = ast_channel_unref(chan); 08775 } 08776 08777 return res; 08778 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11125 of file pbx.c.
References __ast_goto_if_exists().
11126 { 11127 return __ast_goto_if_exists(chan, context, exten, priority, 1); 11128 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11190 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
11191 { 11192 return pbx_parseable_goto(chan, goto_string, 1); 11193 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info | |||
) |
Construct a timing bitmap, for use in time-based conditionals.
i | Pointer to an ast_timing structure. | |
info | Standard string containing a timerange, weekday range, monthday range, and month range, as well as an optional timezone. |
Returns | 1 on success or 0 on failure. |
Definition at line 8268 of file pbx.c.
References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
08269 { 08270 char *info; 08271 int j, num_fields, last_sep = -1; 08272 08273 i->timezone = NULL; 08274 08275 /* Check for empty just in case */ 08276 if (ast_strlen_zero(info_in)) { 08277 return 0; 08278 } 08279 08280 /* make a copy just in case we were passed a static string */ 08281 info = ast_strdupa(info_in); 08282 08283 /* count the number of fields in the timespec */ 08284 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08285 if (info[j] == ',') { 08286 last_sep = j; 08287 num_fields++; 08288 } 08289 } 08290 08291 /* save the timezone, if it is specified */ 08292 if (num_fields == 5) { 08293 i->timezone = ast_strdup(info + last_sep + 1); 08294 } 08295 08296 /* Assume everything except time */ 08297 i->monthmask = 0xfff; /* 12 bits */ 08298 i->daymask = 0x7fffffffU; /* 31 bits */ 08299 i->dowmask = 0x7f; /* 7 bits */ 08300 /* on each call, use strsep() to move info to the next argument */ 08301 get_timerange(i, strsep(&info, "|,")); 08302 if (info) 08303 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08304 if (info) 08305 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08306 if (info) 08307 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08308 return 1; 08309 }
int ast_canmatch_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
Looks for a valid matching extension.
c | not really important | |
context | context to serach within | |
exten | extension to check | |
priority | priority of extension path | |
callerid | callerid of extension being searched for |
Definition at line 5369 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
05370 { 05371 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05372 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
i | Pointer to an ast_timing structure. |
Returns | 1, if the time matches or 0, if the current time falls outside of the specified range. |
Definition at line 8311 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08312 { 08313 return ast_check_timing2(i, ast_tvnow()); 08314 }
int ast_check_timing2 | ( | const struct ast_timing * | i, | |
const struct timeval | tv | |||
) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
i | Pointer to an ast_timing structure. | |
tv | Specified time |
Returns | 1, if the time matches or 0, if the time falls outside of the specified range. |
Definition at line 8316 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by ast_check_timing(), and pbx_builtin_gotoiftime().
08317 { 08318 struct ast_tm tm; 08319 08320 ast_localtime(&tv, &tm, i->timezone); 08321 08322 /* If it's not the right month, return */ 08323 if (!(i->monthmask & (1 << tm.tm_mon))) 08324 return 0; 08325 08326 /* If it's not that time of the month.... */ 08327 /* Warning, tm_mday has range 1..31! */ 08328 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08329 return 0; 08330 08331 /* If it's not the right day of the week */ 08332 if (!(i->dowmask & (1 << tm.tm_wday))) 08333 return 0; 08334 08335 /* Sanity check the hour just to be safe */ 08336 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08337 ast_log(LOG_WARNING, "Insane time...\n"); 08338 return 0; 08339 } 08340 08341 /* Now the tough part, we calculate if it fits 08342 in the right time based on min/hour */ 08343 if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min)))) 08344 return 0; 08345 08346 /* If we got this far, then we're good */ 08347 return 1; 08348 }
char* ast_complete_applications | ( | const char * | line, | |
const char * | word, | |||
int | state | |||
) |
Command completion for the list of installed applications.
This can be called from a CLI command completion function that wants to complete from the list of available applications.
Definition at line 11195 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::name.
Referenced by handle_orig(), and handle_show_application().
11196 { 11197 struct ast_app *app = NULL; 11198 int which = 0; 11199 char *ret = NULL; 11200 size_t wordlen = strlen(word); 11201 11202 AST_RWLIST_RDLOCK(&apps); 11203 AST_RWLIST_TRAVERSE(&apps, app, list) { 11204 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 11205 ret = ast_strdup(app->name); 11206 break; 11207 } 11208 } 11209 AST_RWLIST_UNLOCK(&apps); 11210 11211 return ret; 11212 }
int ast_context_add_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Add an ignorepat.
context | which context to add the ignorpattern to | |
ignorepat | ignorepattern to set up for the extension | |
registrar | registrar of the ignore pattern |
Adds an ignore pattern to a particular context.
0 | on success | |
-1 | on failure |
Definition at line 8552 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08553 { 08554 int ret = -1; 08555 struct ast_context *c; 08556 08557 c = find_context_locked(context); 08558 if (c) { 08559 ret = ast_context_add_ignorepat2(c, value, registrar); 08560 ast_unlock_contexts(); 08561 } 08562 return ret; 08563 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8565 of file pbx.c.
References ast_calloc, ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08566 { 08567 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08568 int length; 08569 char *pattern; 08570 length = sizeof(struct ast_ignorepat); 08571 length += strlen(value) + 1; 08572 if (!(ignorepat = ast_calloc(1, length))) 08573 return -1; 08574 /* The cast to char * is because we need to write the initial value. 08575 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08576 * sees the cast as dereferencing a type-punned pointer and warns about 08577 * it. This is the workaround (we're telling gcc, yes, that's really 08578 * what we wanted to do). 08579 */ 08580 pattern = (char *) ignorepat->pattern; 08581 strcpy(pattern, value); 08582 ignorepat->next = NULL; 08583 ignorepat->registrar = registrar; 08584 ast_wrlock_context(con); 08585 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08586 ignorepatl = ignorepatc; 08587 if (!strcasecmp(ignorepatc->pattern, value)) { 08588 /* Already there */ 08589 ast_unlock_context(con); 08590 ast_free(ignorepat); 08591 errno = EEXIST; 08592 return -1; 08593 } 08594 } 08595 if (ignorepatl) 08596 ignorepatl->next = ignorepat; 08597 else 08598 con->ignorepats = ignorepat; 08599 ast_unlock_context(con); 08600 return 0; 08601 08602 }
int ast_context_add_include | ( | const char * | context, | |
const char * | include, | |||
const char * | registrar | |||
) |
Add a context include.
context | context to add include to | |
include | new include to add | |
registrar | who's registering it |
Adds an include taking a char * string as the context parameter
0 | on success | |
-1 | on error |
Definition at line 8096 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
08097 { 08098 int ret = -1; 08099 struct ast_context *c; 08100 08101 c = find_context_locked(context); 08102 if (c) { 08103 ret = ast_context_add_include2(c, include, registrar); 08104 ast_unlock_contexts(); 08105 } 08106 return ret; 08107 }
int ast_context_add_include2 | ( | struct ast_context * | con, | |
const char * | include, | |||
const char * | registrar | |||
) |
Add a context include.
con | context to add the include to | |
include | include to add | |
registrar | who registered the context |
Adds an include taking a struct ast_context as the first parameter
0 | on success | |
-1 | on failure |
Definition at line 8365 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.
Referenced by ast_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08367 { 08368 struct ast_include *new_include; 08369 char *c; 08370 struct ast_include *i, *il = NULL; /* include, include_last */ 08371 int length; 08372 char *p; 08373 08374 length = sizeof(struct ast_include); 08375 length += 2 * (strlen(value) + 1); 08376 08377 /* allocate new include structure ... */ 08378 if (!(new_include = ast_calloc(1, length))) 08379 return -1; 08380 /* Fill in this structure. Use 'p' for assignments, as the fields 08381 * in the structure are 'const char *' 08382 */ 08383 p = new_include->stuff; 08384 new_include->name = p; 08385 strcpy(p, value); 08386 p += strlen(value) + 1; 08387 new_include->rname = p; 08388 strcpy(p, value); 08389 /* Strip off timing info, and process if it is there */ 08390 if ( (c = strchr(p, ',')) ) { 08391 *c++ = '\0'; 08392 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08393 } 08394 new_include->next = NULL; 08395 new_include->registrar = registrar; 08396 08397 ast_wrlock_context(con); 08398 08399 /* ... go to last include and check if context is already included too... */ 08400 for (i = con->includes; i; i = i->next) { 08401 if (!strcasecmp(i->name, new_include->name)) { 08402 ast_destroy_timing(&(new_include->timing)); 08403 ast_free(new_include); 08404 ast_unlock_context(con); 08405 errno = EEXIST; 08406 return -1; 08407 } 08408 il = i; 08409 } 08410 08411 /* ... include new context into context list, unlock, return */ 08412 if (il) 08413 il->next = new_include; 08414 else 08415 con->includes = new_include; 08416 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08417 08418 ast_unlock_context(con); 08419 08420 return 0; 08421 }
int ast_context_add_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
int | eval, | |||
const char * | registrar | |||
) |
Add a switch.
context | context to which to add the switch | |
sw | switch to add | |
data | data to pass to switch | |
eval | whether to evaluate variables when running switch | |
registrar | whoever registered the switch |
This function registers a switch with the asterisk switch architecture
0 | on success | |
-1 | on failure |
Definition at line 8428 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08429 { 08430 int ret = -1; 08431 struct ast_context *c; 08432 08433 c = find_context_locked(context); 08434 if (c) { /* found, add switch to this context */ 08435 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08436 ast_unlock_contexts(); 08437 } 08438 return ret; 08439 }
int ast_context_add_switch2 | ( | struct ast_context * | con, | |
const char * | sw, | |||
const char * | data, | |||
int | eval, | |||
const char * | registrar | |||
) |
Adds a switch (first param is a ast_context).
Definition at line 8448 of file pbx.c.
References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_compile_ael2(), ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
08450 { 08451 struct ast_sw *new_sw; 08452 struct ast_sw *i; 08453 int length; 08454 char *p; 08455 08456 length = sizeof(struct ast_sw); 08457 length += strlen(value) + 1; 08458 if (data) 08459 length += strlen(data); 08460 length++; 08461 08462 /* allocate new sw structure ... */ 08463 if (!(new_sw = ast_calloc(1, length))) 08464 return -1; 08465 /* ... fill in this structure ... */ 08466 p = new_sw->stuff; 08467 new_sw->name = p; 08468 strcpy(new_sw->name, value); 08469 p += strlen(value) + 1; 08470 new_sw->data = p; 08471 if (data) { 08472 strcpy(new_sw->data, data); 08473 p += strlen(data) + 1; 08474 } else { 08475 strcpy(new_sw->data, ""); 08476 p++; 08477 } 08478 new_sw->eval = eval; 08479 new_sw->registrar = registrar; 08480 08481 /* ... try to lock this context ... */ 08482 ast_wrlock_context(con); 08483 08484 /* ... go to last sw and check if context is already swd too... */ 08485 AST_LIST_TRAVERSE(&con->alts, i, list) { 08486 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08487 ast_free(new_sw); 08488 ast_unlock_context(con); 08489 errno = EEXIST; 08490 return -1; 08491 } 08492 } 08493 08494 /* ... sw new context into context list, unlock, return */ 08495 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08496 08497 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08498 08499 ast_unlock_context(con); 08500 08501 return 0; 08502 }
void ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Destroy a context (matches the specified context (or ANY context if NULL).
con | context to destroy | |
registrar | who registered it |
You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.
Definition at line 9829 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), features_shutdown(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09830 { 09831 ast_wrlock_contexts(); 09832 __ast_context_destroy(contexts, contexts_table, con,registrar); 09833 ast_unlock_contexts(); 09834 }
struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
name | name of the context to find |
Will search for the context with the given name.
Definition at line 2925 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().
02926 { 02927 struct ast_context *tmp; 02928 struct fake_context item; 02929 02930 if (!name) { 02931 return NULL; 02932 } 02933 ast_rdlock_contexts(); 02934 if (contexts_table) { 02935 ast_copy_string(item.name, name, sizeof(item.name)); 02936 tmp = ast_hashtab_lookup(contexts_table, &item); 02937 } else { 02938 tmp = NULL; 02939 while ((tmp = ast_walk_contexts(tmp))) { 02940 if (!strcasecmp(name, tmp->name)) { 02941 break; 02942 } 02943 } 02944 } 02945 ast_unlock_contexts(); 02946 return tmp; 02947 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
const char * | name, | |||
const char * | registrar | |||
) | [read] |
Register a new context or find an existing one.
extcontexts | pointer to the ast_context structure pointer | |
exttable | pointer to the hashtable that contains all the elements in extcontexts | |
name | name of the new context | |
registrar | registrar of the context |
This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.
Definition at line 7680 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
07681 { 07682 struct ast_context *tmp, **local_contexts; 07683 struct fake_context search; 07684 int length = sizeof(struct ast_context) + strlen(name) + 1; 07685 07686 if (!contexts_table) { 07687 /* Protect creation of contexts_table from reentrancy. */ 07688 ast_wrlock_contexts(); 07689 if (!contexts_table) { 07690 contexts_table = ast_hashtab_create(17, 07691 ast_hashtab_compare_contexts, 07692 ast_hashtab_resize_java, 07693 ast_hashtab_newsize_java, 07694 ast_hashtab_hash_contexts, 07695 0); 07696 } 07697 ast_unlock_contexts(); 07698 } 07699 07700 ast_copy_string(search.name, name, sizeof(search.name)); 07701 if (!extcontexts) { 07702 ast_rdlock_contexts(); 07703 local_contexts = &contexts; 07704 tmp = ast_hashtab_lookup(contexts_table, &search); 07705 ast_unlock_contexts(); 07706 if (tmp) { 07707 tmp->refcount++; 07708 return tmp; 07709 } 07710 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07711 local_contexts = extcontexts; 07712 tmp = ast_hashtab_lookup(exttable, &search); 07713 if (tmp) { 07714 tmp->refcount++; 07715 return tmp; 07716 } 07717 } 07718 07719 if ((tmp = ast_calloc(1, length))) { 07720 ast_rwlock_init(&tmp->lock); 07721 ast_mutex_init(&tmp->macrolock); 07722 strcpy(tmp->name, name); 07723 tmp->root = NULL; 07724 tmp->root_table = NULL; 07725 tmp->registrar = ast_strdup(registrar); 07726 tmp->includes = NULL; 07727 tmp->ignorepats = NULL; 07728 tmp->refcount = 1; 07729 } else { 07730 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07731 return NULL; 07732 } 07733 07734 if (!extcontexts) { 07735 ast_wrlock_contexts(); 07736 tmp->next = *local_contexts; 07737 *local_contexts = tmp; 07738 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07739 ast_unlock_contexts(); 07740 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07741 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07742 } else { 07743 tmp->next = *local_contexts; 07744 if (exttable) 07745 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07746 07747 *local_contexts = tmp; 07748 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07749 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07750 } 07751 return tmp; 07752 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
macrocontext | name of the macro-context to lock |
Locks the given macro-context to ensure only one thread (call) can execute it at a time
0 | on success | |
-1 | on failure |
Definition at line 6260 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06261 { 06262 struct ast_context *c; 06263 int ret = -1; 06264 06265 c = find_context_locked(context); 06266 if (c) { 06267 ast_unlock_contexts(); 06268 06269 /* if we found context, lock macrolock */ 06270 ret = ast_mutex_lock(&c->macrolock); 06271 } 06272 06273 return ret; 06274 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
context | context to remove extension from | |
extension | which extension to remove | |
priority | priority of extension to remove (0 to remove all) | |
registrar | registrar of the extension |
This function removes an extension from a given context.
0 | on success | |
-1 | on failure |
Definition at line 6068 of file pbx.c.
References ast_context_remove_extension_callerid(), and AST_EXT_MATCHCID_ANY.
Referenced by register_peer_exten(), remove_exten_if_exist(), sla_station_destructor(), sla_trunk_destructor(), unregister_exten(), and UnregisterExtension().
06069 { 06070 return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar); 06071 }
int ast_context_remove_extension2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar, | |||
int | already_locked | |||
) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
Definition at line 6098 of file pbx.c.
References ast_context_remove_extension_callerid2(), and AST_EXT_MATCHCID_ANY.
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
06099 { 06100 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked); 06101 }
int ast_context_remove_extension_callerid | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcid, | |||
const char * | registrar | |||
) |
Definition at line 6073 of file pbx.c.
References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_context_remove_extension(), and handle_cli_dialplan_remove_extension().
06074 { 06075 int ret = -1; /* default error return */ 06076 struct ast_context *c; 06077 06078 c = find_context_locked(context); 06079 if (c) { /* ... remove extension ... */ 06080 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 06081 matchcallerid, registrar, 0); 06082 ast_unlock_contexts(); 06083 } 06084 06085 return ret; 06086 }
int ast_context_remove_extension_callerid2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcid, | |||
const char * | registrar, | |||
int | already_locked | |||
) |
Definition at line 6103 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
06104 { 06105 struct ast_exten *exten, *prev_exten = NULL; 06106 struct ast_exten *peer; 06107 struct ast_exten ex, *exten2, *exten3; 06108 char dummy_name[1024]; 06109 struct ast_exten *previous_peer = NULL; 06110 struct ast_exten *next_peer = NULL; 06111 int found = 0; 06112 06113 if (!already_locked) 06114 ast_wrlock_context(con); 06115 06116 #ifdef NEED_DEBUG 06117 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 06118 #endif 06119 #ifdef CONTEXT_DEBUG 06120 check_contexts(__FILE__, __LINE__); 06121 #endif 06122 /* find this particular extension */ 06123 ex.exten = dummy_name; 06124 ex.matchcid = matchcallerid; 06125 ex.cidmatch = callerid; 06126 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 06127 exten = ast_hashtab_lookup(con->root_table, &ex); 06128 if (exten) { 06129 if (priority == 0) { 06130 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06131 if (!exten2) 06132 ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name); 06133 if (con->pattern_tree) { 06134 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06135 06136 if (x->exten) { /* this test for safety purposes */ 06137 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06138 x->exten = 0; /* get rid of what will become a bad pointer */ 06139 } else { 06140 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 06141 } 06142 } 06143 } else { 06144 ex.priority = priority; 06145 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 06146 if (exten2) { 06147 if (exten2->label) { /* if this exten has a label, remove that, too */ 06148 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 06149 if (!exten3) 06150 ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten); 06151 } 06152 06153 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 06154 if (!exten3) 06155 ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten); 06156 if (exten2 == exten && exten2->peer) { 06157 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06158 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 06159 } 06160 if (ast_hashtab_size(exten->peer_table) == 0) { 06161 /* well, if the last priority of an exten is to be removed, 06162 then, the extension is removed, too! */ 06163 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 06164 if (!exten3) 06165 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 06166 if (con->pattern_tree) { 06167 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06168 if (x->exten) { /* this test for safety purposes */ 06169 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06170 x->exten = 0; /* get rid of what will become a bad pointer */ 06171 } 06172 } 06173 } 06174 } else { 06175 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 06176 priority, exten->exten, con->name); 06177 } 06178 } 06179 } else { 06180 /* hmmm? this exten is not in this pattern tree? */ 06181 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 06182 extension, con->name); 06183 } 06184 #ifdef NEED_DEBUG 06185 if (con->pattern_tree) { 06186 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 06187 log_match_char_tree(con->pattern_tree, " "); 06188 } 06189 #endif 06190 06191 /* scan the extension list to find first matching extension-registrar */ 06192 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 06193 if (!strcmp(exten->exten, extension) && 06194 (!registrar || !strcmp(exten->registrar, registrar)) && 06195 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 06196 break; 06197 } 06198 if (!exten) { 06199 /* we can't find right extension */ 06200 if (!already_locked) 06201 ast_unlock_context(con); 06202 return -1; 06203 } 06204 06205 /* scan the priority list to remove extension with exten->priority == priority */ 06206 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 06207 peer && !strcmp(peer->exten, extension) && 06208 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ; 06209 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 06210 06211 if ((priority == 0 || peer->priority == priority) && 06212 (!registrar || !strcmp(peer->registrar, registrar) )) { 06213 found = 1; 06214 06215 /* we are first priority extension? */ 06216 if (!previous_peer) { 06217 /* 06218 * We are first in the priority chain, so must update the extension chain. 06219 * The next node is either the next priority or the next extension 06220 */ 06221 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 06222 if (peer->peer) { 06223 /* move the peer_table and peer_label_table down to the next peer, if 06224 it is there */ 06225 peer->peer->peer_table = peer->peer_table; 06226 peer->peer->peer_label_table = peer->peer_label_table; 06227 peer->peer_table = NULL; 06228 peer->peer_label_table = NULL; 06229 } 06230 if (!prev_exten) { /* change the root... */ 06231 con->root = next_node; 06232 } else { 06233 prev_exten->next = next_node; /* unlink */ 06234 } 06235 if (peer->peer) { /* update the new head of the pri list */ 06236 peer->peer->next = peer->next; 06237 } 06238 } else { /* easy, we are not first priority in extension */ 06239 previous_peer->peer = peer->peer; 06240 } 06241 06242 06243 /* now, free whole priority extension */ 06244 destroy_exten(peer); 06245 } else { 06246 previous_peer = peer; 06247 } 06248 } 06249 if (!already_locked) 06250 ast_unlock_context(con); 06251 return found ? 0 : -1; 06252 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8508 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08509 { 08510 int ret = -1; 08511 struct ast_context *c; 08512 08513 c = find_context_locked(context); 08514 if (c) { 08515 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08516 ast_unlock_contexts(); 08517 } 08518 return ret; 08519 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8521 of file pbx.c.
References ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_remove_ignorepat().
08522 { 08523 struct ast_ignorepat *ip, *ipl = NULL; 08524 08525 ast_wrlock_context(con); 08526 08527 for (ip = con->ignorepats; ip; ip = ip->next) { 08528 if (!strcmp(ip->pattern, ignorepat) && 08529 (!registrar || (registrar == ip->registrar))) { 08530 if (ipl) { 08531 ipl->next = ip->next; 08532 ast_free(ip); 08533 } else { 08534 con->ignorepats = ip->next; 08535 ast_free(ip); 08536 } 08537 ast_unlock_context(con); 08538 return 0; 08539 } 08540 ipl = ip; 08541 } 08542 08543 ast_unlock_context(con); 08544 errno = EINVAL; 08545 return -1; 08546 }
int ast_context_remove_include | ( | const char * | context, | |
const char * | include, | |||
const char * | registrar | |||
) |
Remove a context include.
0 | on success | |
-1 | on failure |
Definition at line 5961 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05962 { 05963 int ret = -1; 05964 struct ast_context *c; 05965 05966 c = find_context_locked(context); 05967 if (c) { 05968 /* found, remove include from this context ... */ 05969 ret = ast_context_remove_include2(c, include, registrar); 05970 ast_unlock_contexts(); 05971 } 05972 return ret; 05973 }
int ast_context_remove_include2 | ( | struct ast_context * | con, | |
const char * | include, | |||
const char * | registrar | |||
) |
Removes an include by an ast_context structure.
0 | on success | |
-1 | on success |
Removes an include by an ast_context structure.
0 | on success. | |
-1 | on failure. |
Definition at line 5984 of file pbx.c.
References ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, and ast_include::timing.
Referenced by ast_context_remove_include().
05985 { 05986 struct ast_include *i, *pi = NULL; 05987 int ret = -1; 05988 05989 ast_wrlock_context(con); 05990 05991 /* find our include */ 05992 for (i = con->includes; i; pi = i, i = i->next) { 05993 if (!strcmp(i->name, include) && 05994 (!registrar || !strcmp(i->registrar, registrar))) { 05995 /* remove from list */ 05996 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05997 if (pi) 05998 pi->next = i->next; 05999 else 06000 con->includes = i->next; 06001 /* free include and return */ 06002 ast_destroy_timing(&(i->timing)); 06003 ast_free(i); 06004 ret = 0; 06005 break; 06006 } 06007 } 06008 06009 ast_unlock_context(con); 06010 06011 return ret; 06012 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Removes a switch with the given parameters
0 | on success | |
-1 | on failure |
Definition at line 6019 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
06020 { 06021 int ret = -1; /* default error return */ 06022 struct ast_context *c; 06023 06024 c = find_context_locked(context); 06025 if (c) { 06026 /* remove switch from this context ... */ 06027 ret = ast_context_remove_switch2(c, sw, data, registrar); 06028 ast_unlock_contexts(); 06029 } 06030 return ret; 06031 }
int ast_context_remove_switch2 | ( | struct ast_context * | con, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
This function locks given context, removes switch, unlock context and return.
Definition at line 6041 of file pbx.c.
References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
06042 { 06043 struct ast_sw *i; 06044 int ret = -1; 06045 06046 ast_wrlock_context(con); 06047 06048 /* walk switches */ 06049 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 06050 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 06051 (!registrar || !strcmp(i->registrar, registrar))) { 06052 /* found, remove from list */ 06053 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 06054 AST_LIST_REMOVE_CURRENT(list); 06055 ast_free(i); /* free switch and return */ 06056 ret = 0; 06057 break; 06058 } 06059 } 06060 AST_LIST_TRAVERSE_SAFE_END; 06061 06062 ast_unlock_context(con); 06063 06064 return ret; 06065 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
macrocontext | name of the macro-context to unlock |
Unlocks the given macro-context so that another thread (call) can execute it
0 | on success | |
-1 | on failure |
Definition at line 6281 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06282 { 06283 struct ast_context *c; 06284 int ret = -1; 06285 06286 c = find_context_locked(context); 06287 if (c) { 06288 ast_unlock_contexts(); 06289 06290 /* if we found context, unlock macrolock */ 06291 ret = ast_mutex_unlock(&c->macrolock); 06292 } 06293 06294 return ret; 06295 }
int ast_context_verify_includes | ( | struct ast_context * | con | ) |
Verifies includes in an ast_contect structure.
con | context in which to verify the includes |
0 | if no problems found | |
-1 | if there were any missing context |
Definition at line 11080 of file pbx.c.
References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.
Referenced by pbx_load_module().
11081 { 11082 struct ast_include *inc = NULL; 11083 int res = 0; 11084 11085 while ( (inc = ast_walk_context_includes(con, inc)) ) { 11086 if (ast_context_find(inc->rname)) 11087 continue; 11088 11089 res = -1; 11090 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 11091 ast_get_context_name(con), inc->rname); 11092 break; 11093 } 11094 11095 return res; 11096 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3754 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_compile_ael2(), ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03755 { 03756 struct ast_custom_function *acf = NULL; 03757 03758 AST_RWLIST_RDLOCK(&acf_root); 03759 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03760 if (!strcmp(name, acf->name)) 03761 break; 03762 } 03763 AST_RWLIST_UNLOCK(&acf_root); 03764 03765 return acf; 03766 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3768 of file pbx.c.
References ast_custom_escalating_function::acf, ast_free, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by __ast_custom_function_register_escalating(), _unload_module(), load_module(), reload(), unload_module(), and unload_pbx().
03769 { 03770 struct ast_custom_function *cur; 03771 struct ast_custom_escalating_function *cur_escalation; 03772 03773 if (!acf) { 03774 return -1; 03775 } 03776 03777 AST_RWLIST_WRLOCK(&acf_root); 03778 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03779 #ifdef AST_XML_DOCS 03780 if (cur->docsrc == AST_XML_DOC) { 03781 ast_string_field_free_memory(acf); 03782 } 03783 #endif 03784 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03785 } 03786 AST_RWLIST_UNLOCK(&acf_root); 03787 03788 /* Remove from the escalation list */ 03789 AST_RWLIST_WRLOCK(&escalation_root); 03790 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) { 03791 if (cur_escalation->acf == acf) { 03792 AST_RWLIST_REMOVE_CURRENT(list); 03793 ast_free(cur_escalation); 03794 break; 03795 } 03796 } 03797 AST_RWLIST_TRAVERSE_SAFE_END; 03798 AST_RWLIST_UNLOCK(&escalation_root); 03799 03800 return cur ? 0 : -1; 03801 }
int ast_destroy_timing | ( | struct ast_timing * | i | ) |
Deallocates memory structures associated with a timing bitmap.
i | Pointer to an ast_timing structure. |
0 | success | |
non-zero | failure (number suitable to pass to |
Definition at line 8350 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
[in] | devstate | device state |
Definition at line 4798 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.
Referenced by ast_extension_state3().
04799 { 04800 switch (devstate) { 04801 case AST_DEVICE_ONHOLD: 04802 return AST_EXTENSION_ONHOLD; 04803 case AST_DEVICE_BUSY: 04804 return AST_EXTENSION_BUSY; 04805 case AST_DEVICE_UNKNOWN: 04806 return AST_EXTENSION_NOT_INUSE; 04807 case AST_DEVICE_UNAVAILABLE: 04808 case AST_DEVICE_INVALID: 04809 return AST_EXTENSION_UNAVAILABLE; 04810 case AST_DEVICE_RINGINUSE: 04811 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04812 case AST_DEVICE_RINGING: 04813 return AST_EXTENSION_RINGING; 04814 case AST_DEVICE_INUSE: 04815 return AST_EXTENSION_INUSE; 04816 case AST_DEVICE_NOT_INUSE: 04817 return AST_EXTENSION_NOT_INUSE; 04818 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04819 break; 04820 } 04821 04822 return AST_EXTENSION_NOT_INUSE; 04823 }
int ast_exists_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
Determine whether an extension exists.
c | this is not important | |
context | which context to look in | |
exten | which extension to search for | |
priority | priority of the action within the extension | |
callerid | callerid to search for |
Definition at line 5354 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().
05355 { 05356 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05357 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8662 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), and pbx_parseable_goto().
08663 { 08664 if (!chan) 08665 return -1; 08666 08667 ast_channel_lock(chan); 08668 08669 if (!ast_strlen_zero(context)) 08670 ast_copy_string(chan->context, context, sizeof(chan->context)); 08671 if (!ast_strlen_zero(exten)) 08672 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08673 if (priority > -1) { 08674 chan->priority = priority; 08675 /* see flag description in channel.h for explanation */ 08676 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08677 chan->priority--; 08678 } 08679 08680 ast_channel_unlock(chan); 08681 08682 return 0; 08683 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2902 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by lua_find_extension(), and realtime_switch_common().
02903 { 02904 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02905 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02906 return extension_match_core(pattern, data, needmore); 02907 }
int ast_extension_cmp | ( | const char * | a, | |
const char * | b | |||
) |
Determine if one extension should match before another.
Checks whether or extension a should match before extension b
0 | if the two extensions have equal matching priority | |
1 | on a > b | |
-1 | on a < b |
Definition at line 2667 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02668 { 02669 int cmp; 02670 02671 cmp = ext_cmp(a, b); 02672 if (cmp < 0) { 02673 return -1; 02674 } 02675 if (cmp > 0) { 02676 return 1; 02677 } 02678 return 0; 02679 }
int ast_extension_match | ( | const char * | pattern, | |
const char * | extension | |||
) |
Determine if a given extension matches a given pattern (in NXX format).
Checks whether or not the given extension matches the given pattern.
1 | on match | |
0 | on failure |
Definition at line 2897 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().
02898 { 02899 return extension_match_core(pattern, data, E_MATCH); 02900 }
int ast_extension_patmatch | ( | const char * | pattern, | |
const char * | data | |||
) |
int ast_extension_state | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) |
Uses hint and devicestate callback to get the state of an extension.
c | this is not important | |
context | which context to look in | |
exten | which extension to get state |
Definition at line 4868 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.
Referenced by action_extensionstate(), extstate_read(), get_queue_member_status(), and handle_request_subscribe().
04869 { 04870 struct ast_exten *e; 04871 04872 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04873 return -1; /* No hint, return -1 */ 04874 } 04875 04876 if (e->exten[0] == '_') { 04877 /* Create this hint on-the-fly */ 04878 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04879 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04880 e->registrar); 04881 if (!(e = ast_hint_extension(c, context, exten))) { 04882 /* Improbable, but not impossible */ 04883 return -1; 04884 } 04885 } 04886 04887 return ast_extension_state2(e); /* Check all devices in the hint */ 04888 }
const char* ast_extension_state2str | ( | int | extension_state | ) |
Return string representation of the state of an extension.
extension_state | is the numerical state delivered by ast_extension_state |
Definition at line 4856 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), and show_channels_cb().
04857 { 04858 int i; 04859 04860 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04861 if (extension_states[i].extension_state == extension_state) 04862 return extension_states[i].text; 04863 } 04864 return "Unknown"; 04865 }
int ast_extension_state_add | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
void * | data | |||
) |
Registers a state change callback.
context | which context to look in | |
exten | which extension to get state | |
change_cb | callback to call if state changed | |
data | to pass to callback |
-1 | on failure | |
ID | on success |
Definition at line 5089 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
05091 { 05092 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 05093 }
int ast_extension_state_add_destroy | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
ast_state_cb_destroy_type | destroy_cb, | |||
void * | data | |||
) |
Registers a state change callback with destructor.
context | which context to look in | |
exten | which extension to get state | |
change_cb | callback to call if state changed | |
destroy_cb | callback to call when registration destroyed. | |
data | to pass to callback |
-1 | on failure | |
ID | on success |
Definition at line 5002 of file pbx.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, hints, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.
Referenced by ast_extension_state_add(), and handle_request_subscribe().
05004 { 05005 struct ast_hint *hint; 05006 struct ast_state_cb *state_cb; 05007 struct ast_exten *e; 05008 int id; 05009 05010 /* If there's no context and extension: add callback to statecbs list */ 05011 if (!context && !exten) { 05012 /* Prevent multiple adds from adding the same change_cb at the same time. */ 05013 ao2_lock(statecbs); 05014 05015 /* Remove any existing change_cb. */ 05016 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 05017 05018 /* Now insert the change_cb */ 05019 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05020 ao2_unlock(statecbs); 05021 return -1; 05022 } 05023 state_cb->id = 0; 05024 state_cb->change_cb = change_cb; 05025 state_cb->destroy_cb = destroy_cb; 05026 state_cb->data = data; 05027 ao2_link(statecbs, state_cb); 05028 05029 ao2_ref(state_cb, -1); 05030 ao2_unlock(statecbs); 05031 return 0; 05032 } 05033 05034 if (!context || !exten) 05035 return -1; 05036 05037 /* This callback type is for only one hint, so get the hint */ 05038 e = ast_hint_extension(NULL, context, exten); 05039 if (!e) { 05040 return -1; 05041 } 05042 05043 /* If this is a pattern, dynamically create a new extension for this 05044 * particular match. Note that this will only happen once for each 05045 * individual extension, because the pattern will no longer match first. 05046 */ 05047 if (e->exten[0] == '_') { 05048 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 05049 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 05050 e->registrar); 05051 e = ast_hint_extension(NULL, context, exten); 05052 if (!e || e->exten[0] == '_') { 05053 return -1; 05054 } 05055 } 05056 05057 /* Find the hint in the hints container */ 05058 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05059 hint = ao2_find(hints, e, 0); 05060 if (!hint) { 05061 ao2_unlock(hints); 05062 return -1; 05063 } 05064 05065 /* Now insert the callback in the callback list */ 05066 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05067 ao2_ref(hint, -1); 05068 ao2_unlock(hints); 05069 return -1; 05070 } 05071 do { 05072 id = stateid++; /* Unique ID for this callback */ 05073 /* Do not allow id to ever be -1 or 0. */ 05074 } while (id == -1 || id == 0); 05075 state_cb->id = id; 05076 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 05077 state_cb->destroy_cb = destroy_cb; 05078 state_cb->data = data; /* Data for the callback */ 05079 ao2_link(hint->callbacks, state_cb); 05080 05081 ao2_ref(state_cb, -1); 05082 ao2_ref(hint, -1); 05083 ao2_unlock(hints); 05084 05085 return id; 05086 }
int ast_extension_state_del | ( | int | id, | |
ast_state_cb_type | change_cb | |||
) |
Deletes a registered state change callback by ID.
id | of the registered state callback to delete | |
change_cb | callback to call if state changed (Used if id == 0 (global)) |
0 | success | |
-1 | failure |
Definition at line 5111 of file pbx.c.
References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::callbacks, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
05112 { 05113 struct ast_state_cb *p_cur; 05114 int ret = -1; 05115 05116 if (!id) { /* id == 0 is a callback without extension */ 05117 if (!change_cb) { 05118 return ret; 05119 } 05120 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 05121 if (p_cur) { 05122 ret = 0; 05123 ao2_ref(p_cur, -1); 05124 } 05125 } else { /* callback with extension, find the callback based on ID */ 05126 struct ast_hint *hint; 05127 05128 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05129 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 05130 if (hint) { 05131 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 05132 if (p_cur) { 05133 ret = 0; 05134 ao2_ref(p_cur, -1); 05135 } 05136 ao2_ref(hint, -1); 05137 } 05138 ao2_unlock(hints); 05139 } 05140 05141 return ret; 05142 }
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.
c | this is not important | |
context | which context to look in | |
exten | which extension to search for | |
label | label of the action within the extension to match to priority | |
callerid | callerid to search for |
the | priority which matches the given label in the extension | |
-1 | if not found. |
Definition at line 5359 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by action_originate(), action_redirect(), handle_gosub(), handle_setpriority(), isexten_function_read(), and pbx_parseable_goto().
05360 { 05361 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05362 }
int ast_findlabel_extension2 | ( | struct ast_channel * | c, | |
struct ast_context * | con, | |||
const char * | exten, | |||
const char * | label, | |||
const char * | callerid | |||
) |
Find the priority of an extension that has the specified label.
Definition at line 5364 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05365 { 05366 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05367 }
int ast_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | workspace, | |||
size_t | len | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
workspace | A pointer to safe memory to use for a return value | |
len | the number of bytes in workspace |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 4131 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
04132 { 04133 char *copy = ast_strdupa(function); 04134 char *args = func_args(copy); 04135 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04136 int res; 04137 struct ast_module_user *u = NULL; 04138 04139 if (acfptr == NULL) { 04140 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04141 } else if (!acfptr->read && !acfptr->read2) { 04142 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04143 } else if (!is_read_allowed(acfptr)) { 04144 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04145 } else if (acfptr->read) { 04146 if (acfptr->mod) { 04147 u = __ast_module_user_add(acfptr->mod, chan); 04148 } 04149 res = acfptr->read(chan, copy, args, workspace, len); 04150 if (acfptr->mod && u) { 04151 __ast_module_user_remove(acfptr->mod, u); 04152 } 04153 return res; 04154 } else { 04155 struct ast_str *str = ast_str_create(16); 04156 if (acfptr->mod) { 04157 u = __ast_module_user_add(acfptr->mod, chan); 04158 } 04159 res = acfptr->read2(chan, copy, args, &str, 0); 04160 if (acfptr->mod && u) { 04161 __ast_module_user_remove(acfptr->mod, u); 04162 } 04163 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 04164 ast_free(str); 04165 return res; 04166 } 04167 return -1; 04168 }
int ast_func_read2 | ( | struct ast_channel * | chan, | |
const char * | function, | |||
struct ast_str ** | str, | |||
ssize_t | maxlen | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
str | A dynamic string buffer into which to place the result. | |
maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 4170 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
04171 { 04172 char *copy = ast_strdupa(function); 04173 char *args = func_args(copy); 04174 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04175 int res; 04176 struct ast_module_user *u = NULL; 04177 04178 if (acfptr == NULL) { 04179 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04180 } else if (!acfptr->read && !acfptr->read2) { 04181 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04182 } else if (!is_read_allowed(acfptr)) { 04183 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04184 } else { 04185 if (acfptr->mod) { 04186 u = __ast_module_user_add(acfptr->mod, chan); 04187 } 04188 ast_str_reset(*str); 04189 if (acfptr->read2) { 04190 /* ast_str enabled */ 04191 res = acfptr->read2(chan, copy, args, str, maxlen); 04192 } else { 04193 /* Legacy function pointer, allocate buffer for result */ 04194 int maxsize = ast_str_size(*str); 04195 if (maxlen > -1) { 04196 if (maxlen == 0) { 04197 if (acfptr->read_max) { 04198 maxsize = acfptr->read_max; 04199 } else { 04200 maxsize = VAR_BUF_SIZE; 04201 } 04202 } else { 04203 maxsize = maxlen; 04204 } 04205 ast_str_make_space(str, maxsize); 04206 } 04207 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 04208 } 04209 if (acfptr->mod && u) { 04210 __ast_module_user_remove(acfptr->mod, u); 04211 } 04212 return res; 04213 } 04214 return -1; 04215 }
int ast_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
const char * | value | |||
) |
executes a write operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
value | A value parameter to pass for writing |
This application executes a function in write mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 4217 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), is_write_allowed(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
04218 { 04219 char *copy = ast_strdupa(function); 04220 char *args = func_args(copy); 04221 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04222 04223 if (acfptr == NULL) { 04224 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04225 } else if (!acfptr->write) { 04226 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 04227 } else if (!is_write_allowed(acfptr)) { 04228 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy); 04229 } else { 04230 int res; 04231 struct ast_module_user *u = NULL; 04232 if (acfptr->mod) 04233 u = __ast_module_user_add(acfptr->mod, chan); 04234 res = acfptr->write(chan, copy, args, value); 04235 if (acfptr->mod && u) 04236 __ast_module_user_remove(acfptr->mod, u); 04237 return res; 04238 } 04239 04240 return -1; 04241 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10932 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_compile_ael2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), ast_remove_hint(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10933 { 10934 return con ? con->name : NULL; 10935 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10970 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10971 { 10972 return c ? c->registrar : NULL; 10973 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 11000 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), get_parking_exten(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
11001 { 11002 return e ? e->app : NULL; 11003 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 11005 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_masq_park_call_exten(), ast_park_call_exten(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), print_ext(), and xfer_park_call_helper().
11006 { 11007 return e ? e->data : NULL; 11008 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10995 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10996 { 10997 return e ? e->cidmatch : NULL; 10998 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10937 of file pbx.c.
References ast_exten::parent.
Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
10938 { 10939 return exten ? exten->parent : NULL; 10940 }
const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 10947 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 10990 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10991 { 10992 return e ? e->matchcid : 0; 10993 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10942 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint(), ast_remove_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), destroy_hint(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().
10943 { 10944 return exten ? exten->exten : NULL; 10945 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10962 of file pbx.c.
References ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
10963 { 10964 return exten ? exten->priority : -1; 10965 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10975 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10976 { 10977 return e ? e->registrar : NULL; 10978 }
int ast_get_hint | ( | char * | hint, | |
int | hintsize, | |||
char * | name, | |||
int | namesize, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
If an extension hint exists, return non-zero.
hint | buffer for hint | |
hintsize | size of hint buffer, in bytes | |
name | buffer for name portion of hint | |
namesize | size of name buffer | |
c | Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded. | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 5316 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().
05317 { 05318 struct ast_exten *e = ast_hint_extension(c, context, exten); 05319 05320 if (e) { 05321 if (hint) 05322 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05323 if (name) { 05324 const char *tmp = ast_get_extension_app_data(e); 05325 if (tmp) 05326 ast_copy_string(name, tmp, namesize); 05327 } 05328 return -1; 05329 } 05330 return 0; 05331 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10957 of file pbx.c.
References ast_ignorepat::pattern.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10958 { 10959 return ip ? ip->pattern : NULL; 10960 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10985 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10986 { 10987 return ip ? ip->registrar : NULL; 10988 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 10952 of file pbx.c.
References ast_include::name.
Referenced by complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 10980 of file pbx.c.
References ast_include::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10981 { 10982 return i ? i->registrar : NULL; 10983 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 11015 of file pbx.c.
References ast_sw::data.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11016 { 11017 return sw ? sw->data : NULL; 11018 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 11020 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
11021 { 11022 return sw->eval; 11023 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 11010 of file pbx.c.
References ast_sw::name.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11011 { 11012 return sw ? sw->name : NULL; 11013 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 11025 of file pbx.c.
References ast_sw::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11026 { 11027 return sw ? sw->registrar : NULL; 11028 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11120 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
11121 { 11122 return __ast_goto_if_exists(chan, context, exten, priority, 0); 11123 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1092 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01093 { 01094 const struct ast_context *ac = ah_a; 01095 const struct ast_context *bc = ah_b; 01096 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01097 return 1; 01098 /* assume context names are registered in a string table! */ 01099 return strcmp(ac->name, bc->name); 01100 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1144 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01145 { 01146 const struct ast_context *ac = obj; 01147 return ast_hashtab_hash_string(ac->name); 01148 }
int ast_ignore_pattern | ( | const char * | context, | |
const char * | pattern | |||
) |
Checks to see if a number should be ignored.
context | context to search within | |
pattern | to check whether it should be ignored or not |
Check if a number should be ignored with respect to dialtone cancellation.
0 | if the pattern should not be ignored | |
non-zero | if the pattern should be ignored |
Definition at line 8604 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), and skinny_ss().
08605 { 08606 struct ast_context *con = ast_context_find(context); 08607 08608 if (con) { 08609 struct ast_ignorepat *pat; 08610 08611 for (pat = con->ignorepats; pat; pat = pat->next) { 08612 if (ast_extension_match(pat->pattern, pattern)) 08613 return 1; 08614 } 08615 } 08616 08617 return 0; 08618 }
int ast_matchmore_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
c | not really important XXX | |
context | context to serach within | |
exten | extension to check | |
priority | priority of extension path | |
callerid | callerid of extension being searched for |
Definition at line 5374 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().
05375 { 05376 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05377 }
void ast_merge_contexts_and_delete | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
const char * | registrar | |||
) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
extcontexts | pointer to the ast_context structure | |
exttable | pointer to the ast_hashtab structure that contains all the elements in extcontexts | |
registrar | of the context; if it's set the routine will delete all contexts that belong to that registrar; if NULL only the contexts that are specified in extcontexts |
Definition at line 7891 of file pbx.c.
References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07892 { 07893 double ft; 07894 struct ast_context *tmp; 07895 struct ast_context *oldcontextslist; 07896 struct ast_hashtab *oldtable; 07897 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07898 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07899 struct store_hint *saved_hint; 07900 struct ast_hint *hint; 07901 struct ast_exten *exten; 07902 int length; 07903 struct ast_state_cb *thiscb; 07904 struct ast_hashtab_iter *iter; 07905 struct ao2_iterator i; 07906 struct timeval begintime; 07907 struct timeval writelocktime; 07908 struct timeval endlocktime; 07909 struct timeval enddeltime; 07910 07911 /* 07912 * It is very important that this function hold the hints 07913 * container lock _and_ the conlock during its operation; not 07914 * only do we need to ensure that the list of contexts and 07915 * extensions does not change, but also that no hint callbacks 07916 * (watchers) are added or removed during the merge/delete 07917 * process 07918 * 07919 * In addition, the locks _must_ be taken in this order, because 07920 * there are already other code paths that use this order 07921 */ 07922 07923 begintime = ast_tvnow(); 07924 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07925 ast_wrlock_contexts(); 07926 07927 if (!contexts_table) { 07928 /* Well, that's odd. There are no contexts. */ 07929 contexts_table = exttable; 07930 contexts = *extcontexts; 07931 ast_unlock_contexts(); 07932 ast_mutex_unlock(&context_merge_lock); 07933 return; 07934 } 07935 07936 iter = ast_hashtab_start_traversal(contexts_table); 07937 while ((tmp = ast_hashtab_next(iter))) { 07938 context_merge(extcontexts, exttable, tmp, registrar); 07939 } 07940 ast_hashtab_end_traversal(iter); 07941 07942 ao2_lock(hints); 07943 writelocktime = ast_tvnow(); 07944 07945 /* preserve all watchers for hints */ 07946 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07947 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07948 if (ao2_container_count(hint->callbacks)) { 07949 ao2_lock(hint); 07950 if (!hint->exten) { 07951 /* The extension has already been destroyed. (Should never happen here) */ 07952 ao2_unlock(hint); 07953 continue; 07954 } 07955 07956 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07957 + sizeof(*saved_hint); 07958 if (!(saved_hint = ast_calloc(1, length))) { 07959 ao2_unlock(hint); 07960 continue; 07961 } 07962 07963 /* This removes all the callbacks from the hint into saved_hint. */ 07964 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07965 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07966 /* 07967 * We intentionally do not unref thiscb to account for the 07968 * non-ao2 reference in saved_hint->callbacks 07969 */ 07970 } 07971 07972 saved_hint->laststate = hint->laststate; 07973 saved_hint->context = saved_hint->data; 07974 strcpy(saved_hint->data, hint->exten->parent->name); 07975 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07976 strcpy(saved_hint->exten, hint->exten->exten); 07977 ao2_unlock(hint); 07978 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07979 } 07980 } 07981 ao2_iterator_destroy(&i); 07982 07983 /* save the old table and list */ 07984 oldtable = contexts_table; 07985 oldcontextslist = contexts; 07986 07987 /* move in the new table and list */ 07988 contexts_table = exttable; 07989 contexts = *extcontexts; 07990 07991 /* 07992 * Restore the watchers for hints that can be found; notify 07993 * those that cannot be restored. 07994 */ 07995 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07996 struct pbx_find_info q = { .stacklen = 0 }; 07997 07998 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07999 PRIORITY_HINT, NULL, "", E_MATCH); 08000 /* 08001 * If this is a pattern, dynamically create a new extension for this 08002 * particular match. Note that this will only happen once for each 08003 * individual extension, because the pattern will no longer match first. 08004 */ 08005 if (exten && exten->exten[0] == '_') { 08006 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 08007 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 08008 exten->registrar); 08009 /* rwlocks are not recursive locks */ 08010 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 08011 saved_hint->exten); 08012 } 08013 08014 /* Find the hint in the hints container */ 08015 hint = exten ? ao2_find(hints, exten, 0) : NULL; 08016 if (!hint) { 08017 /* 08018 * Notify watchers of this removed hint later when we aren't 08019 * encumberd by so many locks. 08020 */ 08021 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 08022 } else { 08023 ao2_lock(hint); 08024 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08025 ao2_link(hint->callbacks, thiscb); 08026 /* Ref that we added when putting into saved_hint->callbacks */ 08027 ao2_ref(thiscb, -1); 08028 } 08029 hint->laststate = saved_hint->laststate; 08030 ao2_unlock(hint); 08031 ao2_ref(hint, -1); 08032 ast_free(saved_hint); 08033 } 08034 } 08035 08036 ao2_unlock(hints); 08037 ast_unlock_contexts(); 08038 08039 /* 08040 * Notify watchers of all removed hints with the same lock 08041 * environment as handle_statechange(). 08042 */ 08043 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 08044 /* this hint has been removed, notify the watchers */ 08045 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08046 thiscb->change_cb(saved_hint->context, saved_hint->exten, 08047 AST_EXTENSION_REMOVED, thiscb->data); 08048 /* Ref that we added when putting into saved_hint->callbacks */ 08049 ao2_ref(thiscb, -1); 08050 } 08051 ast_free(saved_hint); 08052 } 08053 08054 ast_mutex_unlock(&context_merge_lock); 08055 endlocktime = ast_tvnow(); 08056 08057 /* 08058 * The old list and hashtab no longer are relevant, delete them 08059 * while the rest of asterisk is now freely using the new stuff 08060 * instead. 08061 */ 08062 08063 ast_hashtab_destroy(oldtable, NULL); 08064 08065 for (tmp = oldcontextslist; tmp; ) { 08066 struct ast_context *next; /* next starting point */ 08067 08068 next = tmp->next; 08069 __ast_internal_context_destroy(tmp); 08070 tmp = next; 08071 } 08072 enddeltime = ast_tvnow(); 08073 08074 ft = ast_tvdiff_us(writelocktime, begintime); 08075 ft /= 1000000.0; 08076 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 08077 08078 ft = ast_tvdiff_us(endlocktime, writelocktime); 08079 ft /= 1000000.0; 08080 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 08081 08082 ft = ast_tvdiff_us(enddeltime, endlocktime); 08083 ft /= 1000000.0; 08084 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 08085 08086 ft = ast_tvdiff_us(enddeltime, begintime); 08087 ft /= 1000000.0; 08088 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 08089 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11185 of file pbx.c.
References pbx_parseable_goto().
Referenced by _while_exec(), check_goto_on_transfer(), dial_exec_full(), gosub_exec(), ivr_dispatch(), parkandannounce_exec(), pbx_builtin_goto(), and while_continue_exec().
11186 { 11187 return pbx_parseable_goto(chan, goto_string, 0); 11188 }
int ast_pbx_outgoing_app | ( | const char * | type, | |
format_t | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | app, | |||
const char * | appdata, | |||
int * | reason, | |||
int | sync, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular application with given extension
Definition at line 9498 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
09499 { 09500 struct ast_channel *chan; 09501 struct app_tmp *tmp; 09502 int res = -1, cdr_res = -1; 09503 struct outgoing_helper oh; 09504 09505 memset(&oh, 0, sizeof(oh)); 09506 oh.vars = vars; 09507 oh.account = account; 09508 09509 if (locked_channel) 09510 *locked_channel = NULL; 09511 if (ast_strlen_zero(app)) { 09512 res = -1; 09513 goto outgoing_app_cleanup; 09514 } 09515 if (synchronous) { 09516 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09517 if (chan) { 09518 ast_set_variables(chan, vars); 09519 if (account) 09520 ast_cdr_setaccount(chan, account); 09521 if (chan->_state == AST_STATE_UP) { 09522 res = 0; 09523 ast_verb(4, "Channel %s was answered.\n", chan->name); 09524 tmp = ast_calloc(1, sizeof(*tmp)); 09525 if (!tmp || ast_string_field_init(tmp, 252)) { 09526 if (tmp) { 09527 ast_free(tmp); 09528 } 09529 res = -1; 09530 } else { 09531 ast_string_field_set(tmp, app, app); 09532 ast_string_field_set(tmp, data, appdata); 09533 tmp->chan = chan; 09534 if (synchronous > 1) { 09535 if (locked_channel) 09536 ast_channel_unlock(chan); 09537 ast_pbx_run_app(tmp); 09538 } else { 09539 if (locked_channel) 09540 ast_channel_lock(chan); 09541 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09542 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09543 ast_string_field_free_memory(tmp); 09544 ast_free(tmp); 09545 if (locked_channel) 09546 ast_channel_unlock(chan); 09547 ast_hangup(chan); 09548 res = -1; 09549 } else { 09550 if (locked_channel) 09551 *locked_channel = chan; 09552 } 09553 } 09554 } 09555 } else { 09556 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09557 if (chan->cdr) { /* update the cdr */ 09558 /* here we update the status of the call, which sould be busy. 09559 * if that fails then we set the status to failed */ 09560 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09561 ast_cdr_failed(chan->cdr); 09562 } 09563 ast_hangup(chan); 09564 } 09565 } 09566 09567 if (res < 0) { /* the call failed for some reason */ 09568 if (*reason == 0) { /* if the call failed (not busy or no answer) 09569 * update the cdr with the failed message */ 09570 cdr_res = ast_pbx_outgoing_cdr_failed(); 09571 if (cdr_res != 0) { 09572 res = cdr_res; 09573 goto outgoing_app_cleanup; 09574 } 09575 } 09576 } 09577 09578 } else { 09579 struct async_stat *as; 09580 if (!(as = ast_calloc(1, sizeof(*as)))) { 09581 res = -1; 09582 goto outgoing_app_cleanup; 09583 } 09584 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09585 if (!chan) { 09586 ast_free(as); 09587 res = -1; 09588 goto outgoing_app_cleanup; 09589 } 09590 as->chan = chan; 09591 ast_copy_string(as->app, app, sizeof(as->app)); 09592 if (appdata) 09593 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09594 as->timeout = timeout; 09595 ast_set_variables(chan, vars); 09596 if (account) 09597 ast_cdr_setaccount(chan, account); 09598 /* Start a new thread, and get something handling this channel. */ 09599 if (locked_channel) 09600 ast_channel_lock(chan); 09601 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09602 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09603 ast_free(as); 09604 if (locked_channel) 09605 ast_channel_unlock(chan); 09606 ast_hangup(chan); 09607 res = -1; 09608 goto outgoing_app_cleanup; 09609 } else { 09610 if (locked_channel) 09611 *locked_channel = chan; 09612 } 09613 res = 0; 09614 } 09615 outgoing_app_cleanup: 09616 ast_variables_destroy(vars); 09617 return res; 09618 }
int ast_pbx_outgoing_exten | ( | const char * | type, | |
format_t | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int * | reason, | |||
int | sync, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular extension
Definition at line 9329 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
09330 { 09331 struct ast_channel *chan; 09332 struct async_stat *as; 09333 int res = -1, cdr_res = -1; 09334 struct outgoing_helper oh; 09335 09336 if (synchronous) { 09337 oh.context = context; 09338 oh.exten = exten; 09339 oh.priority = priority; 09340 oh.cid_num = cid_num; 09341 oh.cid_name = cid_name; 09342 oh.account = account; 09343 oh.vars = vars; 09344 oh.parent_channel = NULL; 09345 09346 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09347 if (channel) { 09348 *channel = chan; 09349 if (chan) 09350 ast_channel_lock(chan); 09351 } 09352 if (chan) { 09353 if (chan->_state == AST_STATE_UP) { 09354 res = 0; 09355 ast_verb(4, "Channel %s was answered.\n", chan->name); 09356 09357 if (synchronous > 1) { 09358 if (channel) 09359 ast_channel_unlock(chan); 09360 if (ast_pbx_run(chan)) { 09361 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09362 if (channel) 09363 *channel = NULL; 09364 ast_hangup(chan); 09365 chan = NULL; 09366 res = -1; 09367 } 09368 } else { 09369 if (ast_pbx_start(chan)) { 09370 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09371 if (channel) { 09372 *channel = NULL; 09373 ast_channel_unlock(chan); 09374 } 09375 ast_hangup(chan); 09376 res = -1; 09377 } 09378 chan = NULL; 09379 } 09380 } else { 09381 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09382 09383 if (chan->cdr) { /* update the cdr */ 09384 /* here we update the status of the call, which sould be busy. 09385 * if that fails then we set the status to failed */ 09386 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09387 ast_cdr_failed(chan->cdr); 09388 } 09389 09390 if (channel) { 09391 *channel = NULL; 09392 ast_channel_unlock(chan); 09393 } 09394 ast_hangup(chan); 09395 chan = NULL; 09396 } 09397 } 09398 09399 if (res < 0) { /* the call failed for some reason */ 09400 if (*reason == 0) { /* if the call failed (not busy or no answer) 09401 * update the cdr with the failed message */ 09402 cdr_res = ast_pbx_outgoing_cdr_failed(); 09403 if (cdr_res != 0) { 09404 res = cdr_res; 09405 goto outgoing_exten_cleanup; 09406 } 09407 } 09408 09409 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09410 /* check if "failed" exists */ 09411 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09412 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09413 if (chan) { 09414 char failed_reason[4] = ""; 09415 if (!ast_strlen_zero(context)) 09416 ast_copy_string(chan->context, context, sizeof(chan->context)); 09417 set_ext_pri(chan, "failed", 1); 09418 ast_set_variables(chan, vars); 09419 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09420 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09421 if (account) 09422 ast_cdr_setaccount(chan, account); 09423 if (ast_pbx_run(chan)) { 09424 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09425 ast_hangup(chan); 09426 } 09427 chan = NULL; 09428 } 09429 } 09430 } 09431 } else { 09432 if (!(as = ast_calloc(1, sizeof(*as)))) { 09433 res = -1; 09434 goto outgoing_exten_cleanup; 09435 } 09436 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09437 if (channel) { 09438 *channel = chan; 09439 if (chan) 09440 ast_channel_lock(chan); 09441 } 09442 if (!chan) { 09443 ast_free(as); 09444 res = -1; 09445 goto outgoing_exten_cleanup; 09446 } 09447 as->chan = chan; 09448 ast_copy_string(as->context, context, sizeof(as->context)); 09449 set_ext_pri(as->chan, exten, priority); 09450 as->timeout = timeout; 09451 ast_set_variables(chan, vars); 09452 if (account) 09453 ast_cdr_setaccount(chan, account); 09454 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09455 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09456 ast_free(as); 09457 if (channel) { 09458 *channel = NULL; 09459 ast_channel_unlock(chan); 09460 } 09461 ast_hangup(chan); 09462 res = -1; 09463 goto outgoing_exten_cleanup; 09464 } 09465 res = 0; 09466 } 09467 outgoing_exten_cleanup: 09468 ast_variables_destroy(vars); 09469 return res; 09470 }
enum ast_pbx_result ast_pbx_run | ( | struct ast_channel * | c | ) |
Execute the PBX in the current thread.
c | channel to run the pbx on |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
Zero | on success | |
non-zero | on failure |
Definition at line 5880 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_notify(), mgcp_ss(), skinny_newcall(), and unistim_ss().
05881 { 05882 return ast_pbx_run_args(c, NULL); 05883 }
enum ast_pbx_result ast_pbx_run_args | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) |
Execute the PBX in the current thread.
c | channel to run the pbx on | |
args | options for the pbx |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
Zero | on success | |
non-zero | on failure |
Definition at line 5860 of file pbx.c.
References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
05861 { 05862 enum ast_pbx_result res = AST_PBX_SUCCESS; 05863 05864 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05865 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05866 return AST_PBX_FAILED; 05867 } 05868 05869 if (increase_call_count(c)) { 05870 return AST_PBX_CALL_LIMIT; 05871 } 05872 05873 res = __ast_pbx_run(c, args); 05874 05875 decrease_call_count(); 05876 05877 return res; 05878 }
enum ast_pbx_result ast_pbx_start | ( | struct ast_channel * | c | ) |
Create a new thread and start the PBX.
c | channel to start the pbx on |
Zero | on success | |
non-zero | on failure |
Definition at line 5833 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), skinny_new(), and unistim_new().
05834 { 05835 pthread_t t; 05836 05837 if (!c) { 05838 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05839 return AST_PBX_FAILED; 05840 } 05841 05842 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05843 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05844 return AST_PBX_FAILED; 05845 } 05846 05847 if (increase_call_count(c)) 05848 return AST_PBX_CALL_LIMIT; 05849 05850 /* Start a new thread, and get something handling this channel. */ 05851 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05852 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05853 decrease_call_count(); 05854 return AST_PBX_FAILED; 05855 } 05856 05857 return AST_PBX_SUCCESS; 05858 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5890 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05891 { 05892 return totalcalls; 05893 }
int ast_rdlock_context | ( | struct ast_context * | con | ) |
Read locks a given context.
con | context to lock |
0 | on success | |
-1 | on failure |
Definition at line 10919 of file pbx.c.
References ast_rwlock_rdlock, and ast_context::lock.
Referenced by _macro_exec(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10920 { 10921 return ast_rwlock_rdlock(&con->lock); 10922 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10901 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_hint_extension(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10902 { 10903 return ast_mutex_lock(&conlock); 10904 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
This function registers a populated ast_switch structure with the asterisk switching architecture.
0 | success | |
non-zero | failure |
Definition at line 6393 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
06394 { 06395 struct ast_switch *tmp; 06396 06397 AST_RWLIST_WRLOCK(&switches); 06398 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06399 if (!strcasecmp(tmp->name, sw->name)) { 06400 AST_RWLIST_UNLOCK(&switches); 06401 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06402 return -1; 06403 } 06404 } 06405 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06406 AST_RWLIST_UNLOCK(&switches); 06407 06408 return 0; 06409 }
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).
c | not important | |
context | which context to generate the extension within | |
exten | new extension to add | |
priority | priority of new extension | |
callerid | callerid of extension | |
found | ||
combined_find_spawn | This adds a new extension to the asterisk extension list. |
0 | on success | |
-1 | on failure. |
Definition at line 5379 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), gosub_run(), and loopback_exec().
05380 { 05381 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05382 }
int ast_str_get_hint | ( | struct ast_str ** | hint, | |
ssize_t | hintsize, | |||
struct ast_str ** | name, | |||
ssize_t | namesize, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
If an extension hint exists, return non-zero.
hint | buffer for hint | |
hintsize | Maximum size of hint buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
name | buffer for name portion of hint | |
namesize | Maximum size of name buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
c | Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded. | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 5334 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and ast_str_set().
Referenced by ast_str_retrieve_variable().
05335 { 05336 struct ast_exten *e = ast_hint_extension(c, context, exten); 05337 05338 if (!e) { 05339 return 0; 05340 } 05341 05342 if (hint) { 05343 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05344 } 05345 if (name) { 05346 const char *tmp = ast_get_extension_app_data(e); 05347 if (tmp) { 05348 ast_str_set(name, namesize, "%s", tmp); 05349 } 05350 } 05351 return -1; 05352 }
const char* ast_str_retrieve_variable | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
struct varshead * | headp, | |||
const char * | var | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
var | Variable name to retrieve. |
Definition at line 3399 of file pbx.c.
References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03400 { 03401 const char not_found = '\0'; 03402 char *tmpvar; 03403 const char *ret; 03404 const char *s; /* the result */ 03405 int offset, length; 03406 int i, need_substring; 03407 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03408 char workspace[20]; 03409 03410 if (c) { 03411 ast_channel_lock(c); 03412 places[0] = &c->varshead; 03413 } 03414 /* 03415 * Make a copy of var because parse_variable_name() modifies the string. 03416 * Then if called directly, we might need to run substring() on the result; 03417 * remember this for later in 'need_substring', 'offset' and 'length' 03418 */ 03419 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03420 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03421 03422 /* 03423 * Look first into predefined variables, then into variable lists. 03424 * Variable 's' points to the result, according to the following rules: 03425 * s == ¬_found (set at the beginning) means that we did not find a 03426 * matching variable and need to look into more places. 03427 * If s != ¬_found, s is a valid result string as follows: 03428 * s = NULL if the variable does not have a value; 03429 * you typically do this when looking for an unset predefined variable. 03430 * s = workspace if the result has been assembled there; 03431 * typically done when the result is built e.g. with an snprintf(), 03432 * so we don't need to do an additional copy. 03433 * s != workspace in case we have a string, that needs to be copied 03434 * (the ast_copy_string is done once for all at the end). 03435 * Typically done when the result is already available in some string. 03436 */ 03437 s = ¬_found; /* default value */ 03438 if (c) { /* This group requires a valid channel */ 03439 /* Names with common parts are looked up a piece at a time using strncmp. */ 03440 if (!strncmp(var, "CALL", 4)) { 03441 if (!strncmp(var + 4, "ING", 3)) { 03442 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03443 ast_str_set(str, maxlen, "%d", 03444 ast_party_id_presentation(&c->caller.id)); 03445 s = ast_str_buffer(*str); 03446 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03447 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03448 s = ast_str_buffer(*str); 03449 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03450 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03451 s = ast_str_buffer(*str); 03452 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03453 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03454 s = ast_str_buffer(*str); 03455 } 03456 } 03457 } else if (!strcmp(var, "HINT")) { 03458 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03459 } else if (!strcmp(var, "HINTNAME")) { 03460 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03461 } else if (!strcmp(var, "EXTEN")) { 03462 s = c->exten; 03463 } else if (!strcmp(var, "CONTEXT")) { 03464 s = c->context; 03465 } else if (!strcmp(var, "PRIORITY")) { 03466 ast_str_set(str, maxlen, "%d", c->priority); 03467 s = ast_str_buffer(*str); 03468 } else if (!strcmp(var, "CHANNEL")) { 03469 s = c->name; 03470 } else if (!strcmp(var, "UNIQUEID")) { 03471 s = c->uniqueid; 03472 } else if (!strcmp(var, "HANGUPCAUSE")) { 03473 ast_str_set(str, maxlen, "%d", c->hangupcause); 03474 s = ast_str_buffer(*str); 03475 } 03476 } 03477 if (s == ¬_found) { /* look for more */ 03478 if (!strcmp(var, "EPOCH")) { 03479 ast_str_set(str, maxlen, "%d", (int) time(NULL)); 03480 s = ast_str_buffer(*str); 03481 } else if (!strcmp(var, "SYSTEMNAME")) { 03482 s = ast_config_AST_SYSTEM_NAME; 03483 } else if (!strcmp(var, "ENTITYID")) { 03484 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03485 s = workspace; 03486 } 03487 } 03488 /* if not found, look into chanvars or global vars */ 03489 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03490 struct ast_var_t *variables; 03491 if (!places[i]) 03492 continue; 03493 if (places[i] == &globals) 03494 ast_rwlock_rdlock(&globalslock); 03495 AST_LIST_TRAVERSE(places[i], variables, entries) { 03496 if (!strcasecmp(ast_var_name(variables), var)) { 03497 s = ast_var_value(variables); 03498 break; 03499 } 03500 } 03501 if (places[i] == &globals) 03502 ast_rwlock_unlock(&globalslock); 03503 } 03504 if (s == ¬_found || s == NULL) { 03505 ast_debug(5, "Result of '%s' is NULL\n", var); 03506 ret = NULL; 03507 } else { 03508 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03509 if (s != ast_str_buffer(*str)) { 03510 ast_str_set(str, maxlen, "%s", s); 03511 } 03512 ret = ast_str_buffer(*str); 03513 if (need_substring) { 03514 ret = ast_str_substring(*str, offset, length); 03515 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03516 } 03517 } 03518 03519 if (c) { 03520 ast_channel_unlock(c); 03521 } 03522 return ret; 03523 }
void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
templ | Variable template to expand. |
Definition at line 4422 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().
04423 { 04424 size_t used; 04425 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04426 }
void ast_str_substitute_variables_full | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | c, | |||
struct varshead * | headp, | |||
const char * | templ, | |||
size_t * | used | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
c | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. | |
used | Number of bytes read from the template. |
Definition at line 4243 of file pbx.c.
References ast_channel_unref, ast_debug, ast_dummy_channel_alloc, ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().
04244 { 04245 /* Substitutes variables into buf, based on string templ */ 04246 char *cp4 = NULL; 04247 const char *tmp, *whereweare; 04248 int orig_size = 0; 04249 int offset, offset2, isfunction; 04250 const char *nextvar, *nextexp, *nextthing; 04251 const char *vars, *vare; 04252 char *finalvars; 04253 int pos, brackets, needsub, len; 04254 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04255 04256 ast_str_reset(*buf); 04257 whereweare = tmp = templ; 04258 while (!ast_strlen_zero(whereweare)) { 04259 /* reset our buffer */ 04260 ast_str_reset(substr3); 04261 04262 /* Assume we're copying the whole remaining string */ 04263 pos = strlen(whereweare); 04264 nextvar = NULL; 04265 nextexp = NULL; 04266 nextthing = strchr(whereweare, '$'); 04267 if (nextthing) { 04268 switch (nextthing[1]) { 04269 case '{': 04270 nextvar = nextthing; 04271 pos = nextvar - whereweare; 04272 break; 04273 case '[': 04274 nextexp = nextthing; 04275 pos = nextexp - whereweare; 04276 break; 04277 default: 04278 pos = 1; 04279 } 04280 } 04281 04282 if (pos) { 04283 /* Copy that many bytes */ 04284 ast_str_append_substr(buf, maxlen, whereweare, pos); 04285 04286 templ += pos; 04287 whereweare += pos; 04288 } 04289 04290 if (nextvar) { 04291 /* We have a variable. Find the start and end, and determine 04292 if we are going to have to recursively call ourselves on the 04293 contents */ 04294 vars = vare = nextvar + 2; 04295 brackets = 1; 04296 needsub = 0; 04297 04298 /* Find the end of it */ 04299 while (brackets && *vare) { 04300 if ((vare[0] == '$') && (vare[1] == '{')) { 04301 needsub++; 04302 } else if (vare[0] == '{') { 04303 brackets++; 04304 } else if (vare[0] == '}') { 04305 brackets--; 04306 } else if ((vare[0] == '$') && (vare[1] == '[')) 04307 needsub++; 04308 vare++; 04309 } 04310 if (brackets) 04311 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04312 len = vare - vars - 1; 04313 04314 /* Skip totally over variable string */ 04315 whereweare += (len + 3); 04316 04317 /* Store variable name (and truncate) */ 04318 ast_str_set_substr(&substr1, 0, vars, len); 04319 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04320 04321 /* Substitute if necessary */ 04322 if (needsub) { 04323 size_t used; 04324 if (!substr2) { 04325 substr2 = ast_str_create(16); 04326 } 04327 04328 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04329 finalvars = ast_str_buffer(substr2); 04330 } else { 04331 finalvars = ast_str_buffer(substr1); 04332 } 04333 04334 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04335 if (isfunction) { 04336 /* Evaluate function */ 04337 if (c || !headp) { 04338 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04339 } else { 04340 struct varshead old; 04341 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04342 if (bogus) { 04343 memcpy(&old, &bogus->varshead, sizeof(old)); 04344 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04345 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04346 /* Don't deallocate the varshead that was passed in */ 04347 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04348 ast_channel_unref(bogus); 04349 } else { 04350 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04351 } 04352 } 04353 ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)"); 04354 } else { 04355 /* Retrieve variable value */ 04356 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04357 cp4 = ast_str_buffer(substr3); 04358 } 04359 if (cp4) { 04360 ast_str_substring(substr3, offset, offset2); 04361 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04362 } 04363 } else if (nextexp) { 04364 /* We have an expression. Find the start and end, and determine 04365 if we are going to have to recursively call ourselves on the 04366 contents */ 04367 vars = vare = nextexp + 2; 04368 brackets = 1; 04369 needsub = 0; 04370 04371 /* Find the end of it */ 04372 while (brackets && *vare) { 04373 if ((vare[0] == '$') && (vare[1] == '[')) { 04374 needsub++; 04375 brackets++; 04376 vare++; 04377 } else if (vare[0] == '[') { 04378 brackets++; 04379 } else if (vare[0] == ']') { 04380 brackets--; 04381 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04382 needsub++; 04383 vare++; 04384 } 04385 vare++; 04386 } 04387 if (brackets) 04388 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04389 len = vare - vars - 1; 04390 04391 /* Skip totally over expression */ 04392 whereweare += (len + 3); 04393 04394 /* Store variable name (and truncate) */ 04395 ast_str_set_substr(&substr1, 0, vars, len); 04396 04397 /* Substitute if necessary */ 04398 if (needsub) { 04399 size_t used; 04400 if (!substr2) { 04401 substr2 = ast_str_create(16); 04402 } 04403 04404 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04405 finalvars = ast_str_buffer(substr2); 04406 } else { 04407 finalvars = ast_str_buffer(substr1); 04408 } 04409 04410 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04411 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04412 } 04413 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04414 } 04415 } 04416 *used = ast_str_strlen(*buf) - orig_size; 04417 ast_free(substr1); 04418 ast_free(substr2); 04419 ast_free(substr3); 04420 }
void ast_str_substitute_variables_varshead | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct varshead * | headp, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. |
Definition at line 4428 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().
04429 { 04430 size_t used; 04431 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04432 }
int ast_thread_inhibit_escalations | ( | void | ) |
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.
Definition at line 4026 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by handle_tcptls_connection().
04027 { 04028 int *thread_inhibit_escalations; 04029 04030 thread_inhibit_escalations = ast_threadstorage_get( 04031 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04032 04033 if (thread_inhibit_escalations == NULL) { 04034 ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n"); 04035 return -1; 04036 } 04037 04038 *thread_inhibit_escalations = 1; 04039 return 0; 04040 }
int ast_unlock_context | ( | struct ast_context * | con | ) |
Unlocks | the given context |
con | context to unlock |
0 | on success | |
-1 | on failure |
Definition at line 10924 of file pbx.c.
References ast_rwlock_unlock, and ast_context::lock.
Referenced by __ast_context_destroy(), _macro_exec(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), ast_context_remove_switch2(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10925 { 10926 return ast_rwlock_unlock(&con->lock); 10927 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10906 of file pbx.c.
References ast_mutex_unlock, and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10907 { 10908 return ast_mutex_unlock(&conlock); 10909 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6411 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06412 { 06413 AST_RWLIST_WRLOCK(&switches); 06414 AST_RWLIST_REMOVE(&switches, sw, list); 06415 AST_RWLIST_UNLOCK(&switches); 06416 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 11038 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), context_used(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) | [read] |
Definition at line 11071 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
11073 { 11074 if (!ip) 11075 return con ? con->ignorepats : NULL; 11076 else 11077 return ip->next; 11078 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 11062 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), context_used(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) | [read] |
Definition at line 11047 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11049 { 11050 if (!sw) 11051 return con ? AST_LIST_FIRST(&con->alts) : NULL; 11052 else 11053 return AST_LIST_NEXT(sw, list); 11054 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 11033 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 11056 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
11058 { 11059 return priority ? priority->peer : exten; 11060 }
int ast_wrlock_context | ( | struct ast_context * | con | ) |
Write locks a given context.
con | context to lock |
0 | on success | |
-1 | on failure |
Definition at line 10914 of file pbx.c.
References ast_rwlock_wrlock, and ast_context::lock.
Referenced by __ast_context_destroy(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), and ast_context_remove_switch2().
10915 { 10916 return ast_rwlock_wrlock(&con->lock); 10917 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10896 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
10897 { 10898 return ast_mutex_lock(&conlock); 10899 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10663 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), pbx_shutdown(), and reload().
10664 { 10665 struct ast_var_t *vardata; 10666 10667 ast_rwlock_wrlock(&globalslock); 10668 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10669 ast_var_delete(vardata); 10670 ast_rwlock_unlock(&globalslock); 10671 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Return a pointer to the value of the corresponding channel variable.
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 10429 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), gosub_run(), handle_gosub(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_exec(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
10430 { 10431 struct ast_var_t *variables; 10432 const char *ret = NULL; 10433 int i; 10434 struct varshead *places[2] = { NULL, &globals }; 10435 10436 if (!name) 10437 return NULL; 10438 10439 if (chan) { 10440 ast_channel_lock(chan); 10441 places[0] = &chan->varshead; 10442 } 10443 10444 for (i = 0; i < 2; i++) { 10445 if (!places[i]) 10446 continue; 10447 if (places[i] == &globals) 10448 ast_rwlock_rdlock(&globalslock); 10449 AST_LIST_TRAVERSE(places[i], variables, entries) { 10450 if (!strcmp(name, ast_var_name(variables))) { 10451 ret = ast_var_value(variables); 10452 break; 10453 } 10454 } 10455 if (places[i] == &globals) 10456 ast_rwlock_unlock(&globalslock); 10457 if (ret) 10458 break; 10459 } 10460 10461 if (chan) 10462 ast_channel_unlock(chan); 10463 10464 return ret; 10465 }
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 at line 10467 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
10468 { 10469 struct ast_var_t *newvariable; 10470 struct varshead *headp; 10471 10472 if (name[strlen(name)-1] == ')') { 10473 char *function = ast_strdupa(name); 10474 10475 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10476 ast_func_write(chan, function, value); 10477 return; 10478 } 10479 10480 if (chan) { 10481 ast_channel_lock(chan); 10482 headp = &chan->varshead; 10483 } else { 10484 ast_rwlock_wrlock(&globalslock); 10485 headp = &globals; 10486 } 10487 10488 if (value && (newvariable = ast_var_assign(name, value))) { 10489 if (headp == &globals) 10490 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10491 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10492 } 10493 10494 if (chan) 10495 ast_channel_unlock(chan); 10496 else 10497 ast_rwlock_unlock(&globalslock); 10498 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Definition at line 3574 of file pbx.c.
References raise_exception().
03575 { 03576 /* Priority will become 1, next time through the AUTOLOOP */ 03577 return raise_exception(chan, reason, 0); 03578 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
struct ast_str ** | buf | |||
) |
Create a human-readable string, specifying all variables and their corresponding values.
chan | Channel from which to read variables | |
buf | Dynamic string in which to place the result (should be allocated with ast_str_create). |
Definition at line 10398 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
10399 { 10400 struct ast_var_t *variables; 10401 const char *var, *val; 10402 int total = 0; 10403 10404 if (!chan) 10405 return 0; 10406 10407 ast_str_reset(*buf); 10408 10409 ast_channel_lock(chan); 10410 10411 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10412 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10413 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10414 ) { 10415 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10416 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10417 break; 10418 } else 10419 total++; 10420 } else 10421 break; 10422 } 10423 10424 ast_channel_unlock(chan); 10425 10426 return total; 10427 }
int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 10557 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), and value.
Referenced by ast_compile_ael2().
10558 { 10559 char *name, *value, *mydata; 10560 10561 if (ast_compat_app_set) { 10562 return pbx_builtin_setvar_multiple(chan, data); 10563 } 10564 10565 if (ast_strlen_zero(data)) { 10566 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10567 return 0; 10568 } 10569 10570 mydata = ast_strdupa(data); 10571 name = strsep(&mydata, "="); 10572 value = mydata; 10573 if (!value) { 10574 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10575 return 0; 10576 } 10577 10578 if (strchr(name, ' ')) { 10579 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10580 } 10581 10582 pbx_builtin_setvar_helper(chan, name, value); 10583 10584 return 0; 10585 }
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 at line 10500 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), gosub_run(), handle_gosub(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_call_full(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), ring_entry(), rollback_exec(), rotate_file(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
10501 { 10502 struct ast_var_t *newvariable; 10503 struct varshead *headp; 10504 const char *nametail = name; 10505 10506 if (name[strlen(name) - 1] == ')') { 10507 char *function = ast_strdupa(name); 10508 10509 return ast_func_write(chan, function, value); 10510 } 10511 10512 if (chan) { 10513 ast_channel_lock(chan); 10514 headp = &chan->varshead; 10515 } else { 10516 ast_rwlock_wrlock(&globalslock); 10517 headp = &globals; 10518 } 10519 10520 /* For comparison purposes, we have to strip leading underscores */ 10521 if (*nametail == '_') { 10522 nametail++; 10523 if (*nametail == '_') 10524 nametail++; 10525 } 10526 10527 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10528 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10529 /* there is already such a variable, delete it */ 10530 AST_LIST_REMOVE_CURRENT(entries); 10531 ast_var_delete(newvariable); 10532 break; 10533 } 10534 } 10535 AST_LIST_TRAVERSE_SAFE_END; 10536 10537 if (value && (newvariable = ast_var_assign(name, value))) { 10538 if (headp == &globals) 10539 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10540 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10541 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10542 "Channel: %s\r\n" 10543 "Variable: %s\r\n" 10544 "Value: %s\r\n" 10545 "Uniqueid: %s\r\n", 10546 chan ? chan->name : "none", name, value, 10547 chan ? chan->uniqueid : "none"); 10548 } 10549 10550 if (chan) 10551 ast_channel_unlock(chan); 10552 else 10553 ast_rwlock_unlock(&globalslock); 10554 return 0; 10555 }
int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
Definition at line 10587 of file pbx.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
10588 { 10589 char *data; 10590 int x; 10591 AST_DECLARE_APP_ARGS(args, 10592 AST_APP_ARG(pair)[24]; 10593 ); 10594 AST_DECLARE_APP_ARGS(pair, 10595 AST_APP_ARG(name); 10596 AST_APP_ARG(value); 10597 ); 10598 10599 if (ast_strlen_zero(vdata)) { 10600 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10601 return 0; 10602 } 10603 10604 data = ast_strdupa(vdata); 10605 AST_STANDARD_APP_ARGS(args, data); 10606 10607 for (x = 0; x < args.argc; x++) { 10608 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10609 if (pair.argc == 2) { 10610 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10611 if (strchr(pair.name, ' ')) 10612 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value); 10613 } else if (!chan) { 10614 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10615 } else { 10616 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10617 } 10618 } 10619 10620 return 0; 10621 }
int pbx_checkcondition | ( | const char * | condition | ) |
Evaluate a condition.
0 | if the condition is NULL or of zero length | |
int | If the string is an integer, the integer representation of the integer is returned | |
1 | Any other non-empty string |
Definition at line 10673 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), pbx_builtin_gotoif(), and testtime_write().
10674 { 10675 int res; 10676 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10677 return 0; 10678 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10679 return res; 10680 } else { /* Strings are true */ 10681 return 1; 10682 } 10683 }
int pbx_exec | ( | struct ast_channel * | c, | |
struct ast_app * | app, | |||
const char * | data | |||
) |
Execute an application.
c | channel to execute on | |
app | which app to execute | |
data | the data passed into the app |
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.
0 | success | |
-1 | failure |
c | Channel | |
app | Application | |
data | Data for execution |
Definition at line 1451 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_exec_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01454 { 01455 int res; 01456 struct ast_module_user *u = NULL; 01457 const char *saved_c_appl; 01458 const char *saved_c_data; 01459 01460 if (c->cdr && !ast_check_hangup(c)) 01461 ast_cdr_setapp(c->cdr, app->name, data); 01462 01463 /* save channel values */ 01464 saved_c_appl= c->appl; 01465 saved_c_data= c->data; 01466 01467 c->appl = app->name; 01468 c->data = data; 01469 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01470 01471 if (app->module) 01472 u = __ast_module_user_add(app->module, c); 01473 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01474 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01475 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01476 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01477 app->name, (char *) data); 01478 } 01479 res = app->execute(c, S_OR(data, "")); 01480 if (app->module && u) 01481 __ast_module_user_remove(app->module, u); 01482 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01483 /* restore channel values */ 01484 c->appl = saved_c_appl; 01485 c->data = saved_c_data; 01486 return res; 01487 }
struct ast_exten* pbx_find_extension | ( | struct ast_channel * | chan, | |
struct ast_context * | bypass, | |||
struct pbx_find_info * | q, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
enum ext_match_t | action | |||
) | [read] |
Definition at line 2967 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().
02971 { 02972 int x, res; 02973 struct ast_context *tmp = NULL; 02974 struct ast_exten *e = NULL, *eroot = NULL; 02975 struct ast_include *i = NULL; 02976 struct ast_sw *sw = NULL; 02977 struct ast_exten pattern = {NULL, }; 02978 struct scoreboard score = {0, }; 02979 struct ast_str *tmpdata = NULL; 02980 02981 pattern.label = label; 02982 pattern.priority = priority; 02983 #ifdef NEED_DEBUG_HERE 02984 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02985 #endif 02986 02987 /* Initialize status if appropriate */ 02988 if (q->stacklen == 0) { 02989 q->status = STATUS_NO_CONTEXT; 02990 q->swo = NULL; 02991 q->data = NULL; 02992 q->foundcontext = NULL; 02993 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02994 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02995 return NULL; 02996 } 02997 02998 /* Check first to see if we've already been checked */ 02999 for (x = 0; x < q->stacklen; x++) { 03000 if (!strcasecmp(q->incstack[x], context)) 03001 return NULL; 03002 } 03003 03004 if (bypass) { /* bypass means we only look there */ 03005 tmp = bypass; 03006 } else { /* look in contexts */ 03007 tmp = find_context(context); 03008 if (!tmp) { 03009 return NULL; 03010 } 03011 } 03012 03013 if (q->status < STATUS_NO_EXTENSION) 03014 q->status = STATUS_NO_EXTENSION; 03015 03016 /* Do a search for matching extension */ 03017 03018 eroot = NULL; 03019 score.total_specificity = 0; 03020 score.exten = 0; 03021 score.total_length = 0; 03022 if (!tmp->pattern_tree && tmp->root_table) { 03023 create_match_char_tree(tmp); 03024 #ifdef NEED_DEBUG 03025 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 03026 log_match_char_tree(tmp->pattern_tree," "); 03027 #endif 03028 } 03029 #ifdef NEED_DEBUG 03030 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03031 log_match_char_tree(tmp->pattern_tree, ":: "); 03032 #endif 03033 03034 do { 03035 if (!ast_strlen_zero(overrideswitch)) { 03036 char *osw = ast_strdupa(overrideswitch), *name; 03037 struct ast_switch *asw; 03038 ast_switch_f *aswf = NULL; 03039 char *datap; 03040 int eval = 0; 03041 03042 name = strsep(&osw, "/"); 03043 asw = pbx_findswitch(name); 03044 03045 if (!asw) { 03046 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03047 break; 03048 } 03049 03050 if (osw && strchr(osw, '$')) { 03051 eval = 1; 03052 } 03053 03054 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03055 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03056 break; 03057 } else if (eval) { 03058 /* Substitute variables now */ 03059 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03060 datap = ast_str_buffer(tmpdata); 03061 } else { 03062 datap = osw; 03063 } 03064 03065 /* equivalent of extension_match_core() at the switch level */ 03066 if (action == E_CANMATCH) 03067 aswf = asw->canmatch; 03068 else if (action == E_MATCHMORE) 03069 aswf = asw->matchmore; 03070 else /* action == E_MATCH */ 03071 aswf = asw->exists; 03072 if (!aswf) { 03073 res = 0; 03074 } else { 03075 if (chan) { 03076 ast_autoservice_start(chan); 03077 } 03078 res = aswf(chan, context, exten, priority, callerid, datap); 03079 if (chan) { 03080 ast_autoservice_stop(chan); 03081 } 03082 } 03083 if (res) { /* Got a match */ 03084 q->swo = asw; 03085 q->data = datap; 03086 q->foundcontext = context; 03087 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03088 return NULL; 03089 } 03090 } 03091 } while (0); 03092 03093 if (extenpatternmatchnew) { 03094 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03095 eroot = score.exten; 03096 03097 if (score.last_char == '!' && action == E_MATCHMORE) { 03098 /* We match an extension ending in '!'. 03099 * The decision in this case is final and is NULL (no match). 03100 */ 03101 #ifdef NEED_DEBUG_HERE 03102 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03103 #endif 03104 return NULL; 03105 } 03106 03107 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03108 q->status = STATUS_SUCCESS; 03109 #ifdef NEED_DEBUG_HERE 03110 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03111 #endif 03112 return score.canmatch_exten; 03113 } 03114 03115 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03116 if (score.node) { 03117 struct ast_exten *z = trie_find_next_match(score.node); 03118 if (z) { 03119 #ifdef NEED_DEBUG_HERE 03120 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03121 #endif 03122 } else { 03123 if (score.canmatch_exten) { 03124 #ifdef NEED_DEBUG_HERE 03125 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03126 #endif 03127 return score.canmatch_exten; 03128 } else { 03129 #ifdef NEED_DEBUG_HERE 03130 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03131 #endif 03132 } 03133 } 03134 return z; 03135 } 03136 #ifdef NEED_DEBUG_HERE 03137 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03138 #endif 03139 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03140 } 03141 03142 if (eroot) { 03143 /* found entry, now look for the right priority */ 03144 if (q->status < STATUS_NO_PRIORITY) 03145 q->status = STATUS_NO_PRIORITY; 03146 e = NULL; 03147 if (action == E_FINDLABEL && label ) { 03148 if (q->status < STATUS_NO_LABEL) 03149 q->status = STATUS_NO_LABEL; 03150 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03151 } else { 03152 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03153 } 03154 if (e) { /* found a valid match */ 03155 q->status = STATUS_SUCCESS; 03156 q->foundcontext = context; 03157 #ifdef NEED_DEBUG_HERE 03158 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03159 #endif 03160 return e; 03161 } 03162 } 03163 } else { /* the old/current default exten pattern match algorithm */ 03164 03165 /* scan the list trying to match extension and CID */ 03166 eroot = NULL; 03167 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03168 int match = extension_match_core(eroot->exten, exten, action); 03169 /* 0 on fail, 1 on match, 2 on earlymatch */ 03170 03171 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03172 continue; /* keep trying */ 03173 if (match == 2 && action == E_MATCHMORE) { 03174 /* We match an extension ending in '!'. 03175 * The decision in this case is final and is NULL (no match). 03176 */ 03177 return NULL; 03178 } 03179 /* found entry, now look for the right priority */ 03180 if (q->status < STATUS_NO_PRIORITY) 03181 q->status = STATUS_NO_PRIORITY; 03182 e = NULL; 03183 if (action == E_FINDLABEL && label ) { 03184 if (q->status < STATUS_NO_LABEL) 03185 q->status = STATUS_NO_LABEL; 03186 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03187 } else { 03188 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03189 } 03190 if (e) { /* found a valid match */ 03191 q->status = STATUS_SUCCESS; 03192 q->foundcontext = context; 03193 return e; 03194 } 03195 } 03196 } 03197 03198 /* Check alternative switches */ 03199 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03200 struct ast_switch *asw = pbx_findswitch(sw->name); 03201 ast_switch_f *aswf = NULL; 03202 char *datap; 03203 03204 if (!asw) { 03205 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03206 continue; 03207 } 03208 03209 /* Substitute variables now */ 03210 if (sw->eval) { 03211 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03212 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03213 continue; 03214 } 03215 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03216 } 03217 03218 /* equivalent of extension_match_core() at the switch level */ 03219 if (action == E_CANMATCH) 03220 aswf = asw->canmatch; 03221 else if (action == E_MATCHMORE) 03222 aswf = asw->matchmore; 03223 else /* action == E_MATCH */ 03224 aswf = asw->exists; 03225 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03226 if (!aswf) 03227 res = 0; 03228 else { 03229 if (chan) 03230 ast_autoservice_start(chan); 03231 res = aswf(chan, context, exten, priority, callerid, datap); 03232 if (chan) 03233 ast_autoservice_stop(chan); 03234 } 03235 if (res) { /* Got a match */ 03236 q->swo = asw; 03237 q->data = datap; 03238 q->foundcontext = context; 03239 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03240 return NULL; 03241 } 03242 } 03243 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03244 /* Now try any includes we have in this context */ 03245 for (i = tmp->includes; i; i = i->next) { 03246 if (include_valid(i)) { 03247 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03248 #ifdef NEED_DEBUG_HERE 03249 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03250 #endif 03251 return e; 03252 } 03253 if (q->swo) 03254 return NULL; 03255 } 03256 } 03257 return NULL; 03258 }
struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Look up an application.
app | name of the app |
This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in.
Definition at line 1491 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_exec_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01492 { 01493 struct ast_app *tmp; 01494 01495 AST_RWLIST_RDLOCK(&apps); 01496 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01497 if (!strcasecmp(tmp->name, app)) 01498 break; 01499 } 01500 AST_RWLIST_UNLOCK(&apps); 01501 01502 return tmp; 01503 }
void pbx_live_dangerously | ( | int | new_live_dangerously | ) |
Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).
These dialplan functions (such as SHELL
) provide an opportunity for privilege escalation. They are okay to invoke from the dialplan, but external protocols with permission controls should not normally invoke them.
This function can globally enable/disable the execution of dangerous functions from external protocols.
new_live_dangerously | If true, enable the execution of escalating functions from external protocols. |
Definition at line 4013 of file pbx.c.
References ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by ast_readconfig().
04014 { 04015 if (new_live_dangerously && !live_dangerously) { 04016 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n" 04017 "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n"); 04018 } 04019 04020 if (!new_live_dangerously && live_dangerously) { 04021 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n"); 04022 } 04023 live_dangerously = new_live_dangerously; 04024 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
Retrieve the value of a builtin variable or variable from the channel variable stack.
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 3388 of file pbx.c.
References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_retrieve_variable(), and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03389 { 03390 struct ast_str *str = ast_str_create(16); 03391 const char *cret; 03392 03393 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03394 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03395 *ret = cret ? workspace : NULL; 03396 ast_free(str); 03397 }
int pbx_set_autofallthrough | ( | int | newval | ) |
Set "autofallthrough" flag, if newval is <0, does not actually set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.
Definition at line 5895 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05896 { 05897 int oldval = autofallthrough; 05898 autofallthrough = newval; 05899 return oldval; 05900 }
int pbx_set_extenpatternmatchnew | ( | int | newval | ) |
Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use the old linear-search algorithm. Returns previous value.
Definition at line 5902 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05903 { 05904 int oldval = extenpatternmatchnew; 05905 extenpatternmatchnew = newval; 05906 return oldval; 05907 }
void pbx_set_overrideswitch | ( | const char * | newval | ) |
Set "overrideswitch" field. If set and of nonzero length, all contexts will be tried directly through the named switch prior to any other matching within that context.
Definition at line 5909 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05910 { 05911 if (overrideswitch) { 05912 ast_free(overrideswitch); 05913 } 05914 if (!ast_strlen_zero(newval)) { 05915 overrideswitch = ast_strdup(newval); 05916 } else { 05917 overrideswitch = NULL; 05918 } 05919 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4630 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_extension_helper(), pbx_find_extension(), pbx_load_config(), realtime_exec(), rotate_file(), substituted(), try_calling(), and write_cdr().
04631 { 04632 size_t used; 04633 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04634 }
void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
struct varshead * | headp, | |||
const char * | cp1, | |||
char * | cp2, | |||
int | cp2_size, | |||
size_t * | used | |||
) |
Definition at line 4434 of file pbx.c.
References ast_alloca, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
04435 { 04436 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04437 char *cp4 = NULL; 04438 const char *tmp, *whereweare, *orig_cp2 = cp2; 04439 int length, offset, offset2, isfunction; 04440 char *workspace = NULL; 04441 char *ltmp = NULL, *var = NULL; 04442 char *nextvar, *nextexp, *nextthing; 04443 char *vars, *vare; 04444 int pos, brackets, needsub, len; 04445 04446 *cp2 = 0; /* just in case nothing ends up there */ 04447 whereweare=tmp=cp1; 04448 while (!ast_strlen_zero(whereweare) && count) { 04449 /* Assume we're copying the whole remaining string */ 04450 pos = strlen(whereweare); 04451 nextvar = NULL; 04452 nextexp = NULL; 04453 nextthing = strchr(whereweare, '$'); 04454 if (nextthing) { 04455 switch (nextthing[1]) { 04456 case '{': 04457 nextvar = nextthing; 04458 pos = nextvar - whereweare; 04459 break; 04460 case '[': 04461 nextexp = nextthing; 04462 pos = nextexp - whereweare; 04463 break; 04464 default: 04465 pos = 1; 04466 } 04467 } 04468 04469 if (pos) { 04470 /* Can't copy more than 'count' bytes */ 04471 if (pos > count) 04472 pos = count; 04473 04474 /* Copy that many bytes */ 04475 memcpy(cp2, whereweare, pos); 04476 04477 count -= pos; 04478 cp2 += pos; 04479 whereweare += pos; 04480 *cp2 = 0; 04481 } 04482 04483 if (nextvar) { 04484 /* We have a variable. Find the start and end, and determine 04485 if we are going to have to recursively call ourselves on the 04486 contents */ 04487 vars = vare = nextvar + 2; 04488 brackets = 1; 04489 needsub = 0; 04490 04491 /* Find the end of it */ 04492 while (brackets && *vare) { 04493 if ((vare[0] == '$') && (vare[1] == '{')) { 04494 needsub++; 04495 } else if (vare[0] == '{') { 04496 brackets++; 04497 } else if (vare[0] == '}') { 04498 brackets--; 04499 } else if ((vare[0] == '$') && (vare[1] == '[')) 04500 needsub++; 04501 vare++; 04502 } 04503 if (brackets) 04504 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04505 len = vare - vars - 1; 04506 04507 /* Skip totally over variable string */ 04508 whereweare += (len + 3); 04509 04510 if (!var) 04511 var = ast_alloca(VAR_BUF_SIZE); 04512 04513 /* Store variable name (and truncate) */ 04514 ast_copy_string(var, vars, len + 1); 04515 04516 /* Substitute if necessary */ 04517 if (needsub) { 04518 size_t used; 04519 if (!ltmp) 04520 ltmp = ast_alloca(VAR_BUF_SIZE); 04521 04522 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04523 vars = ltmp; 04524 } else { 04525 vars = var; 04526 } 04527 04528 if (!workspace) 04529 workspace = ast_alloca(VAR_BUF_SIZE); 04530 04531 workspace[0] = '\0'; 04532 04533 parse_variable_name(vars, &offset, &offset2, &isfunction); 04534 if (isfunction) { 04535 /* Evaluate function */ 04536 if (c || !headp) 04537 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04538 else { 04539 struct varshead old; 04540 struct ast_channel *c = ast_dummy_channel_alloc(); 04541 if (c) { 04542 memcpy(&old, &c->varshead, sizeof(old)); 04543 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04544 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04545 /* Don't deallocate the varshead that was passed in */ 04546 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04547 c = ast_channel_unref(c); 04548 } else { 04549 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04550 } 04551 } 04552 ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)"); 04553 } else { 04554 /* Retrieve variable value */ 04555 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04556 } 04557 if (cp4) { 04558 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04559 04560 length = strlen(cp4); 04561 if (length > count) 04562 length = count; 04563 memcpy(cp2, cp4, length); 04564 count -= length; 04565 cp2 += length; 04566 *cp2 = 0; 04567 } 04568 } else if (nextexp) { 04569 /* We have an expression. Find the start and end, and determine 04570 if we are going to have to recursively call ourselves on the 04571 contents */ 04572 vars = vare = nextexp + 2; 04573 brackets = 1; 04574 needsub = 0; 04575 04576 /* Find the end of it */ 04577 while (brackets && *vare) { 04578 if ((vare[0] == '$') && (vare[1] == '[')) { 04579 needsub++; 04580 brackets++; 04581 vare++; 04582 } else if (vare[0] == '[') { 04583 brackets++; 04584 } else if (vare[0] == ']') { 04585 brackets--; 04586 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04587 needsub++; 04588 vare++; 04589 } 04590 vare++; 04591 } 04592 if (brackets) 04593 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04594 len = vare - vars - 1; 04595 04596 /* Skip totally over expression */ 04597 whereweare += (len + 3); 04598 04599 if (!var) 04600 var = ast_alloca(VAR_BUF_SIZE); 04601 04602 /* Store variable name (and truncate) */ 04603 ast_copy_string(var, vars, len + 1); 04604 04605 /* Substitute if necessary */ 04606 if (needsub) { 04607 size_t used; 04608 if (!ltmp) 04609 ltmp = ast_alloca(VAR_BUF_SIZE); 04610 04611 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04612 vars = ltmp; 04613 } else { 04614 vars = var; 04615 } 04616 04617 length = ast_expr(vars, cp2, count, c); 04618 04619 if (length) { 04620 ast_debug(1, "Expression result is '%s'\n", cp2); 04621 count -= length; 04622 cp2 += length; 04623 *cp2 = 0; 04624 } 04625 } 04626 } 04627 *used = cp2 - orig_cp2; 04628 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4636 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04637 { 04638 size_t used; 04639 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04640 }