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 | ast_variable_list |
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 1169 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 1178 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 1159 of file pbx.h.
01159 { 01160 AST_CFE_NONE, 01161 AST_CFE_READ, 01162 AST_CFE_WRITE, 01163 AST_CFE_BOTH, 01164 };
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 304 of file pbx.h.
00304 { 00305 AST_PBX_SUCCESS = 0, 00306 AST_PBX_FAILED = -1, 00307 AST_PBX_CALL_LIMIT = -2, 00308 };
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 1256 of file pbx.h.
01256 { 01257 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01258 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01259 E_MATCH = 0x02, /* extension is an exact match */ 01260 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01261 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01262 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01263 };
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3903 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().
03904 { 03905 struct ast_custom_function *cur; 03906 char tmps[80]; 03907 03908 if (!acf) { 03909 return -1; 03910 } 03911 03912 acf->mod = mod; 03913 #ifdef AST_XML_DOCS 03914 acf->docsrc = AST_STATIC_DOC; 03915 #endif 03916 03917 if (acf_retrieve_docs(acf)) { 03918 return -1; 03919 } 03920 03921 AST_RWLIST_WRLOCK(&acf_root); 03922 03923 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03924 if (!strcmp(acf->name, cur->name)) { 03925 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03926 AST_RWLIST_UNLOCK(&acf_root); 03927 return -1; 03928 } 03929 } 03930 03931 /* Store in alphabetical order */ 03932 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03933 if (strcasecmp(acf->name, cur->name) < 0) { 03934 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03935 break; 03936 } 03937 } 03938 AST_RWLIST_TRAVERSE_SAFE_END; 03939 03940 if (!cur) { 03941 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03942 } 03943 03944 AST_RWLIST_UNLOCK(&acf_root); 03945 03946 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03947 03948 return 0; 03949 }
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 3951 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.
03952 { 03953 struct ast_custom_escalating_function *acf_escalation = NULL; 03954 int res; 03955 03956 res = __ast_custom_function_register(acf, mod); 03957 if (res != 0) { 03958 return -1; 03959 } 03960 03961 if (escalation == AST_CFE_NONE) { 03962 /* No escalations; no need to do anything else */ 03963 return 0; 03964 } 03965 03966 acf_escalation = ast_calloc(1, sizeof(*acf_escalation)); 03967 if (!acf_escalation) { 03968 ast_custom_function_unregister(acf); 03969 return -1; 03970 } 03971 03972 acf_escalation->acf = acf; 03973 switch (escalation) { 03974 case AST_CFE_NONE: 03975 break; 03976 case AST_CFE_READ: 03977 acf_escalation->read_escalates = 1; 03978 break; 03979 case AST_CFE_WRITE: 03980 acf_escalation->write_escalates = 1; 03981 break; 03982 case AST_CFE_BOTH: 03983 acf_escalation->read_escalates = 1; 03984 acf_escalation->write_escalates = 1; 03985 break; 03986 } 03987 03988 AST_RWLIST_WRLOCK(&escalation_root); 03989 AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list); 03990 AST_RWLIST_UNLOCK(&escalation_root); 03991 03992 return 0; 03993 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5936 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05937 { 05938 return countcalls; 05939 }
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 8696 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().
08699 { 08700 int ret = -1; 08701 struct ast_context *c; 08702 08703 c = find_context_locked(context); 08704 if (c) { 08705 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08706 application, data, datad, registrar); 08707 ast_unlock_contexts(); 08708 } 08709 08710 return ret; 08711 }
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 9057 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().
09061 { 09062 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 09063 application, data, datad, registrar, 1); 09064 }
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 8736 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().
08737 { 08738 int res = 0; 08739 struct ast_channel *tmpchan; 08740 struct { 08741 char *accountcode; 08742 char *exten; 08743 char *context; 08744 char *linkedid; 08745 char *name; 08746 struct ast_cdr *cdr; 08747 int amaflags; 08748 int state; 08749 format_t readformat; 08750 format_t writeformat; 08751 } tmpvars = { 0, }; 08752 08753 ast_channel_lock(chan); 08754 if (chan->pbx) { /* This channel is currently in the PBX */ 08755 ast_explicit_goto(chan, context, exten, priority + 1); 08756 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08757 ast_channel_unlock(chan); 08758 return res; 08759 } 08760 08761 /* In order to do it when the channel doesn't really exist within 08762 * the PBX, we have to make a new channel, masquerade, and start the PBX 08763 * at the new location */ 08764 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08765 tmpvars.exten = ast_strdupa(chan->exten); 08766 tmpvars.context = ast_strdupa(chan->context); 08767 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08768 tmpvars.name = ast_strdupa(chan->name); 08769 tmpvars.amaflags = chan->amaflags; 08770 tmpvars.state = chan->_state; 08771 tmpvars.writeformat = chan->writeformat; 08772 tmpvars.readformat = chan->readformat; 08773 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08774 08775 ast_channel_unlock(chan); 08776 08777 /* Do not hold any channel locks while calling channel_alloc() since the function 08778 * locks the channel container when linking the new channel in. */ 08779 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08780 ast_cdr_discard(tmpvars.cdr); 08781 return -1; 08782 } 08783 08784 /* copy the cdr info over */ 08785 if (tmpvars.cdr) { 08786 ast_cdr_discard(tmpchan->cdr); 08787 tmpchan->cdr = tmpvars.cdr; 08788 tmpvars.cdr = NULL; 08789 } 08790 08791 /* Make formats okay */ 08792 tmpchan->readformat = tmpvars.readformat; 08793 tmpchan->writeformat = tmpvars.writeformat; 08794 08795 /* Setup proper location. Never hold another channel lock while calling this function. */ 08796 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08797 08798 /* Masquerade into tmp channel */ 08799 if (ast_channel_masquerade(tmpchan, chan)) { 08800 /* Failed to set up the masquerade. It's probably chan_local 08801 * in the middle of optimizing itself out. Sad. :( */ 08802 ast_hangup(tmpchan); 08803 tmpchan = NULL; 08804 res = -1; 08805 } else { 08806 ast_do_masquerade(tmpchan); 08807 /* Start the PBX going on our stolen channel */ 08808 if (ast_pbx_start(tmpchan)) { 08809 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08810 ast_hangup(tmpchan); 08811 res = -1; 08812 } 08813 } 08814 08815 return res; 08816 }
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 8818 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08819 { 08820 struct ast_channel *chan; 08821 int res = -1; 08822 08823 if ((chan = ast_channel_get_by_name(channame))) { 08824 res = ast_async_goto(chan, context, exten, priority); 08825 chan = ast_channel_unref(chan); 08826 } 08827 08828 return res; 08829 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11176 of file pbx.c.
References __ast_goto_if_exists().
11177 { 11178 return __ast_goto_if_exists(chan, context, exten, priority, 1); 11179 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11241 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
11242 { 11243 return pbx_parseable_goto(chan, goto_string, 1); 11244 }
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 8319 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().
08320 { 08321 char *info; 08322 int j, num_fields, last_sep = -1; 08323 08324 i->timezone = NULL; 08325 08326 /* Check for empty just in case */ 08327 if (ast_strlen_zero(info_in)) { 08328 return 0; 08329 } 08330 08331 /* make a copy just in case we were passed a static string */ 08332 info = ast_strdupa(info_in); 08333 08334 /* count the number of fields in the timespec */ 08335 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08336 if (info[j] == ',') { 08337 last_sep = j; 08338 num_fields++; 08339 } 08340 } 08341 08342 /* save the timezone, if it is specified */ 08343 if (num_fields == 5) { 08344 i->timezone = ast_strdup(info + last_sep + 1); 08345 } 08346 08347 /* Assume everything except time */ 08348 i->monthmask = 0xfff; /* 12 bits */ 08349 i->daymask = 0x7fffffffU; /* 31 bits */ 08350 i->dowmask = 0x7f; /* 7 bits */ 08351 /* on each call, use strsep() to move info to the next argument */ 08352 get_timerange(i, strsep(&info, "|,")); 08353 if (info) 08354 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08355 if (info) 08356 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08357 if (info) 08358 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08359 return 1; 08360 }
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 5420 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().
05421 { 05422 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05423 }
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 8362 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08363 { 08364 return ast_check_timing2(i, ast_tvnow()); 08365 }
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 8367 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().
08368 { 08369 struct ast_tm tm; 08370 08371 ast_localtime(&tv, &tm, i->timezone); 08372 08373 /* If it's not the right month, return */ 08374 if (!(i->monthmask & (1 << tm.tm_mon))) 08375 return 0; 08376 08377 /* If it's not that time of the month.... */ 08378 /* Warning, tm_mday has range 1..31! */ 08379 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08380 return 0; 08381 08382 /* If it's not the right day of the week */ 08383 if (!(i->dowmask & (1 << tm.tm_wday))) 08384 return 0; 08385 08386 /* Sanity check the hour just to be safe */ 08387 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08388 ast_log(LOG_WARNING, "Insane time...\n"); 08389 return 0; 08390 } 08391 08392 /* Now the tough part, we calculate if it fits 08393 in the right time based on min/hour */ 08394 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)))) 08395 return 0; 08396 08397 /* If we got this far, then we're good */ 08398 return 1; 08399 }
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 11246 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().
11247 { 11248 struct ast_app *app = NULL; 11249 int which = 0; 11250 char *ret = NULL; 11251 size_t wordlen = strlen(word); 11252 11253 AST_RWLIST_RDLOCK(&apps); 11254 AST_RWLIST_TRAVERSE(&apps, app, list) { 11255 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 11256 ret = ast_strdup(app->name); 11257 break; 11258 } 11259 } 11260 AST_RWLIST_UNLOCK(&apps); 11261 11262 return ret; 11263 }
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 8603 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08604 { 08605 int ret = -1; 08606 struct ast_context *c; 08607 08608 c = find_context_locked(context); 08609 if (c) { 08610 ret = ast_context_add_ignorepat2(c, value, registrar); 08611 ast_unlock_contexts(); 08612 } 08613 return ret; 08614 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8616 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().
08617 { 08618 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08619 int length; 08620 char *pattern; 08621 length = sizeof(struct ast_ignorepat); 08622 length += strlen(value) + 1; 08623 if (!(ignorepat = ast_calloc(1, length))) 08624 return -1; 08625 /* The cast to char * is because we need to write the initial value. 08626 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08627 * sees the cast as dereferencing a type-punned pointer and warns about 08628 * it. This is the workaround (we're telling gcc, yes, that's really 08629 * what we wanted to do). 08630 */ 08631 pattern = (char *) ignorepat->pattern; 08632 strcpy(pattern, value); 08633 ignorepat->next = NULL; 08634 ignorepat->registrar = registrar; 08635 ast_wrlock_context(con); 08636 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08637 ignorepatl = ignorepatc; 08638 if (!strcasecmp(ignorepatc->pattern, value)) { 08639 /* Already there */ 08640 ast_unlock_context(con); 08641 ast_free(ignorepat); 08642 errno = EEXIST; 08643 return -1; 08644 } 08645 } 08646 if (ignorepatl) 08647 ignorepatl->next = ignorepat; 08648 else 08649 con->ignorepats = ignorepat; 08650 ast_unlock_context(con); 08651 return 0; 08652 08653 }
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 8147 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
08148 { 08149 int ret = -1; 08150 struct ast_context *c; 08151 08152 c = find_context_locked(context); 08153 if (c) { 08154 ret = ast_context_add_include2(c, include, registrar); 08155 ast_unlock_contexts(); 08156 } 08157 return ret; 08158 }
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 8416 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().
08418 { 08419 struct ast_include *new_include; 08420 char *c; 08421 struct ast_include *i, *il = NULL; /* include, include_last */ 08422 int length; 08423 char *p; 08424 08425 length = sizeof(struct ast_include); 08426 length += 2 * (strlen(value) + 1); 08427 08428 /* allocate new include structure ... */ 08429 if (!(new_include = ast_calloc(1, length))) 08430 return -1; 08431 /* Fill in this structure. Use 'p' for assignments, as the fields 08432 * in the structure are 'const char *' 08433 */ 08434 p = new_include->stuff; 08435 new_include->name = p; 08436 strcpy(p, value); 08437 p += strlen(value) + 1; 08438 new_include->rname = p; 08439 strcpy(p, value); 08440 /* Strip off timing info, and process if it is there */ 08441 if ( (c = strchr(p, ',')) ) { 08442 *c++ = '\0'; 08443 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08444 } 08445 new_include->next = NULL; 08446 new_include->registrar = registrar; 08447 08448 ast_wrlock_context(con); 08449 08450 /* ... go to last include and check if context is already included too... */ 08451 for (i = con->includes; i; i = i->next) { 08452 if (!strcasecmp(i->name, new_include->name)) { 08453 ast_destroy_timing(&(new_include->timing)); 08454 ast_free(new_include); 08455 ast_unlock_context(con); 08456 errno = EEXIST; 08457 return -1; 08458 } 08459 il = i; 08460 } 08461 08462 /* ... include new context into context list, unlock, return */ 08463 if (il) 08464 il->next = new_include; 08465 else 08466 con->includes = new_include; 08467 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08468 08469 ast_unlock_context(con); 08470 08471 return 0; 08472 }
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 8479 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08480 { 08481 int ret = -1; 08482 struct ast_context *c; 08483 08484 c = find_context_locked(context); 08485 if (c) { /* found, add switch to this context */ 08486 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08487 ast_unlock_contexts(); 08488 } 08489 return ret; 08490 }
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 8499 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().
08501 { 08502 struct ast_sw *new_sw; 08503 struct ast_sw *i; 08504 int length; 08505 char *p; 08506 08507 length = sizeof(struct ast_sw); 08508 length += strlen(value) + 1; 08509 if (data) 08510 length += strlen(data); 08511 length++; 08512 08513 /* allocate new sw structure ... */ 08514 if (!(new_sw = ast_calloc(1, length))) 08515 return -1; 08516 /* ... fill in this structure ... */ 08517 p = new_sw->stuff; 08518 new_sw->name = p; 08519 strcpy(new_sw->name, value); 08520 p += strlen(value) + 1; 08521 new_sw->data = p; 08522 if (data) { 08523 strcpy(new_sw->data, data); 08524 p += strlen(data) + 1; 08525 } else { 08526 strcpy(new_sw->data, ""); 08527 p++; 08528 } 08529 new_sw->eval = eval; 08530 new_sw->registrar = registrar; 08531 08532 /* ... try to lock this context ... */ 08533 ast_wrlock_context(con); 08534 08535 /* ... go to last sw and check if context is already swd too... */ 08536 AST_LIST_TRAVERSE(&con->alts, i, list) { 08537 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08538 ast_free(new_sw); 08539 ast_unlock_context(con); 08540 errno = EEXIST; 08541 return -1; 08542 } 08543 } 08544 08545 /* ... sw new context into context list, unlock, return */ 08546 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08547 08548 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08549 08550 ast_unlock_context(con); 08551 08552 return 0; 08553 }
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 9880 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().
09881 { 09882 ast_wrlock_contexts(); 09883 __ast_context_destroy(contexts, contexts_table, con,registrar); 09884 ast_unlock_contexts(); 09885 }
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 2928 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().
02929 { 02930 struct ast_context *tmp; 02931 struct fake_context item; 02932 02933 if (!name) { 02934 return NULL; 02935 } 02936 ast_rdlock_contexts(); 02937 if (contexts_table) { 02938 ast_copy_string(item.name, name, sizeof(item.name)); 02939 tmp = ast_hashtab_lookup(contexts_table, &item); 02940 } else { 02941 tmp = NULL; 02942 while ((tmp = ast_walk_contexts(tmp))) { 02943 if (!strcasecmp(name, tmp->name)) { 02944 break; 02945 } 02946 } 02947 } 02948 ast_unlock_contexts(); 02949 return tmp; 02950 }
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 7731 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().
07732 { 07733 struct ast_context *tmp, **local_contexts; 07734 struct fake_context search; 07735 int length = sizeof(struct ast_context) + strlen(name) + 1; 07736 07737 if (!contexts_table) { 07738 /* Protect creation of contexts_table from reentrancy. */ 07739 ast_wrlock_contexts(); 07740 if (!contexts_table) { 07741 contexts_table = ast_hashtab_create(17, 07742 ast_hashtab_compare_contexts, 07743 ast_hashtab_resize_java, 07744 ast_hashtab_newsize_java, 07745 ast_hashtab_hash_contexts, 07746 0); 07747 } 07748 ast_unlock_contexts(); 07749 } 07750 07751 ast_copy_string(search.name, name, sizeof(search.name)); 07752 if (!extcontexts) { 07753 ast_rdlock_contexts(); 07754 local_contexts = &contexts; 07755 tmp = ast_hashtab_lookup(contexts_table, &search); 07756 ast_unlock_contexts(); 07757 if (tmp) { 07758 tmp->refcount++; 07759 return tmp; 07760 } 07761 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07762 local_contexts = extcontexts; 07763 tmp = ast_hashtab_lookup(exttable, &search); 07764 if (tmp) { 07765 tmp->refcount++; 07766 return tmp; 07767 } 07768 } 07769 07770 if ((tmp = ast_calloc(1, length))) { 07771 ast_rwlock_init(&tmp->lock); 07772 ast_mutex_init(&tmp->macrolock); 07773 strcpy(tmp->name, name); 07774 tmp->root = NULL; 07775 tmp->root_table = NULL; 07776 tmp->registrar = ast_strdup(registrar); 07777 tmp->includes = NULL; 07778 tmp->ignorepats = NULL; 07779 tmp->refcount = 1; 07780 } else { 07781 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07782 return NULL; 07783 } 07784 07785 if (!extcontexts) { 07786 ast_wrlock_contexts(); 07787 tmp->next = *local_contexts; 07788 *local_contexts = tmp; 07789 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07790 ast_unlock_contexts(); 07791 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07792 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07793 } else { 07794 tmp->next = *local_contexts; 07795 if (exttable) 07796 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07797 07798 *local_contexts = tmp; 07799 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07800 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07801 } 07802 return tmp; 07803 }
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 6311 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06312 { 06313 struct ast_context *c; 06314 int ret = -1; 06315 06316 c = find_context_locked(context); 06317 if (c) { 06318 ast_unlock_contexts(); 06319 06320 /* if we found context, lock macrolock */ 06321 ret = ast_mutex_lock(&c->macrolock); 06322 } 06323 06324 return ret; 06325 }
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 6119 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().
06120 { 06121 return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar); 06122 }
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 6149 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().
06150 { 06151 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked); 06152 }
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 6124 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().
06125 { 06126 int ret = -1; /* default error return */ 06127 struct ast_context *c; 06128 06129 c = find_context_locked(context); 06130 if (c) { /* ... remove extension ... */ 06131 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 06132 matchcallerid, registrar, 0); 06133 ast_unlock_contexts(); 06134 } 06135 06136 return ret; 06137 }
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 6154 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().
06155 { 06156 struct ast_exten *exten, *prev_exten = NULL; 06157 struct ast_exten *peer; 06158 struct ast_exten ex, *exten2, *exten3; 06159 char dummy_name[1024]; 06160 struct ast_exten *previous_peer = NULL; 06161 struct ast_exten *next_peer = NULL; 06162 int found = 0; 06163 06164 if (!already_locked) 06165 ast_wrlock_context(con); 06166 06167 #ifdef NEED_DEBUG 06168 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 06169 #endif 06170 #ifdef CONTEXT_DEBUG 06171 check_contexts(__FILE__, __LINE__); 06172 #endif 06173 /* find this particular extension */ 06174 ex.exten = dummy_name; 06175 ex.matchcid = matchcallerid; 06176 ex.cidmatch = callerid; 06177 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 06178 exten = ast_hashtab_lookup(con->root_table, &ex); 06179 if (exten) { 06180 if (priority == 0) { 06181 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06182 if (!exten2) 06183 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); 06184 if (con->pattern_tree) { 06185 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06186 06187 if (x->exten) { /* this test for safety purposes */ 06188 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06189 x->exten = 0; /* get rid of what will become a bad pointer */ 06190 } else { 06191 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 06192 } 06193 } 06194 } else { 06195 ex.priority = priority; 06196 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 06197 if (exten2) { 06198 if (exten2->label) { /* if this exten has a label, remove that, too */ 06199 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 06200 if (!exten3) 06201 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); 06202 } 06203 06204 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 06205 if (!exten3) 06206 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); 06207 if (exten2 == exten && exten2->peer) { 06208 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06209 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 06210 } 06211 if (ast_hashtab_size(exten->peer_table) == 0) { 06212 /* well, if the last priority of an exten is to be removed, 06213 then, the extension is removed, too! */ 06214 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 06215 if (!exten3) 06216 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 06217 if (con->pattern_tree) { 06218 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06219 if (x->exten) { /* this test for safety purposes */ 06220 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06221 x->exten = 0; /* get rid of what will become a bad pointer */ 06222 } 06223 } 06224 } 06225 } else { 06226 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 06227 priority, exten->exten, con->name); 06228 } 06229 } 06230 } else { 06231 /* hmmm? this exten is not in this pattern tree? */ 06232 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 06233 extension, con->name); 06234 } 06235 #ifdef NEED_DEBUG 06236 if (con->pattern_tree) { 06237 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 06238 log_match_char_tree(con->pattern_tree, " "); 06239 } 06240 #endif 06241 06242 /* scan the extension list to find first matching extension-registrar */ 06243 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 06244 if (!strcmp(exten->exten, extension) && 06245 (!registrar || !strcmp(exten->registrar, registrar)) && 06246 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 06247 break; 06248 } 06249 if (!exten) { 06250 /* we can't find right extension */ 06251 if (!already_locked) 06252 ast_unlock_context(con); 06253 return -1; 06254 } 06255 06256 /* scan the priority list to remove extension with exten->priority == priority */ 06257 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 06258 peer && !strcmp(peer->exten, extension) && 06259 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ; 06260 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 06261 06262 if ((priority == 0 || peer->priority == priority) && 06263 (!registrar || !strcmp(peer->registrar, registrar) )) { 06264 found = 1; 06265 06266 /* we are first priority extension? */ 06267 if (!previous_peer) { 06268 /* 06269 * We are first in the priority chain, so must update the extension chain. 06270 * The next node is either the next priority or the next extension 06271 */ 06272 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 06273 if (peer->peer) { 06274 /* move the peer_table and peer_label_table down to the next peer, if 06275 it is there */ 06276 peer->peer->peer_table = peer->peer_table; 06277 peer->peer->peer_label_table = peer->peer_label_table; 06278 peer->peer_table = NULL; 06279 peer->peer_label_table = NULL; 06280 } 06281 if (!prev_exten) { /* change the root... */ 06282 con->root = next_node; 06283 } else { 06284 prev_exten->next = next_node; /* unlink */ 06285 } 06286 if (peer->peer) { /* update the new head of the pri list */ 06287 peer->peer->next = peer->next; 06288 } 06289 } else { /* easy, we are not first priority in extension */ 06290 previous_peer->peer = peer->peer; 06291 } 06292 06293 06294 /* now, free whole priority extension */ 06295 destroy_exten(peer); 06296 } else { 06297 previous_peer = peer; 06298 } 06299 } 06300 if (!already_locked) 06301 ast_unlock_context(con); 06302 return found ? 0 : -1; 06303 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8559 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08560 { 08561 int ret = -1; 08562 struct ast_context *c; 08563 08564 c = find_context_locked(context); 08565 if (c) { 08566 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08567 ast_unlock_contexts(); 08568 } 08569 return ret; 08570 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8572 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().
08573 { 08574 struct ast_ignorepat *ip, *ipl = NULL; 08575 08576 ast_wrlock_context(con); 08577 08578 for (ip = con->ignorepats; ip; ip = ip->next) { 08579 if (!strcmp(ip->pattern, ignorepat) && 08580 (!registrar || (registrar == ip->registrar))) { 08581 if (ipl) { 08582 ipl->next = ip->next; 08583 ast_free(ip); 08584 } else { 08585 con->ignorepats = ip->next; 08586 ast_free(ip); 08587 } 08588 ast_unlock_context(con); 08589 return 0; 08590 } 08591 ipl = ip; 08592 } 08593 08594 ast_unlock_context(con); 08595 errno = EINVAL; 08596 return -1; 08597 }
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 6012 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
06013 { 06014 int ret = -1; 06015 struct ast_context *c; 06016 06017 c = find_context_locked(context); 06018 if (c) { 06019 /* found, remove include from this context ... */ 06020 ret = ast_context_remove_include2(c, include, registrar); 06021 ast_unlock_contexts(); 06022 } 06023 return ret; 06024 }
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 6035 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().
06036 { 06037 struct ast_include *i, *pi = NULL; 06038 int ret = -1; 06039 06040 ast_wrlock_context(con); 06041 06042 /* find our include */ 06043 for (i = con->includes; i; pi = i, i = i->next) { 06044 if (!strcmp(i->name, include) && 06045 (!registrar || !strcmp(i->registrar, registrar))) { 06046 /* remove from list */ 06047 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 06048 if (pi) 06049 pi->next = i->next; 06050 else 06051 con->includes = i->next; 06052 /* free include and return */ 06053 ast_destroy_timing(&(i->timing)); 06054 ast_free(i); 06055 ret = 0; 06056 break; 06057 } 06058 } 06059 06060 ast_unlock_context(con); 06061 06062 return ret; 06063 }
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 6070 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
06071 { 06072 int ret = -1; /* default error return */ 06073 struct ast_context *c; 06074 06075 c = find_context_locked(context); 06076 if (c) { 06077 /* remove switch from this context ... */ 06078 ret = ast_context_remove_switch2(c, sw, data, registrar); 06079 ast_unlock_contexts(); 06080 } 06081 return ret; 06082 }
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 6092 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().
06093 { 06094 struct ast_sw *i; 06095 int ret = -1; 06096 06097 ast_wrlock_context(con); 06098 06099 /* walk switches */ 06100 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 06101 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 06102 (!registrar || !strcmp(i->registrar, registrar))) { 06103 /* found, remove from list */ 06104 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 06105 AST_LIST_REMOVE_CURRENT(list); 06106 ast_free(i); /* free switch and return */ 06107 ret = 0; 06108 break; 06109 } 06110 } 06111 AST_LIST_TRAVERSE_SAFE_END; 06112 06113 ast_unlock_context(con); 06114 06115 return ret; 06116 }
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 6332 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06333 { 06334 struct ast_context *c; 06335 int ret = -1; 06336 06337 c = find_context_locked(context); 06338 if (c) { 06339 ast_unlock_contexts(); 06340 06341 /* if we found context, unlock macrolock */ 06342 ret = ast_mutex_unlock(&c->macrolock); 06343 } 06344 06345 return ret; 06346 }
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 11131 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().
11132 { 11133 struct ast_include *inc = NULL; 11134 int res = 0; 11135 11136 while ( (inc = ast_walk_context_includes(con, inc)) ) { 11137 if (ast_context_find(inc->rname)) 11138 continue; 11139 11140 res = -1; 11141 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 11142 ast_get_context_name(con), inc->rname); 11143 break; 11144 } 11145 11146 return res; 11147 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3757 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().
03758 { 03759 struct ast_custom_function *acf = NULL; 03760 03761 AST_RWLIST_RDLOCK(&acf_root); 03762 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03763 if (!strcmp(name, acf->name)) 03764 break; 03765 } 03766 AST_RWLIST_UNLOCK(&acf_root); 03767 03768 return acf; 03769 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3771 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().
03772 { 03773 struct ast_custom_function *cur; 03774 struct ast_custom_escalating_function *cur_escalation; 03775 03776 if (!acf) { 03777 return -1; 03778 } 03779 03780 AST_RWLIST_WRLOCK(&acf_root); 03781 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03782 #ifdef AST_XML_DOCS 03783 if (cur->docsrc == AST_XML_DOC) { 03784 ast_string_field_free_memory(acf); 03785 } 03786 #endif 03787 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03788 } 03789 AST_RWLIST_UNLOCK(&acf_root); 03790 03791 /* Remove from the escalation list */ 03792 AST_RWLIST_WRLOCK(&escalation_root); 03793 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) { 03794 if (cur_escalation->acf == acf) { 03795 AST_RWLIST_REMOVE_CURRENT(list); 03796 ast_free(cur_escalation); 03797 break; 03798 } 03799 } 03800 AST_RWLIST_TRAVERSE_SAFE_END; 03801 AST_RWLIST_UNLOCK(&escalation_root); 03802 03803 return cur ? 0 : -1; 03804 }
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 8401 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 4849 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().
04850 { 04851 switch (devstate) { 04852 case AST_DEVICE_ONHOLD: 04853 return AST_EXTENSION_ONHOLD; 04854 case AST_DEVICE_BUSY: 04855 return AST_EXTENSION_BUSY; 04856 case AST_DEVICE_UNKNOWN: 04857 return AST_EXTENSION_NOT_INUSE; 04858 case AST_DEVICE_UNAVAILABLE: 04859 case AST_DEVICE_INVALID: 04860 return AST_EXTENSION_UNAVAILABLE; 04861 case AST_DEVICE_RINGINUSE: 04862 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04863 case AST_DEVICE_RINGING: 04864 return AST_EXTENSION_RINGING; 04865 case AST_DEVICE_INUSE: 04866 return AST_EXTENSION_INUSE; 04867 case AST_DEVICE_NOT_INUSE: 04868 return AST_EXTENSION_NOT_INUSE; 04869 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04870 break; 04871 } 04872 04873 return AST_EXTENSION_NOT_INUSE; 04874 }
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 5405 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().
05406 { 05407 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05408 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8713 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().
08714 { 08715 if (!chan) 08716 return -1; 08717 08718 ast_channel_lock(chan); 08719 08720 if (!ast_strlen_zero(context)) 08721 ast_copy_string(chan->context, context, sizeof(chan->context)); 08722 if (!ast_strlen_zero(exten)) 08723 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08724 if (priority > -1) { 08725 chan->priority = priority; 08726 /* see flag description in channel.h for explanation */ 08727 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08728 chan->priority--; 08729 } 08730 08731 ast_channel_unlock(chan); 08732 08733 return 0; 08734 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2905 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().
02906 { 02907 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02908 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02909 return extension_match_core(pattern, data, needmore); 02910 }
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 2670 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02671 { 02672 int cmp; 02673 02674 cmp = ext_cmp(a, b); 02675 if (cmp < 0) { 02676 return -1; 02677 } 02678 if (cmp > 0) { 02679 return 1; 02680 } 02681 return 0; 02682 }
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 2900 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().
02901 { 02902 return extension_match_core(pattern, data, E_MATCH); 02903 }
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 4919 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().
04920 { 04921 struct ast_exten *e; 04922 04923 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04924 return -1; /* No hint, return -1 */ 04925 } 04926 04927 if (e->exten[0] == '_') { 04928 /* Create this hint on-the-fly */ 04929 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04930 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04931 e->registrar); 04932 if (!(e = ast_hint_extension(c, context, exten))) { 04933 /* Improbable, but not impossible */ 04934 return -1; 04935 } 04936 } 04937 04938 return ast_extension_state2(e); /* Check all devices in the hint */ 04939 }
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 4907 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().
04908 { 04909 int i; 04910 04911 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04912 if (extension_states[i].extension_state == extension_state) 04913 return extension_states[i].text; 04914 } 04915 return "Unknown"; 04916 }
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 5140 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
05142 { 05143 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 05144 }
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 5053 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().
05055 { 05056 struct ast_hint *hint; 05057 struct ast_state_cb *state_cb; 05058 struct ast_exten *e; 05059 int id; 05060 05061 /* If there's no context and extension: add callback to statecbs list */ 05062 if (!context && !exten) { 05063 /* Prevent multiple adds from adding the same change_cb at the same time. */ 05064 ao2_lock(statecbs); 05065 05066 /* Remove any existing change_cb. */ 05067 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 05068 05069 /* Now insert the change_cb */ 05070 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05071 ao2_unlock(statecbs); 05072 return -1; 05073 } 05074 state_cb->id = 0; 05075 state_cb->change_cb = change_cb; 05076 state_cb->destroy_cb = destroy_cb; 05077 state_cb->data = data; 05078 ao2_link(statecbs, state_cb); 05079 05080 ao2_ref(state_cb, -1); 05081 ao2_unlock(statecbs); 05082 return 0; 05083 } 05084 05085 if (!context || !exten) 05086 return -1; 05087 05088 /* This callback type is for only one hint, so get the hint */ 05089 e = ast_hint_extension(NULL, context, exten); 05090 if (!e) { 05091 return -1; 05092 } 05093 05094 /* If this is a pattern, dynamically create a new extension for this 05095 * particular match. Note that this will only happen once for each 05096 * individual extension, because the pattern will no longer match first. 05097 */ 05098 if (e->exten[0] == '_') { 05099 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 05100 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 05101 e->registrar); 05102 e = ast_hint_extension(NULL, context, exten); 05103 if (!e || e->exten[0] == '_') { 05104 return -1; 05105 } 05106 } 05107 05108 /* Find the hint in the hints container */ 05109 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05110 hint = ao2_find(hints, e, 0); 05111 if (!hint) { 05112 ao2_unlock(hints); 05113 return -1; 05114 } 05115 05116 /* Now insert the callback in the callback list */ 05117 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05118 ao2_ref(hint, -1); 05119 ao2_unlock(hints); 05120 return -1; 05121 } 05122 do { 05123 id = stateid++; /* Unique ID for this callback */ 05124 /* Do not allow id to ever be -1 or 0. */ 05125 } while (id == -1 || id == 0); 05126 state_cb->id = id; 05127 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 05128 state_cb->destroy_cb = destroy_cb; 05129 state_cb->data = data; /* Data for the callback */ 05130 ao2_link(hint->callbacks, state_cb); 05131 05132 ao2_ref(state_cb, -1); 05133 ao2_ref(hint, -1); 05134 ao2_unlock(hints); 05135 05136 return id; 05137 }
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 5162 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().
05163 { 05164 struct ast_state_cb *p_cur; 05165 int ret = -1; 05166 05167 if (!id) { /* id == 0 is a callback without extension */ 05168 if (!change_cb) { 05169 return ret; 05170 } 05171 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 05172 if (p_cur) { 05173 ret = 0; 05174 ao2_ref(p_cur, -1); 05175 } 05176 } else { /* callback with extension, find the callback based on ID */ 05177 struct ast_hint *hint; 05178 05179 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05180 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 05181 if (hint) { 05182 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 05183 if (p_cur) { 05184 ret = 0; 05185 ao2_ref(p_cur, -1); 05186 } 05187 ao2_ref(hint, -1); 05188 } 05189 ao2_unlock(hints); 05190 } 05191 05192 return ret; 05193 }
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 5410 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().
05411 { 05412 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05413 }
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 5415 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05416 { 05417 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05418 }
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 4134 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().
04135 { 04136 char *copy = ast_strdupa(function); 04137 char *args = func_args(copy); 04138 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04139 int res; 04140 struct ast_module_user *u = NULL; 04141 04142 if (acfptr == NULL) { 04143 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04144 } else if (!acfptr->read && !acfptr->read2) { 04145 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04146 } else if (!is_read_allowed(acfptr)) { 04147 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04148 } else if (acfptr->read) { 04149 if (acfptr->mod) { 04150 u = __ast_module_user_add(acfptr->mod, chan); 04151 } 04152 res = acfptr->read(chan, copy, args, workspace, len); 04153 if (acfptr->mod && u) { 04154 __ast_module_user_remove(acfptr->mod, u); 04155 } 04156 return res; 04157 } else { 04158 struct ast_str *str = ast_str_create(16); 04159 if (acfptr->mod) { 04160 u = __ast_module_user_add(acfptr->mod, chan); 04161 } 04162 res = acfptr->read2(chan, copy, args, &str, 0); 04163 if (acfptr->mod && u) { 04164 __ast_module_user_remove(acfptr->mod, u); 04165 } 04166 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 04167 ast_free(str); 04168 return res; 04169 } 04170 return -1; 04171 }
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 4173 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().
04174 { 04175 char *copy = ast_strdupa(function); 04176 char *args = func_args(copy); 04177 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04178 int res; 04179 struct ast_module_user *u = NULL; 04180 04181 if (acfptr == NULL) { 04182 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04183 } else if (!acfptr->read && !acfptr->read2) { 04184 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04185 } else if (!is_read_allowed(acfptr)) { 04186 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04187 } else { 04188 if (acfptr->mod) { 04189 u = __ast_module_user_add(acfptr->mod, chan); 04190 } 04191 ast_str_reset(*str); 04192 if (acfptr->read2) { 04193 /* ast_str enabled */ 04194 res = acfptr->read2(chan, copy, args, str, maxlen); 04195 } else { 04196 /* Legacy function pointer, allocate buffer for result */ 04197 int maxsize = ast_str_size(*str); 04198 if (maxlen > -1) { 04199 if (maxlen == 0) { 04200 if (acfptr->read_max) { 04201 maxsize = acfptr->read_max; 04202 } else { 04203 maxsize = VAR_BUF_SIZE; 04204 } 04205 } else { 04206 maxsize = maxlen; 04207 } 04208 ast_str_make_space(str, maxsize); 04209 } 04210 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 04211 } 04212 if (acfptr->mod && u) { 04213 __ast_module_user_remove(acfptr->mod, u); 04214 } 04215 return res; 04216 } 04217 return -1; 04218 }
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 4220 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().
04221 { 04222 char *copy = ast_strdupa(function); 04223 char *args = func_args(copy); 04224 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04225 04226 if (acfptr == NULL) { 04227 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04228 } else if (!acfptr->write) { 04229 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 04230 } else if (!is_write_allowed(acfptr)) { 04231 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy); 04232 } else { 04233 int res; 04234 struct ast_module_user *u = NULL; 04235 if (acfptr->mod) 04236 u = __ast_module_user_add(acfptr->mod, chan); 04237 res = acfptr->write(chan, copy, args, value); 04238 if (acfptr->mod && u) 04239 __ast_module_user_remove(acfptr->mod, u); 04240 return res; 04241 } 04242 04243 return -1; 04244 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10983 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().
10984 { 10985 return con ? con->name : NULL; 10986 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 11021 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
11022 { 11023 return c ? c->registrar : NULL; 11024 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 11051 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().
11052 { 11053 return e ? e->app : NULL; 11054 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 11056 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().
11057 { 11058 return e ? e->data : NULL; 11059 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 11046 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
11047 { 11048 return e ? e->cidmatch : NULL; 11049 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10988 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().
10989 { 10990 return exten ? exten->parent : NULL; 10991 }
const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 10998 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 11041 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
11042 { 11043 return e ? e->matchcid : 0; 11044 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10993 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().
10994 { 10995 return exten ? exten->exten : NULL; 10996 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 11013 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().
11014 { 11015 return exten ? exten->priority : -1; 11016 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 11026 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11027 { 11028 return e ? e->registrar : NULL; 11029 }
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 5367 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().
05368 { 05369 struct ast_exten *e = ast_hint_extension(c, context, exten); 05370 05371 if (e) { 05372 if (hint) 05373 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05374 if (name) { 05375 const char *tmp = ast_get_extension_app_data(e); 05376 if (tmp) 05377 ast_copy_string(name, tmp, namesize); 05378 } 05379 return -1; 05380 } 05381 return 0; 05382 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 11008 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().
11009 { 11010 return ip ? ip->pattern : NULL; 11011 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 11036 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().
11037 { 11038 return ip ? ip->registrar : NULL; 11039 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 11003 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 11031 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().
11032 { 11033 return i ? i->registrar : NULL; 11034 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 11066 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().
11067 { 11068 return sw ? sw->data : NULL; 11069 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 11071 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
11072 { 11073 return sw->eval; 11074 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 11061 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().
11062 { 11063 return sw ? sw->name : NULL; 11064 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 11076 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().
11077 { 11078 return sw ? sw->registrar : NULL; 11079 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11171 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().
11172 { 11173 return __ast_goto_if_exists(chan, context, exten, priority, 0); 11174 }
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 8655 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().
08656 { 08657 struct ast_context *con = ast_context_find(context); 08658 08659 if (con) { 08660 struct ast_ignorepat *pat; 08661 08662 for (pat = con->ignorepats; pat; pat = pat->next) { 08663 if (ast_extension_match(pat->pattern, pattern)) 08664 return 1; 08665 } 08666 } 08667 08668 return 0; 08669 }
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 5425 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().
05426 { 05427 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05428 }
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 7942 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().
07943 { 07944 double ft; 07945 struct ast_context *tmp; 07946 struct ast_context *oldcontextslist; 07947 struct ast_hashtab *oldtable; 07948 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07949 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07950 struct store_hint *saved_hint; 07951 struct ast_hint *hint; 07952 struct ast_exten *exten; 07953 int length; 07954 struct ast_state_cb *thiscb; 07955 struct ast_hashtab_iter *iter; 07956 struct ao2_iterator i; 07957 struct timeval begintime; 07958 struct timeval writelocktime; 07959 struct timeval endlocktime; 07960 struct timeval enddeltime; 07961 07962 /* 07963 * It is very important that this function hold the hints 07964 * container lock _and_ the conlock during its operation; not 07965 * only do we need to ensure that the list of contexts and 07966 * extensions does not change, but also that no hint callbacks 07967 * (watchers) are added or removed during the merge/delete 07968 * process 07969 * 07970 * In addition, the locks _must_ be taken in this order, because 07971 * there are already other code paths that use this order 07972 */ 07973 07974 begintime = ast_tvnow(); 07975 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07976 ast_wrlock_contexts(); 07977 07978 if (!contexts_table) { 07979 /* Well, that's odd. There are no contexts. */ 07980 contexts_table = exttable; 07981 contexts = *extcontexts; 07982 ast_unlock_contexts(); 07983 ast_mutex_unlock(&context_merge_lock); 07984 return; 07985 } 07986 07987 iter = ast_hashtab_start_traversal(contexts_table); 07988 while ((tmp = ast_hashtab_next(iter))) { 07989 context_merge(extcontexts, exttable, tmp, registrar); 07990 } 07991 ast_hashtab_end_traversal(iter); 07992 07993 ao2_lock(hints); 07994 writelocktime = ast_tvnow(); 07995 07996 /* preserve all watchers for hints */ 07997 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07998 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07999 if (ao2_container_count(hint->callbacks)) { 08000 ao2_lock(hint); 08001 if (!hint->exten) { 08002 /* The extension has already been destroyed. (Should never happen here) */ 08003 ao2_unlock(hint); 08004 continue; 08005 } 08006 08007 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 08008 + sizeof(*saved_hint); 08009 if (!(saved_hint = ast_calloc(1, length))) { 08010 ao2_unlock(hint); 08011 continue; 08012 } 08013 08014 /* This removes all the callbacks from the hint into saved_hint. */ 08015 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 08016 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 08017 /* 08018 * We intentionally do not unref thiscb to account for the 08019 * non-ao2 reference in saved_hint->callbacks 08020 */ 08021 } 08022 08023 saved_hint->laststate = hint->laststate; 08024 saved_hint->context = saved_hint->data; 08025 strcpy(saved_hint->data, hint->exten->parent->name); 08026 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 08027 strcpy(saved_hint->exten, hint->exten->exten); 08028 ao2_unlock(hint); 08029 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 08030 } 08031 } 08032 ao2_iterator_destroy(&i); 08033 08034 /* save the old table and list */ 08035 oldtable = contexts_table; 08036 oldcontextslist = contexts; 08037 08038 /* move in the new table and list */ 08039 contexts_table = exttable; 08040 contexts = *extcontexts; 08041 08042 /* 08043 * Restore the watchers for hints that can be found; notify 08044 * those that cannot be restored. 08045 */ 08046 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 08047 struct pbx_find_info q = { .stacklen = 0 }; 08048 08049 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 08050 PRIORITY_HINT, NULL, "", E_MATCH); 08051 /* 08052 * If this is a pattern, dynamically create a new extension for this 08053 * particular match. Note that this will only happen once for each 08054 * individual extension, because the pattern will no longer match first. 08055 */ 08056 if (exten && exten->exten[0] == '_') { 08057 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 08058 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 08059 exten->registrar); 08060 /* rwlocks are not recursive locks */ 08061 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 08062 saved_hint->exten); 08063 } 08064 08065 /* Find the hint in the hints container */ 08066 hint = exten ? ao2_find(hints, exten, 0) : NULL; 08067 if (!hint) { 08068 /* 08069 * Notify watchers of this removed hint later when we aren't 08070 * encumberd by so many locks. 08071 */ 08072 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 08073 } else { 08074 ao2_lock(hint); 08075 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08076 ao2_link(hint->callbacks, thiscb); 08077 /* Ref that we added when putting into saved_hint->callbacks */ 08078 ao2_ref(thiscb, -1); 08079 } 08080 hint->laststate = saved_hint->laststate; 08081 ao2_unlock(hint); 08082 ao2_ref(hint, -1); 08083 ast_free(saved_hint); 08084 } 08085 } 08086 08087 ao2_unlock(hints); 08088 ast_unlock_contexts(); 08089 08090 /* 08091 * Notify watchers of all removed hints with the same lock 08092 * environment as handle_statechange(). 08093 */ 08094 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 08095 /* this hint has been removed, notify the watchers */ 08096 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08097 thiscb->change_cb(saved_hint->context, saved_hint->exten, 08098 AST_EXTENSION_REMOVED, thiscb->data); 08099 /* Ref that we added when putting into saved_hint->callbacks */ 08100 ao2_ref(thiscb, -1); 08101 } 08102 ast_free(saved_hint); 08103 } 08104 08105 ast_mutex_unlock(&context_merge_lock); 08106 endlocktime = ast_tvnow(); 08107 08108 /* 08109 * The old list and hashtab no longer are relevant, delete them 08110 * while the rest of asterisk is now freely using the new stuff 08111 * instead. 08112 */ 08113 08114 ast_hashtab_destroy(oldtable, NULL); 08115 08116 for (tmp = oldcontextslist; tmp; ) { 08117 struct ast_context *next; /* next starting point */ 08118 08119 next = tmp->next; 08120 __ast_internal_context_destroy(tmp); 08121 tmp = next; 08122 } 08123 enddeltime = ast_tvnow(); 08124 08125 ft = ast_tvdiff_us(writelocktime, begintime); 08126 ft /= 1000000.0; 08127 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 08128 08129 ft = ast_tvdiff_us(endlocktime, writelocktime); 08130 ft /= 1000000.0; 08131 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 08132 08133 ft = ast_tvdiff_us(enddeltime, endlocktime); 08134 ft /= 1000000.0; 08135 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 08136 08137 ft = ast_tvdiff_us(enddeltime, begintime); 08138 ft /= 1000000.0; 08139 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 08140 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11236 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().
11237 { 11238 return pbx_parseable_goto(chan, goto_string, 0); 11239 }
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 9549 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().
09550 { 09551 struct ast_channel *chan; 09552 struct app_tmp *tmp; 09553 int res = -1, cdr_res = -1; 09554 struct outgoing_helper oh; 09555 09556 memset(&oh, 0, sizeof(oh)); 09557 oh.vars = vars; 09558 oh.account = account; 09559 09560 if (locked_channel) 09561 *locked_channel = NULL; 09562 if (ast_strlen_zero(app)) { 09563 res = -1; 09564 goto outgoing_app_cleanup; 09565 } 09566 if (synchronous) { 09567 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09568 if (chan) { 09569 ast_set_variables(chan, vars); 09570 if (account) 09571 ast_cdr_setaccount(chan, account); 09572 if (chan->_state == AST_STATE_UP) { 09573 res = 0; 09574 ast_verb(4, "Channel %s was answered.\n", chan->name); 09575 tmp = ast_calloc(1, sizeof(*tmp)); 09576 if (!tmp || ast_string_field_init(tmp, 252)) { 09577 if (tmp) { 09578 ast_free(tmp); 09579 } 09580 res = -1; 09581 } else { 09582 ast_string_field_set(tmp, app, app); 09583 ast_string_field_set(tmp, data, appdata); 09584 tmp->chan = chan; 09585 if (synchronous > 1) { 09586 if (locked_channel) 09587 ast_channel_unlock(chan); 09588 ast_pbx_run_app(tmp); 09589 } else { 09590 if (locked_channel) 09591 ast_channel_lock(chan); 09592 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09593 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09594 ast_string_field_free_memory(tmp); 09595 ast_free(tmp); 09596 if (locked_channel) 09597 ast_channel_unlock(chan); 09598 ast_hangup(chan); 09599 res = -1; 09600 } else { 09601 if (locked_channel) 09602 *locked_channel = chan; 09603 } 09604 } 09605 } 09606 } else { 09607 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09608 if (chan->cdr) { /* update the cdr */ 09609 /* here we update the status of the call, which sould be busy. 09610 * if that fails then we set the status to failed */ 09611 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09612 ast_cdr_failed(chan->cdr); 09613 } 09614 ast_hangup(chan); 09615 } 09616 } 09617 09618 if (res < 0) { /* the call failed for some reason */ 09619 if (*reason == 0) { /* if the call failed (not busy or no answer) 09620 * update the cdr with the failed message */ 09621 cdr_res = ast_pbx_outgoing_cdr_failed(); 09622 if (cdr_res != 0) { 09623 res = cdr_res; 09624 goto outgoing_app_cleanup; 09625 } 09626 } 09627 } 09628 09629 } else { 09630 struct async_stat *as; 09631 if (!(as = ast_calloc(1, sizeof(*as)))) { 09632 res = -1; 09633 goto outgoing_app_cleanup; 09634 } 09635 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09636 if (!chan) { 09637 ast_free(as); 09638 res = -1; 09639 goto outgoing_app_cleanup; 09640 } 09641 as->chan = chan; 09642 ast_copy_string(as->app, app, sizeof(as->app)); 09643 if (appdata) 09644 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09645 as->timeout = timeout; 09646 ast_set_variables(chan, vars); 09647 if (account) 09648 ast_cdr_setaccount(chan, account); 09649 /* Start a new thread, and get something handling this channel. */ 09650 if (locked_channel) 09651 ast_channel_lock(chan); 09652 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09653 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09654 ast_free(as); 09655 if (locked_channel) 09656 ast_channel_unlock(chan); 09657 ast_hangup(chan); 09658 res = -1; 09659 goto outgoing_app_cleanup; 09660 } else { 09661 if (locked_channel) 09662 *locked_channel = chan; 09663 } 09664 res = 0; 09665 } 09666 outgoing_app_cleanup: 09667 ast_variables_destroy(vars); 09668 return res; 09669 }
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 9380 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().
09381 { 09382 struct ast_channel *chan; 09383 struct async_stat *as; 09384 int res = -1, cdr_res = -1; 09385 struct outgoing_helper oh; 09386 09387 if (synchronous) { 09388 oh.context = context; 09389 oh.exten = exten; 09390 oh.priority = priority; 09391 oh.cid_num = cid_num; 09392 oh.cid_name = cid_name; 09393 oh.account = account; 09394 oh.vars = vars; 09395 oh.parent_channel = NULL; 09396 09397 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09398 if (channel) { 09399 *channel = chan; 09400 if (chan) 09401 ast_channel_lock(chan); 09402 } 09403 if (chan) { 09404 if (chan->_state == AST_STATE_UP) { 09405 res = 0; 09406 ast_verb(4, "Channel %s was answered.\n", chan->name); 09407 09408 if (synchronous > 1) { 09409 if (channel) 09410 ast_channel_unlock(chan); 09411 if (ast_pbx_run(chan)) { 09412 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09413 if (channel) 09414 *channel = NULL; 09415 ast_hangup(chan); 09416 chan = NULL; 09417 res = -1; 09418 } 09419 } else { 09420 if (ast_pbx_start(chan)) { 09421 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09422 if (channel) { 09423 *channel = NULL; 09424 ast_channel_unlock(chan); 09425 } 09426 ast_hangup(chan); 09427 res = -1; 09428 } 09429 chan = NULL; 09430 } 09431 } else { 09432 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09433 09434 if (chan->cdr) { /* update the cdr */ 09435 /* here we update the status of the call, which sould be busy. 09436 * if that fails then we set the status to failed */ 09437 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09438 ast_cdr_failed(chan->cdr); 09439 } 09440 09441 if (channel) { 09442 *channel = NULL; 09443 ast_channel_unlock(chan); 09444 } 09445 ast_hangup(chan); 09446 chan = NULL; 09447 } 09448 } 09449 09450 if (res < 0) { /* the call failed for some reason */ 09451 if (*reason == 0) { /* if the call failed (not busy or no answer) 09452 * update the cdr with the failed message */ 09453 cdr_res = ast_pbx_outgoing_cdr_failed(); 09454 if (cdr_res != 0) { 09455 res = cdr_res; 09456 goto outgoing_exten_cleanup; 09457 } 09458 } 09459 09460 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09461 /* check if "failed" exists */ 09462 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09463 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09464 if (chan) { 09465 char failed_reason[4] = ""; 09466 if (!ast_strlen_zero(context)) 09467 ast_copy_string(chan->context, context, sizeof(chan->context)); 09468 set_ext_pri(chan, "failed", 1); 09469 ast_set_variables(chan, vars); 09470 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09471 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09472 if (account) 09473 ast_cdr_setaccount(chan, account); 09474 if (ast_pbx_run(chan)) { 09475 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09476 ast_hangup(chan); 09477 } 09478 chan = NULL; 09479 } 09480 } 09481 } 09482 } else { 09483 if (!(as = ast_calloc(1, sizeof(*as)))) { 09484 res = -1; 09485 goto outgoing_exten_cleanup; 09486 } 09487 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09488 if (channel) { 09489 *channel = chan; 09490 if (chan) 09491 ast_channel_lock(chan); 09492 } 09493 if (!chan) { 09494 ast_free(as); 09495 res = -1; 09496 goto outgoing_exten_cleanup; 09497 } 09498 as->chan = chan; 09499 ast_copy_string(as->context, context, sizeof(as->context)); 09500 set_ext_pri(as->chan, exten, priority); 09501 as->timeout = timeout; 09502 ast_set_variables(chan, vars); 09503 if (account) 09504 ast_cdr_setaccount(chan, account); 09505 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09506 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09507 ast_free(as); 09508 if (channel) { 09509 *channel = NULL; 09510 ast_channel_unlock(chan); 09511 } 09512 ast_hangup(chan); 09513 res = -1; 09514 goto outgoing_exten_cleanup; 09515 } 09516 res = 0; 09517 } 09518 outgoing_exten_cleanup: 09519 ast_variables_destroy(vars); 09520 return res; 09521 }
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 5931 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().
05932 { 05933 return ast_pbx_run_args(c, NULL); 05934 }
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 5911 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().
05912 { 05913 enum ast_pbx_result res = AST_PBX_SUCCESS; 05914 05915 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05916 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05917 return AST_PBX_FAILED; 05918 } 05919 05920 if (increase_call_count(c)) { 05921 return AST_PBX_CALL_LIMIT; 05922 } 05923 05924 res = __ast_pbx_run(c, args); 05925 05926 decrease_call_count(); 05927 05928 return res; 05929 }
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 5884 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().
05885 { 05886 pthread_t t; 05887 05888 if (!c) { 05889 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05890 return AST_PBX_FAILED; 05891 } 05892 05893 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05894 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05895 return AST_PBX_FAILED; 05896 } 05897 05898 if (increase_call_count(c)) 05899 return AST_PBX_CALL_LIMIT; 05900 05901 /* Start a new thread, and get something handling this channel. */ 05902 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05903 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05904 decrease_call_count(); 05905 return AST_PBX_FAILED; 05906 } 05907 05908 return AST_PBX_SUCCESS; 05909 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5941 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05942 { 05943 return totalcalls; 05944 }
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 10970 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().
10971 { 10972 return ast_rwlock_rdlock(&con->lock); 10973 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10952 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().
10953 { 10954 return ast_mutex_lock(&conlock); 10955 }
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 6444 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().
06445 { 06446 struct ast_switch *tmp; 06447 06448 AST_RWLIST_WRLOCK(&switches); 06449 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06450 if (!strcasecmp(tmp->name, sw->name)) { 06451 AST_RWLIST_UNLOCK(&switches); 06452 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06453 return -1; 06454 } 06455 } 06456 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06457 AST_RWLIST_UNLOCK(&switches); 06458 06459 return 0; 06460 }
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 5430 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().
05431 { 05432 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05433 }
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 5385 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().
05386 { 05387 struct ast_exten *e = ast_hint_extension(c, context, exten); 05388 05389 if (!e) { 05390 return 0; 05391 } 05392 05393 if (hint) { 05394 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05395 } 05396 if (name) { 05397 const char *tmp = ast_get_extension_app_data(e); 05398 if (tmp) { 05399 ast_str_set(name, namesize, "%s", tmp); 05400 } 05401 } 05402 return -1; 05403 }
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 3402 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().
03403 { 03404 const char not_found = '\0'; 03405 char *tmpvar; 03406 const char *ret; 03407 const char *s; /* the result */ 03408 int offset, length; 03409 int i, need_substring; 03410 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03411 char workspace[20]; 03412 03413 if (c) { 03414 ast_channel_lock(c); 03415 places[0] = &c->varshead; 03416 } 03417 /* 03418 * Make a copy of var because parse_variable_name() modifies the string. 03419 * Then if called directly, we might need to run substring() on the result; 03420 * remember this for later in 'need_substring', 'offset' and 'length' 03421 */ 03422 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03423 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03424 03425 /* 03426 * Look first into predefined variables, then into variable lists. 03427 * Variable 's' points to the result, according to the following rules: 03428 * s == ¬_found (set at the beginning) means that we did not find a 03429 * matching variable and need to look into more places. 03430 * If s != ¬_found, s is a valid result string as follows: 03431 * s = NULL if the variable does not have a value; 03432 * you typically do this when looking for an unset predefined variable. 03433 * s = workspace if the result has been assembled there; 03434 * typically done when the result is built e.g. with an snprintf(), 03435 * so we don't need to do an additional copy. 03436 * s != workspace in case we have a string, that needs to be copied 03437 * (the ast_copy_string is done once for all at the end). 03438 * Typically done when the result is already available in some string. 03439 */ 03440 s = ¬_found; /* default value */ 03441 if (c) { /* This group requires a valid channel */ 03442 /* Names with common parts are looked up a piece at a time using strncmp. */ 03443 if (!strncmp(var, "CALL", 4)) { 03444 if (!strncmp(var + 4, "ING", 3)) { 03445 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03446 ast_str_set(str, maxlen, "%d", 03447 ast_party_id_presentation(&c->caller.id)); 03448 s = ast_str_buffer(*str); 03449 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03450 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03451 s = ast_str_buffer(*str); 03452 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03453 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03454 s = ast_str_buffer(*str); 03455 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03456 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03457 s = ast_str_buffer(*str); 03458 } 03459 } 03460 } else if (!strcmp(var, "HINT")) { 03461 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03462 } else if (!strcmp(var, "HINTNAME")) { 03463 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03464 } else if (!strcmp(var, "EXTEN")) { 03465 s = c->exten; 03466 } else if (!strcmp(var, "CONTEXT")) { 03467 s = c->context; 03468 } else if (!strcmp(var, "PRIORITY")) { 03469 ast_str_set(str, maxlen, "%d", c->priority); 03470 s = ast_str_buffer(*str); 03471 } else if (!strcmp(var, "CHANNEL")) { 03472 s = c->name; 03473 } else if (!strcmp(var, "UNIQUEID")) { 03474 s = c->uniqueid; 03475 } else if (!strcmp(var, "HANGUPCAUSE")) { 03476 ast_str_set(str, maxlen, "%d", c->hangupcause); 03477 s = ast_str_buffer(*str); 03478 } 03479 } 03480 if (s == ¬_found) { /* look for more */ 03481 if (!strcmp(var, "EPOCH")) { 03482 ast_str_set(str, maxlen, "%d", (int) time(NULL)); 03483 s = ast_str_buffer(*str); 03484 } else if (!strcmp(var, "SYSTEMNAME")) { 03485 s = ast_config_AST_SYSTEM_NAME; 03486 } else if (!strcmp(var, "ENTITYID")) { 03487 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03488 s = workspace; 03489 } 03490 } 03491 /* if not found, look into chanvars or global vars */ 03492 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03493 struct ast_var_t *variables; 03494 if (!places[i]) 03495 continue; 03496 if (places[i] == &globals) 03497 ast_rwlock_rdlock(&globalslock); 03498 AST_LIST_TRAVERSE(places[i], variables, entries) { 03499 if (!strcasecmp(ast_var_name(variables), var)) { 03500 s = ast_var_value(variables); 03501 break; 03502 } 03503 } 03504 if (places[i] == &globals) 03505 ast_rwlock_unlock(&globalslock); 03506 } 03507 if (s == ¬_found || s == NULL) { 03508 ast_debug(5, "Result of '%s' is NULL\n", var); 03509 ret = NULL; 03510 } else { 03511 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03512 if (s != ast_str_buffer(*str)) { 03513 ast_str_set(str, maxlen, "%s", s); 03514 } 03515 ret = ast_str_buffer(*str); 03516 if (need_substring) { 03517 ret = ast_str_substring(*str, offset, length); 03518 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03519 } 03520 } 03521 03522 if (c) { 03523 ast_channel_unlock(c); 03524 } 03525 return ret; 03526 }
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 4425 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().
04426 { 04427 size_t used; 04428 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04429 }
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 4246 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().
04247 { 04248 /* Substitutes variables into buf, based on string templ */ 04249 char *cp4 = NULL; 04250 const char *tmp, *whereweare; 04251 int orig_size = 0; 04252 int offset, offset2, isfunction; 04253 const char *nextvar, *nextexp, *nextthing; 04254 const char *vars, *vare; 04255 char *finalvars; 04256 int pos, brackets, needsub, len; 04257 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04258 04259 ast_str_reset(*buf); 04260 whereweare = tmp = templ; 04261 while (!ast_strlen_zero(whereweare)) { 04262 /* reset our buffer */ 04263 ast_str_reset(substr3); 04264 04265 /* Assume we're copying the whole remaining string */ 04266 pos = strlen(whereweare); 04267 nextvar = NULL; 04268 nextexp = NULL; 04269 nextthing = strchr(whereweare, '$'); 04270 if (nextthing) { 04271 switch (nextthing[1]) { 04272 case '{': 04273 nextvar = nextthing; 04274 pos = nextvar - whereweare; 04275 break; 04276 case '[': 04277 nextexp = nextthing; 04278 pos = nextexp - whereweare; 04279 break; 04280 default: 04281 pos = 1; 04282 } 04283 } 04284 04285 if (pos) { 04286 /* Copy that many bytes */ 04287 ast_str_append_substr(buf, maxlen, whereweare, pos); 04288 04289 templ += pos; 04290 whereweare += pos; 04291 } 04292 04293 if (nextvar) { 04294 /* We have a variable. Find the start and end, and determine 04295 if we are going to have to recursively call ourselves on the 04296 contents */ 04297 vars = vare = nextvar + 2; 04298 brackets = 1; 04299 needsub = 0; 04300 04301 /* Find the end of it */ 04302 while (brackets && *vare) { 04303 if ((vare[0] == '$') && (vare[1] == '{')) { 04304 needsub++; 04305 } else if (vare[0] == '{') { 04306 brackets++; 04307 } else if (vare[0] == '}') { 04308 brackets--; 04309 } else if ((vare[0] == '$') && (vare[1] == '[')) 04310 needsub++; 04311 vare++; 04312 } 04313 if (brackets) 04314 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04315 len = vare - vars - 1; 04316 04317 /* Skip totally over variable string */ 04318 whereweare += (len + 3); 04319 04320 /* Store variable name (and truncate) */ 04321 ast_str_set_substr(&substr1, 0, vars, len); 04322 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04323 04324 /* Substitute if necessary */ 04325 if (needsub) { 04326 size_t used; 04327 if (!substr2) { 04328 substr2 = ast_str_create(16); 04329 } 04330 04331 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04332 finalvars = ast_str_buffer(substr2); 04333 } else { 04334 finalvars = ast_str_buffer(substr1); 04335 } 04336 04337 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04338 if (isfunction) { 04339 /* Evaluate function */ 04340 if (c || !headp) { 04341 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04342 } else { 04343 struct varshead old; 04344 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04345 if (bogus) { 04346 memcpy(&old, &bogus->varshead, sizeof(old)); 04347 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04348 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04349 /* Don't deallocate the varshead that was passed in */ 04350 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04351 ast_channel_unref(bogus); 04352 } else { 04353 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04354 } 04355 } 04356 ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)"); 04357 } else { 04358 /* Retrieve variable value */ 04359 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04360 cp4 = ast_str_buffer(substr3); 04361 } 04362 if (cp4) { 04363 ast_str_substring(substr3, offset, offset2); 04364 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04365 } 04366 } else if (nextexp) { 04367 /* We have an expression. Find the start and end, and determine 04368 if we are going to have to recursively call ourselves on the 04369 contents */ 04370 vars = vare = nextexp + 2; 04371 brackets = 1; 04372 needsub = 0; 04373 04374 /* Find the end of it */ 04375 while (brackets && *vare) { 04376 if ((vare[0] == '$') && (vare[1] == '[')) { 04377 needsub++; 04378 brackets++; 04379 vare++; 04380 } else if (vare[0] == '[') { 04381 brackets++; 04382 } else if (vare[0] == ']') { 04383 brackets--; 04384 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04385 needsub++; 04386 vare++; 04387 } 04388 vare++; 04389 } 04390 if (brackets) 04391 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04392 len = vare - vars - 1; 04393 04394 /* Skip totally over expression */ 04395 whereweare += (len + 3); 04396 04397 /* Store variable name (and truncate) */ 04398 ast_str_set_substr(&substr1, 0, vars, len); 04399 04400 /* Substitute if necessary */ 04401 if (needsub) { 04402 size_t used; 04403 if (!substr2) { 04404 substr2 = ast_str_create(16); 04405 } 04406 04407 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04408 finalvars = ast_str_buffer(substr2); 04409 } else { 04410 finalvars = ast_str_buffer(substr1); 04411 } 04412 04413 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04414 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04415 } 04416 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04417 } 04418 } 04419 *used = ast_str_strlen(*buf) - orig_size; 04420 ast_free(substr1); 04421 ast_free(substr2); 04422 ast_free(substr3); 04423 }
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 4431 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().
04432 { 04433 size_t used; 04434 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04435 }
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 4029 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by handle_tcptls_connection().
04030 { 04031 int *thread_inhibit_escalations; 04032 04033 thread_inhibit_escalations = ast_threadstorage_get( 04034 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04035 04036 if (thread_inhibit_escalations == NULL) { 04037 ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n"); 04038 return -1; 04039 } 04040 04041 *thread_inhibit_escalations = 1; 04042 return 0; 04043 }
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 10975 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().
10976 { 10977 return ast_rwlock_unlock(&con->lock); 10978 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10957 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().
10958 { 10959 return ast_mutex_unlock(&conlock); 10960 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6462 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06463 { 06464 AST_RWLIST_WRLOCK(&switches); 06465 AST_RWLIST_REMOVE(&switches, sw, list); 06466 AST_RWLIST_UNLOCK(&switches); 06467 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 11089 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 11122 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().
11124 { 11125 if (!ip) 11126 return con ? con->ignorepats : NULL; 11127 else 11128 return ip->next; 11129 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 11113 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 11098 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().
11100 { 11101 if (!sw) 11102 return con ? AST_LIST_FIRST(&con->alts) : NULL; 11103 else 11104 return AST_LIST_NEXT(sw, list); 11105 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 11084 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 11107 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().
11109 { 11110 return priority ? priority->peer : exten; 11111 }
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 10965 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().
10966 { 10967 return ast_rwlock_wrlock(&con->lock); 10968 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10947 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().
10948 { 10949 return ast_mutex_lock(&conlock); 10950 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10714 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().
10715 { 10716 struct ast_var_t *vardata; 10717 10718 ast_rwlock_wrlock(&globalslock); 10719 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10720 ast_var_delete(vardata); 10721 ast_rwlock_unlock(&globalslock); 10722 }
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 10480 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().
10481 { 10482 struct ast_var_t *variables; 10483 const char *ret = NULL; 10484 int i; 10485 struct varshead *places[2] = { NULL, &globals }; 10486 10487 if (!name) 10488 return NULL; 10489 10490 if (chan) { 10491 ast_channel_lock(chan); 10492 places[0] = &chan->varshead; 10493 } 10494 10495 for (i = 0; i < 2; i++) { 10496 if (!places[i]) 10497 continue; 10498 if (places[i] == &globals) 10499 ast_rwlock_rdlock(&globalslock); 10500 AST_LIST_TRAVERSE(places[i], variables, entries) { 10501 if (!strcmp(name, ast_var_name(variables))) { 10502 ret = ast_var_value(variables); 10503 break; 10504 } 10505 } 10506 if (places[i] == &globals) 10507 ast_rwlock_unlock(&globalslock); 10508 if (ret) 10509 break; 10510 } 10511 10512 if (chan) 10513 ast_channel_unlock(chan); 10514 10515 return ret; 10516 }
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 10518 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().
10519 { 10520 struct ast_var_t *newvariable; 10521 struct varshead *headp; 10522 10523 if (name[strlen(name)-1] == ')') { 10524 char *function = ast_strdupa(name); 10525 10526 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10527 ast_func_write(chan, function, value); 10528 return; 10529 } 10530 10531 if (chan) { 10532 ast_channel_lock(chan); 10533 headp = &chan->varshead; 10534 } else { 10535 ast_rwlock_wrlock(&globalslock); 10536 headp = &globals; 10537 } 10538 10539 if (value && (newvariable = ast_var_assign(name, value))) { 10540 if (headp == &globals) 10541 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10542 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10543 } 10544 10545 if (chan) 10546 ast_channel_unlock(chan); 10547 else 10548 ast_rwlock_unlock(&globalslock); 10549 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Definition at line 3577 of file pbx.c.
References raise_exception().
03578 { 03579 /* Priority will become 1, next time through the AUTOLOOP */ 03580 return raise_exception(chan, reason, 0); 03581 }
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 10449 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().
10450 { 10451 struct ast_var_t *variables; 10452 const char *var, *val; 10453 int total = 0; 10454 10455 if (!chan) 10456 return 0; 10457 10458 ast_str_reset(*buf); 10459 10460 ast_channel_lock(chan); 10461 10462 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10463 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10464 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10465 ) { 10466 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10467 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10468 break; 10469 } else 10470 total++; 10471 } else 10472 break; 10473 } 10474 10475 ast_channel_unlock(chan); 10476 10477 return total; 10478 }
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 10608 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().
10609 { 10610 char *name, *value, *mydata; 10611 10612 if (ast_compat_app_set) { 10613 return pbx_builtin_setvar_multiple(chan, data); 10614 } 10615 10616 if (ast_strlen_zero(data)) { 10617 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10618 return 0; 10619 } 10620 10621 mydata = ast_strdupa(data); 10622 name = strsep(&mydata, "="); 10623 value = mydata; 10624 if (!value) { 10625 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10626 return 0; 10627 } 10628 10629 if (strchr(name, ' ')) { 10630 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10631 } 10632 10633 pbx_builtin_setvar_helper(chan, name, value); 10634 10635 return 0; 10636 }
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 10551 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_LIST_HEAD(), 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(), 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().
10552 { 10553 struct ast_var_t *newvariable; 10554 struct varshead *headp; 10555 const char *nametail = name; 10556 10557 if (name[strlen(name) - 1] == ')') { 10558 char *function = ast_strdupa(name); 10559 10560 return ast_func_write(chan, function, value); 10561 } 10562 10563 if (chan) { 10564 ast_channel_lock(chan); 10565 headp = &chan->varshead; 10566 } else { 10567 ast_rwlock_wrlock(&globalslock); 10568 headp = &globals; 10569 } 10570 10571 /* For comparison purposes, we have to strip leading underscores */ 10572 if (*nametail == '_') { 10573 nametail++; 10574 if (*nametail == '_') 10575 nametail++; 10576 } 10577 10578 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10579 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10580 /* there is already such a variable, delete it */ 10581 AST_LIST_REMOVE_CURRENT(entries); 10582 ast_var_delete(newvariable); 10583 break; 10584 } 10585 } 10586 AST_LIST_TRAVERSE_SAFE_END; 10587 10588 if (value && (newvariable = ast_var_assign(name, value))) { 10589 if (headp == &globals) 10590 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10591 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10592 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10593 "Channel: %s\r\n" 10594 "Variable: %s\r\n" 10595 "Value: %s\r\n" 10596 "Uniqueid: %s\r\n", 10597 chan ? chan->name : "none", name, value, 10598 chan ? chan->uniqueid : "none"); 10599 } 10600 10601 if (chan) 10602 ast_channel_unlock(chan); 10603 else 10604 ast_rwlock_unlock(&globalslock); 10605 return 0; 10606 }
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 10638 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().
10639 { 10640 char *data; 10641 int x; 10642 AST_DECLARE_APP_ARGS(args, 10643 AST_APP_ARG(pair)[24]; 10644 ); 10645 AST_DECLARE_APP_ARGS(pair, 10646 AST_APP_ARG(name); 10647 AST_APP_ARG(value); 10648 ); 10649 10650 if (ast_strlen_zero(vdata)) { 10651 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10652 return 0; 10653 } 10654 10655 data = ast_strdupa(vdata); 10656 AST_STANDARD_APP_ARGS(args, data); 10657 10658 for (x = 0; x < args.argc; x++) { 10659 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10660 if (pair.argc == 2) { 10661 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10662 if (strchr(pair.name, ' ')) 10663 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); 10664 } else if (!chan) { 10665 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10666 } else { 10667 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10668 } 10669 } 10670 10671 return 0; 10672 }
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 10724 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().
10725 { 10726 int res; 10727 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10728 return 0; 10729 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10730 return res; 10731 } else { /* Strings are true */ 10732 return 1; 10733 } 10734 }
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 1454 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().
01457 { 01458 int res; 01459 struct ast_module_user *u = NULL; 01460 const char *saved_c_appl; 01461 const char *saved_c_data; 01462 01463 if (c->cdr && !ast_check_hangup(c)) 01464 ast_cdr_setapp(c->cdr, app->name, data); 01465 01466 /* save channel values */ 01467 saved_c_appl= c->appl; 01468 saved_c_data= c->data; 01469 01470 c->appl = app->name; 01471 c->data = data; 01472 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01473 01474 if (app->module) 01475 u = __ast_module_user_add(app->module, c); 01476 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01477 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01478 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01479 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01480 app->name, (char *) data); 01481 } 01482 res = app->execute(c, S_OR(data, "")); 01483 if (app->module && u) 01484 __ast_module_user_remove(app->module, u); 01485 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01486 /* restore channel values */ 01487 c->appl = saved_c_appl; 01488 c->data = saved_c_data; 01489 return res; 01490 }
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 2970 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().
02974 { 02975 int x, res; 02976 struct ast_context *tmp = NULL; 02977 struct ast_exten *e = NULL, *eroot = NULL; 02978 struct ast_include *i = NULL; 02979 struct ast_sw *sw = NULL; 02980 struct ast_exten pattern = {NULL, }; 02981 struct scoreboard score = {0, }; 02982 struct ast_str *tmpdata = NULL; 02983 02984 pattern.label = label; 02985 pattern.priority = priority; 02986 #ifdef NEED_DEBUG_HERE 02987 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02988 #endif 02989 02990 /* Initialize status if appropriate */ 02991 if (q->stacklen == 0) { 02992 q->status = STATUS_NO_CONTEXT; 02993 q->swo = NULL; 02994 q->data = NULL; 02995 q->foundcontext = NULL; 02996 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02997 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02998 return NULL; 02999 } 03000 03001 /* Check first to see if we've already been checked */ 03002 for (x = 0; x < q->stacklen; x++) { 03003 if (!strcasecmp(q->incstack[x], context)) 03004 return NULL; 03005 } 03006 03007 if (bypass) { /* bypass means we only look there */ 03008 tmp = bypass; 03009 } else { /* look in contexts */ 03010 tmp = find_context(context); 03011 if (!tmp) { 03012 return NULL; 03013 } 03014 } 03015 03016 if (q->status < STATUS_NO_EXTENSION) 03017 q->status = STATUS_NO_EXTENSION; 03018 03019 /* Do a search for matching extension */ 03020 03021 eroot = NULL; 03022 score.total_specificity = 0; 03023 score.exten = 0; 03024 score.total_length = 0; 03025 if (!tmp->pattern_tree && tmp->root_table) { 03026 create_match_char_tree(tmp); 03027 #ifdef NEED_DEBUG 03028 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 03029 log_match_char_tree(tmp->pattern_tree," "); 03030 #endif 03031 } 03032 #ifdef NEED_DEBUG 03033 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03034 log_match_char_tree(tmp->pattern_tree, ":: "); 03035 #endif 03036 03037 do { 03038 if (!ast_strlen_zero(overrideswitch)) { 03039 char *osw = ast_strdupa(overrideswitch), *name; 03040 struct ast_switch *asw; 03041 ast_switch_f *aswf = NULL; 03042 char *datap; 03043 int eval = 0; 03044 03045 name = strsep(&osw, "/"); 03046 asw = pbx_findswitch(name); 03047 03048 if (!asw) { 03049 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03050 break; 03051 } 03052 03053 if (osw && strchr(osw, '$')) { 03054 eval = 1; 03055 } 03056 03057 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03058 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03059 break; 03060 } else if (eval) { 03061 /* Substitute variables now */ 03062 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03063 datap = ast_str_buffer(tmpdata); 03064 } else { 03065 datap = osw; 03066 } 03067 03068 /* equivalent of extension_match_core() at the switch level */ 03069 if (action == E_CANMATCH) 03070 aswf = asw->canmatch; 03071 else if (action == E_MATCHMORE) 03072 aswf = asw->matchmore; 03073 else /* action == E_MATCH */ 03074 aswf = asw->exists; 03075 if (!aswf) { 03076 res = 0; 03077 } else { 03078 if (chan) { 03079 ast_autoservice_start(chan); 03080 } 03081 res = aswf(chan, context, exten, priority, callerid, datap); 03082 if (chan) { 03083 ast_autoservice_stop(chan); 03084 } 03085 } 03086 if (res) { /* Got a match */ 03087 q->swo = asw; 03088 q->data = datap; 03089 q->foundcontext = context; 03090 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03091 return NULL; 03092 } 03093 } 03094 } while (0); 03095 03096 if (extenpatternmatchnew) { 03097 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03098 eroot = score.exten; 03099 03100 if (score.last_char == '!' && action == E_MATCHMORE) { 03101 /* We match an extension ending in '!'. 03102 * The decision in this case is final and is NULL (no match). 03103 */ 03104 #ifdef NEED_DEBUG_HERE 03105 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03106 #endif 03107 return NULL; 03108 } 03109 03110 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03111 q->status = STATUS_SUCCESS; 03112 #ifdef NEED_DEBUG_HERE 03113 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03114 #endif 03115 return score.canmatch_exten; 03116 } 03117 03118 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03119 if (score.node) { 03120 struct ast_exten *z = trie_find_next_match(score.node); 03121 if (z) { 03122 #ifdef NEED_DEBUG_HERE 03123 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03124 #endif 03125 } else { 03126 if (score.canmatch_exten) { 03127 #ifdef NEED_DEBUG_HERE 03128 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03129 #endif 03130 return score.canmatch_exten; 03131 } else { 03132 #ifdef NEED_DEBUG_HERE 03133 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03134 #endif 03135 } 03136 } 03137 return z; 03138 } 03139 #ifdef NEED_DEBUG_HERE 03140 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03141 #endif 03142 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03143 } 03144 03145 if (eroot) { 03146 /* found entry, now look for the right priority */ 03147 if (q->status < STATUS_NO_PRIORITY) 03148 q->status = STATUS_NO_PRIORITY; 03149 e = NULL; 03150 if (action == E_FINDLABEL && label ) { 03151 if (q->status < STATUS_NO_LABEL) 03152 q->status = STATUS_NO_LABEL; 03153 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03154 } else { 03155 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03156 } 03157 if (e) { /* found a valid match */ 03158 q->status = STATUS_SUCCESS; 03159 q->foundcontext = context; 03160 #ifdef NEED_DEBUG_HERE 03161 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03162 #endif 03163 return e; 03164 } 03165 } 03166 } else { /* the old/current default exten pattern match algorithm */ 03167 03168 /* scan the list trying to match extension and CID */ 03169 eroot = NULL; 03170 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03171 int match = extension_match_core(eroot->exten, exten, action); 03172 /* 0 on fail, 1 on match, 2 on earlymatch */ 03173 03174 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03175 continue; /* keep trying */ 03176 if (match == 2 && action == E_MATCHMORE) { 03177 /* We match an extension ending in '!'. 03178 * The decision in this case is final and is NULL (no match). 03179 */ 03180 return NULL; 03181 } 03182 /* found entry, now look for the right priority */ 03183 if (q->status < STATUS_NO_PRIORITY) 03184 q->status = STATUS_NO_PRIORITY; 03185 e = NULL; 03186 if (action == E_FINDLABEL && label ) { 03187 if (q->status < STATUS_NO_LABEL) 03188 q->status = STATUS_NO_LABEL; 03189 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03190 } else { 03191 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03192 } 03193 if (e) { /* found a valid match */ 03194 q->status = STATUS_SUCCESS; 03195 q->foundcontext = context; 03196 return e; 03197 } 03198 } 03199 } 03200 03201 /* Check alternative switches */ 03202 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03203 struct ast_switch *asw = pbx_findswitch(sw->name); 03204 ast_switch_f *aswf = NULL; 03205 char *datap; 03206 03207 if (!asw) { 03208 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03209 continue; 03210 } 03211 03212 /* Substitute variables now */ 03213 if (sw->eval) { 03214 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03215 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03216 continue; 03217 } 03218 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03219 } 03220 03221 /* equivalent of extension_match_core() at the switch level */ 03222 if (action == E_CANMATCH) 03223 aswf = asw->canmatch; 03224 else if (action == E_MATCHMORE) 03225 aswf = asw->matchmore; 03226 else /* action == E_MATCH */ 03227 aswf = asw->exists; 03228 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03229 if (!aswf) 03230 res = 0; 03231 else { 03232 if (chan) 03233 ast_autoservice_start(chan); 03234 res = aswf(chan, context, exten, priority, callerid, datap); 03235 if (chan) 03236 ast_autoservice_stop(chan); 03237 } 03238 if (res) { /* Got a match */ 03239 q->swo = asw; 03240 q->data = datap; 03241 q->foundcontext = context; 03242 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03243 return NULL; 03244 } 03245 } 03246 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03247 /* Now try any includes we have in this context */ 03248 for (i = tmp->includes; i; i = i->next) { 03249 if (include_valid(i)) { 03250 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03251 #ifdef NEED_DEBUG_HERE 03252 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03253 #endif 03254 return e; 03255 } 03256 if (q->swo) 03257 return NULL; 03258 } 03259 } 03260 return NULL; 03261 }
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 1494 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().
01495 { 01496 struct ast_app *tmp; 01497 01498 AST_RWLIST_RDLOCK(&apps); 01499 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01500 if (!strcasecmp(tmp->name, app)) 01501 break; 01502 } 01503 AST_RWLIST_UNLOCK(&apps); 01504 01505 return tmp; 01506 }
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 4016 of file pbx.c.
References ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by ast_readconfig().
04017 { 04018 if (new_live_dangerously && !live_dangerously) { 04019 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n" 04020 "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n"); 04021 } 04022 04023 if (!new_live_dangerously && live_dangerously) { 04024 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n"); 04025 } 04026 live_dangerously = new_live_dangerously; 04027 }
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 3391 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().
03392 { 03393 struct ast_str *str = ast_str_create(16); 03394 const char *cret; 03395 03396 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03397 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03398 *ret = cret ? workspace : NULL; 03399 ast_free(str); 03400 }
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 5946 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05947 { 05948 int oldval = autofallthrough; 05949 autofallthrough = newval; 05950 return oldval; 05951 }
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 5953 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05954 { 05955 int oldval = extenpatternmatchnew; 05956 extenpatternmatchnew = newval; 05957 return oldval; 05958 }
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 5960 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05961 { 05962 if (overrideswitch) { 05963 ast_free(overrideswitch); 05964 } 05965 if (!ast_strlen_zero(newval)) { 05966 overrideswitch = ast_strdup(newval); 05967 } else { 05968 overrideswitch = NULL; 05969 } 05970 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4633 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().
04634 { 04635 size_t used; 04636 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04637 }
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 4437 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().
04438 { 04439 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04440 char *cp4 = NULL; 04441 const char *tmp, *whereweare, *orig_cp2 = cp2; 04442 int length, offset, offset2, isfunction; 04443 char *workspace = NULL; 04444 char *ltmp = NULL, *var = NULL; 04445 char *nextvar, *nextexp, *nextthing; 04446 char *vars, *vare; 04447 int pos, brackets, needsub, len; 04448 04449 *cp2 = 0; /* just in case nothing ends up there */ 04450 whereweare=tmp=cp1; 04451 while (!ast_strlen_zero(whereweare) && count) { 04452 /* Assume we're copying the whole remaining string */ 04453 pos = strlen(whereweare); 04454 nextvar = NULL; 04455 nextexp = NULL; 04456 nextthing = strchr(whereweare, '$'); 04457 if (nextthing) { 04458 switch (nextthing[1]) { 04459 case '{': 04460 nextvar = nextthing; 04461 pos = nextvar - whereweare; 04462 break; 04463 case '[': 04464 nextexp = nextthing; 04465 pos = nextexp - whereweare; 04466 break; 04467 default: 04468 pos = 1; 04469 } 04470 } 04471 04472 if (pos) { 04473 /* Can't copy more than 'count' bytes */ 04474 if (pos > count) 04475 pos = count; 04476 04477 /* Copy that many bytes */ 04478 memcpy(cp2, whereweare, pos); 04479 04480 count -= pos; 04481 cp2 += pos; 04482 whereweare += pos; 04483 *cp2 = 0; 04484 } 04485 04486 if (nextvar) { 04487 /* We have a variable. Find the start and end, and determine 04488 if we are going to have to recursively call ourselves on the 04489 contents */ 04490 vars = vare = nextvar + 2; 04491 brackets = 1; 04492 needsub = 0; 04493 04494 /* Find the end of it */ 04495 while (brackets && *vare) { 04496 if ((vare[0] == '$') && (vare[1] == '{')) { 04497 needsub++; 04498 } else if (vare[0] == '{') { 04499 brackets++; 04500 } else if (vare[0] == '}') { 04501 brackets--; 04502 } else if ((vare[0] == '$') && (vare[1] == '[')) 04503 needsub++; 04504 vare++; 04505 } 04506 if (brackets) 04507 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04508 len = vare - vars - 1; 04509 04510 /* Skip totally over variable string */ 04511 whereweare += (len + 3); 04512 04513 if (!var) 04514 var = ast_alloca(VAR_BUF_SIZE); 04515 04516 /* Store variable name (and truncate) */ 04517 ast_copy_string(var, vars, len + 1); 04518 04519 /* Substitute if necessary */ 04520 if (needsub) { 04521 size_t used; 04522 if (!ltmp) 04523 ltmp = ast_alloca(VAR_BUF_SIZE); 04524 04525 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04526 vars = ltmp; 04527 } else { 04528 vars = var; 04529 } 04530 04531 if (!workspace) 04532 workspace = ast_alloca(VAR_BUF_SIZE); 04533 04534 workspace[0] = '\0'; 04535 04536 parse_variable_name(vars, &offset, &offset2, &isfunction); 04537 if (isfunction) { 04538 /* Evaluate function */ 04539 if (c || !headp) 04540 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04541 else { 04542 struct varshead old; 04543 struct ast_channel *c = ast_dummy_channel_alloc(); 04544 if (c) { 04545 memcpy(&old, &c->varshead, sizeof(old)); 04546 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04547 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04548 /* Don't deallocate the varshead that was passed in */ 04549 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04550 c = ast_channel_unref(c); 04551 } else { 04552 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04553 } 04554 } 04555 ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)"); 04556 } else { 04557 /* Retrieve variable value */ 04558 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04559 } 04560 if (cp4) { 04561 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04562 04563 length = strlen(cp4); 04564 if (length > count) 04565 length = count; 04566 memcpy(cp2, cp4, length); 04567 count -= length; 04568 cp2 += length; 04569 *cp2 = 0; 04570 } 04571 } else if (nextexp) { 04572 /* We have an expression. Find the start and end, and determine 04573 if we are going to have to recursively call ourselves on the 04574 contents */ 04575 vars = vare = nextexp + 2; 04576 brackets = 1; 04577 needsub = 0; 04578 04579 /* Find the end of it */ 04580 while (brackets && *vare) { 04581 if ((vare[0] == '$') && (vare[1] == '[')) { 04582 needsub++; 04583 brackets++; 04584 vare++; 04585 } else if (vare[0] == '[') { 04586 brackets++; 04587 } else if (vare[0] == ']') { 04588 brackets--; 04589 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04590 needsub++; 04591 vare++; 04592 } 04593 vare++; 04594 } 04595 if (brackets) 04596 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04597 len = vare - vars - 1; 04598 04599 /* Skip totally over expression */ 04600 whereweare += (len + 3); 04601 04602 if (!var) 04603 var = ast_alloca(VAR_BUF_SIZE); 04604 04605 /* Store variable name (and truncate) */ 04606 ast_copy_string(var, vars, len + 1); 04607 04608 /* Substitute if necessary */ 04609 if (needsub) { 04610 size_t used; 04611 if (!ltmp) 04612 ltmp = ast_alloca(VAR_BUF_SIZE); 04613 04614 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04615 vars = ltmp; 04616 } else { 04617 vars = var; 04618 } 04619 04620 length = ast_expr(vars, cp2, count, c); 04621 04622 if (length) { 04623 ast_debug(1, "Expression result is '%s'\n", cp2); 04624 count -= length; 04625 cp2 += length; 04626 *cp2 = 0; 04627 } 04628 } 04629 } 04630 *used = cp2 - orig_cp2; 04631 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4639 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04640 { 04641 size_t used; 04642 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04643 }