Core PBX routines and definitions. More...
#include "asterisk/channel.h"#include "asterisk/sched.h"#include "asterisk/devicestate.h"#include "asterisk/chanvars.h"#include "asterisk/hashtab.h"#include "asterisk/stringfields.h"#include "asterisk/xmldoc.h"#include "asterisk/frame_defs.h"
Go to the source code of this file.
Data Structures | |
| struct | ast_custom_function |
| Data structure associated with a custom dialplan function. More... | |
| struct | ast_pbx |
| struct | ast_pbx_args |
| Options for ast_pbx_run(). More... | |
| struct | ast_switch |
| struct | ast_timing |
| struct | pbx_find_info |
Defines | |
| #define | ast_custom_function_register(acf) __ast_custom_function_register(acf, ast_module_info->self) |
| Register a custom function. | |
| #define | ast_custom_function_register_escalating(acf, escalation) __ast_custom_function_register_escalating(acf, escalation, ast_module_info->self) |
| Register a custom function which requires escalated privileges. | |
| #define | AST_MAX_APP 32 |
| #define | AST_PBX_GOTO_FAILED -3 |
| #define | AST_PBX_KEEP 0 |
| #define | AST_PBX_MAX_STACK 128 |
| #define | AST_PBX_REPLACE 1 |
| #define | PRIORITY_HINT -1 |
| #define | STATUS_NO_CONTEXT 1 |
| #define | STATUS_NO_EXTENSION 2 |
| #define | STATUS_NO_LABEL 4 |
| #define | STATUS_NO_PRIORITY 3 |
| #define | STATUS_SUCCESS 5 |
Typedefs | |
| typedef void(* | ast_state_cb_destroy_type )(int id, void *data) |
| Typedef for devicestate and hint callback removal indication callback. | |
| typedef int(* | ast_state_cb_type )(char *context, char *id, enum ast_extension_states state, void *data) |
| Typedef for devicestate and hint callbacks. | |
| typedef int( | ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| All switch functions have the same interface, so define a type for them. | |
Enumerations | |
| enum | ast_custom_function_escalation { AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, AST_CFE_BOTH } |
Description of the ways in which a function may escalate privileges. More... | |
| enum | ast_ext_matchcid_types { AST_EXT_MATCHCID_OFF = 0, AST_EXT_MATCHCID_ON = 1, AST_EXT_MATCHCID_ANY = 2 } |
extension matchcid types More... | |
| enum | ast_extension_states { AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0, AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4 } |
Extension states. More... | |
| enum | ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 } |
The result codes when starting the PBX on a channel with ast_pbx_start. More... | |
| enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22, E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
| int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
| Register a custom function. | |
| int | __ast_custom_function_register_escalating (struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod) |
| Register a custom function which requires escalated privileges. | |
| int | ast_active_calls (void) |
| Retrieve the number of active calls. | |
| int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add and extension to an extension context. | |
| int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add an extension to an extension context, this time with an ast_context *. | |
| int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| Set the channel to next execute the specified dialplan location. | |
| int | ast_async_goto_by_name (const char *chan, const char *context, const char *exten, int priority) |
| Set the channel to next execute the specified dialplan location. | |
| int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_build_timing (struct ast_timing *i, const char *info) |
| Construct a timing bitmap, for use in time-based conditionals. | |
| int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks for a valid matching extension. | |
| int | ast_check_timing (const struct ast_timing *i) |
| Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified. | |
| int | ast_check_timing2 (const struct ast_timing *i, const struct timeval tv) |
| Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified. | |
| char * | ast_complete_applications (const char *line, const char *word, int state) |
| Command completion for the list of installed applications. | |
| int | ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| Add an ignorepat. | |
| int | ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
| Add a switch. | |
| int | ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar) |
| Adds a switch (first param is a ast_context). | |
| void | ast_context_destroy (struct ast_context *con, const char *registrar) |
| Destroy a context (matches the specified context (or ANY context if NULL). | |
| struct ast_context * | ast_context_find (const char *name) |
| Find a context. | |
| struct ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
| Register a new context or find an existing one. | |
| int | ast_context_lockmacro (const char *macrocontext) |
| locks the macrolock in the given given context | |
| int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
| Remove a context include. | |
| int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Removes an include by an ast_context structure. | |
| int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
| Remove a switch. | |
| int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
| This function locks given context, removes switch, unlock context and return. | |
| int | ast_context_unlockmacro (const char *macrocontext) |
| Unlocks the macrolock in the given context. | |
| int | ast_context_verify_includes (struct ast_context *con) |
| Verifies includes in an ast_contect structure. | |
| struct ast_custom_function * | ast_custom_function_find (const char *name) |
| int | ast_custom_function_unregister (struct ast_custom_function *acf) |
| Unregister a custom function. | |
| int | ast_destroy_timing (struct ast_timing *i) |
| Deallocates memory structures associated with a timing bitmap. | |
| enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
| Map devstate to an extension state. | |
| int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Determine whether an extension exists. | |
| int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_extension_close (const char *pattern, const char *data, int needmore) |
| int | ast_extension_cmp (const char *a, const char *b) |
| Determine if one extension should match before another. | |
| int | ast_extension_match (const char *pattern, const char *extension) |
| Determine if a given extension matches a given pattern (in NXX format). | |
| int | ast_extension_patmatch (const char *pattern, const char *data) |
| int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
| Uses hint and devicestate callback to get the state of an extension. | |
| const char * | ast_extension_state2str (int extension_state) |
| Return string representation of the state of an extension. | |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data) |
| Registers a state change callback. | |
| int | ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data) |
| Registers a state change callback with destructor. | |
| int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
| Deletes a registered state change callback by ID. | |
| int | ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
| executes a read operation on a function | |
| int | ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen) |
| executes a read operation on a function | |
| int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
| executes a write operation on a function | |
| int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
| If an extension hint exists, return non-zero. | |
| int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_ignore_pattern (const char *context, const char *pattern) |
| Checks to see if a number should be ignored. | |
| int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
| void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
| Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
| int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
| int | ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
| enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
| Execute the PBX in the current thread. | |
| enum ast_pbx_result | ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args) |
| Execute the PBX in the current thread. | |
| enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
| Create a new thread and start the PBX. | |
| int | ast_processed_calls (void) |
| Retrieve the total number of calls processed through the PBX since last restart. | |
| int | ast_rdlock_context (struct ast_context *con) |
| Read locks a given context. | |
| int | ast_rdlock_contexts (void) |
| Read locks the context list. | |
| int | ast_register_switch (struct ast_switch *sw) |
| Register an alternative dialplan switch. | |
| int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn) |
| Launch a new extension (i.e. new stack). | |
| int | ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten) |
| If an extension hint exists, return non-zero. | |
| int | ast_thread_inhibit_escalations (void) |
| Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect. | |
| int | ast_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts (void) |
| Unlocks contexts. | |
| void | ast_unregister_switch (struct ast_switch *sw) |
| Unregister an alternative switch. | |
| int | ast_wrlock_context (struct ast_context *con) |
| Write locks a given context. | |
| int | ast_wrlock_contexts (void) |
| Write locks the context list. | |
| void | pbx_builtin_clear_globals (void) |
| const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
| Return a pointer to the value of the corresponding channel variable. | |
| void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, without removing any previously set value. | |
| int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *data) |
| int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
| Create a human-readable string, specifying all variables and their corresponding values. | |
| int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
| Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
| int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
| int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *data) |
| Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
| int | pbx_checkcondition (const char *condition) |
| Evaluate a condition. | |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
| Execute an application. | |
| struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
| struct ast_app * | pbx_findapp (const char *app) |
| Look up an application. | |
| void | pbx_live_dangerously (int new_live_dangerously) |
| Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.). | |
| void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
| Retrieve the value of a builtin variable or variable from the channel variable stack. | |
| int | pbx_set_autofallthrough (int newval) |
| int | pbx_set_extenpatternmatchnew (int newval) |
| void | pbx_set_overrideswitch (const char *newval) |
Registrar info functions ... | |
| const char * | ast_get_context_registrar (struct ast_context *c) |
| const char * | ast_get_extension_registrar (struct ast_exten *e) |
| const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
| const char * | ast_get_include_registrar (struct ast_include *i) |
| const char * | ast_get_switch_registrar (struct ast_sw *sw) |
Other Extension stuff | |
| const char * | ast_get_extension_app (struct ast_exten *e) |
| void * | ast_get_extension_app_data (struct ast_exten *e) |
| const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
| const char * | ast_get_extension_label (struct ast_exten *e) |
| int | ast_get_extension_matchcid (struct ast_exten *e) |
| int | ast_get_extension_priority (struct ast_exten *exten) |
Substitution routines, using dynamic string buffers | |
| const char * | ast_str_retrieve_variable (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var) |
| void | ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ) |
| void | ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used) |
| void | ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ) |
Walking functions ... | |
| struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
| struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
| struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| struct ast_context * | ast_walk_contexts (struct ast_context *con) |
| struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
Substitution routines, using static string buffers | |
| void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
| void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used) |
| void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
|
| |
| #define | AST_PBX_ERROR 1 |
| #define | AST_PBX_HANGUP -1 |
| Special return values from applications to the PBX. | |
| #define | AST_PBX_INCOMPLETE 12 |
| #define | AST_PBX_OK 0 |
| int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
| Simply remove extension from context. | |
| int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked) |
| This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
| int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar) |
| int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked) |
| const char * | ast_get_context_name (struct ast_context *con) |
| struct ast_context * | ast_get_extension_context (struct ast_exten *exten) |
| const char * | ast_get_extension_name (struct ast_exten *exten) |
| const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
| const char * | ast_get_include_name (struct ast_include *include) |
| const char * | ast_get_switch_data (struct ast_sw *sw) |
| int | ast_get_switch_eval (struct ast_sw *sw) |
| const char * | ast_get_switch_name (struct ast_sw *sw) |
| int | ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b) |
| hashtable functions for contexts | |
| unsigned int | ast_hashtab_hash_contexts (const void *obj) |
Core PBX routines and definitions.
Definition in file pbx.h.
| #define ast_custom_function_register | ( | acf | ) | __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function.
Definition at line 1164 of file pbx.h.
Referenced by load_module(), and reload().
| #define ast_custom_function_register_escalating | ( | acf, | |||
| escalation | ) | __ast_custom_function_register_escalating(acf, escalation, ast_module_info->self) |
Register a custom function which requires escalated privileges.
Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).
Definition at line 1173 of file pbx.h.
Referenced by load_module().
| #define AST_MAX_APP 32 |
Max length of an application
Definition at line 39 of file pbx.h.
Referenced by handle_show_function(), print_app_docs(), sla_build_station(), and sla_station_destructor().
| #define AST_PBX_ERROR 1 |
| #define AST_PBX_GOTO_FAILED -3 |
Definition at line 41 of file pbx.h.
Referenced by __ast_goto_if_exists().
| #define AST_PBX_HANGUP -1 |
| #define AST_PBX_INCOMPLETE 12 |
Return to PBX matching, allowing more digits for the extension
Definition at line 50 of file pbx.h.
Referenced by __ast_pbx_run(), dial_exec_full(), pbx_builtin_incomplete(), and retrydial_exec().
| #define PRIORITY_HINT -1 |
Special Priority for a hint
Definition at line 53 of file pbx.h.
Referenced by add_extensions(), add_priority(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_space(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), pbx_load_config(), print_ext(), sla_build_station(), and sla_station_destructor().
| typedef void(* ast_state_cb_destroy_type)(int id, void *data) |
| typedef int(* ast_state_cb_type)(char *context, char *id, enum ast_extension_states state, void *data) |
| typedef int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Description of the ways in which a function may escalate privileges.
Definition at line 1154 of file pbx.h.
01154 { 01155 AST_CFE_NONE, 01156 AST_CFE_READ, 01157 AST_CFE_WRITE, 01158 AST_CFE_BOTH, 01159 };
extension matchcid types
Definition at line 76 of file pbx.h.
00076 { 00077 AST_EXT_MATCHCID_OFF = 0, /*!< Match only extensions with matchcid=0 */ 00078 AST_EXT_MATCHCID_ON = 1, /*!< Match only extensions with matchcid=1 AND cidmatch matches */ 00079 AST_EXT_MATCHCID_ANY = 2, /*!< Match both - used only in functions manipulating ast_exten's */ 00080 };
| enum ast_extension_states |
Extension states.
Definition at line 60 of file pbx.h.
00060 { 00061 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */ 00062 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */ 00063 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */ 00064 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */ 00065 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ 00066 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ 00067 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ 00068 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ 00069 };
| enum ast_pbx_result |
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition at line 299 of file pbx.h.
00299 { 00300 AST_PBX_SUCCESS = 0, 00301 AST_PBX_FAILED = -1, 00302 AST_PBX_CALL_LIMIT = -2, 00303 };
| enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows.
| E_MATCHMORE | |
| E_CANMATCH | |
| E_MATCH | |
| E_MATCH_MASK | |
| E_SPAWN | |
| E_FINDLABEL | |
| E_MATCHMORE | |
| E_CANMATCH | |
| E_MATCH | |
| E_MATCH_MASK | |
| E_SPAWN | |
| E_FINDLABEL |
Definition at line 1251 of file pbx.h.
01251 { 01252 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01253 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01254 E_MATCH = 0x02, /* extension is an exact match */ 01255 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01256 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01257 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01258 };
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 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 5884 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05885 { 05886 return countcalls; 05887 }
| 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 8614 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().
08617 { 08618 int ret = -1; 08619 struct ast_context *c; 08620 08621 c = find_context_locked(context); 08622 if (c) { 08623 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08624 application, data, datad, registrar); 08625 ast_unlock_contexts(); 08626 } 08627 08628 return ret; 08629 }
| 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 8975 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().
08979 { 08980 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08981 application, data, datad, registrar, 1); 08982 }
| 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 8654 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().
08655 { 08656 int res = 0; 08657 struct ast_channel *tmpchan; 08658 struct { 08659 char *accountcode; 08660 char *exten; 08661 char *context; 08662 char *linkedid; 08663 char *name; 08664 struct ast_cdr *cdr; 08665 int amaflags; 08666 int state; 08667 format_t readformat; 08668 format_t writeformat; 08669 } tmpvars = { 0, }; 08670 08671 ast_channel_lock(chan); 08672 if (chan->pbx) { /* This channel is currently in the PBX */ 08673 ast_explicit_goto(chan, context, exten, priority + 1); 08674 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08675 ast_channel_unlock(chan); 08676 return res; 08677 } 08678 08679 /* In order to do it when the channel doesn't really exist within 08680 * the PBX, we have to make a new channel, masquerade, and start the PBX 08681 * at the new location */ 08682 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08683 tmpvars.exten = ast_strdupa(chan->exten); 08684 tmpvars.context = ast_strdupa(chan->context); 08685 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08686 tmpvars.name = ast_strdupa(chan->name); 08687 tmpvars.amaflags = chan->amaflags; 08688 tmpvars.state = chan->_state; 08689 tmpvars.writeformat = chan->writeformat; 08690 tmpvars.readformat = chan->readformat; 08691 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08692 08693 ast_channel_unlock(chan); 08694 08695 /* Do not hold any channel locks while calling channel_alloc() since the function 08696 * locks the channel container when linking the new channel in. */ 08697 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08698 ast_cdr_discard(tmpvars.cdr); 08699 return -1; 08700 } 08701 08702 /* copy the cdr info over */ 08703 if (tmpvars.cdr) { 08704 ast_cdr_discard(tmpchan->cdr); 08705 tmpchan->cdr = tmpvars.cdr; 08706 tmpvars.cdr = NULL; 08707 } 08708 08709 /* Make formats okay */ 08710 tmpchan->readformat = tmpvars.readformat; 08711 tmpchan->writeformat = tmpvars.writeformat; 08712 08713 /* Setup proper location. Never hold another channel lock while calling this function. */ 08714 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08715 08716 /* Masquerade into tmp channel */ 08717 if (ast_channel_masquerade(tmpchan, chan)) { 08718 /* Failed to set up the masquerade. It's probably chan_local 08719 * in the middle of optimizing itself out. Sad. :( */ 08720 ast_hangup(tmpchan); 08721 tmpchan = NULL; 08722 res = -1; 08723 } else { 08724 ast_do_masquerade(tmpchan); 08725 /* Start the PBX going on our stolen channel */ 08726 if (ast_pbx_start(tmpchan)) { 08727 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08728 ast_hangup(tmpchan); 08729 res = -1; 08730 } 08731 } 08732 08733 return res; 08734 }
| 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 8736 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08737 { 08738 struct ast_channel *chan; 08739 int res = -1; 08740 08741 if ((chan = ast_channel_get_by_name(channame))) { 08742 res = ast_async_goto(chan, context, exten, priority); 08743 chan = ast_channel_unref(chan); 08744 } 08745 08746 return res; 08747 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 11094 of file pbx.c.
References __ast_goto_if_exists().
11095 { 11096 return __ast_goto_if_exists(chan, context, exten, priority, 1); 11097 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 11159 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
11160 { 11161 return pbx_parseable_goto(chan, goto_string, 1); 11162 }
| 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 8237 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().
08238 { 08239 char *info; 08240 int j, num_fields, last_sep = -1; 08241 08242 /* Check for empty just in case */ 08243 if (ast_strlen_zero(info_in)) { 08244 return 0; 08245 } 08246 08247 /* make a copy just in case we were passed a static string */ 08248 info = ast_strdupa(info_in); 08249 08250 /* count the number of fields in the timespec */ 08251 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08252 if (info[j] == ',') { 08253 last_sep = j; 08254 num_fields++; 08255 } 08256 } 08257 08258 /* save the timezone, if it is specified */ 08259 if (num_fields == 5) { 08260 i->timezone = ast_strdup(info + last_sep + 1); 08261 } else { 08262 i->timezone = NULL; 08263 } 08264 08265 /* Assume everything except time */ 08266 i->monthmask = 0xfff; /* 12 bits */ 08267 i->daymask = 0x7fffffffU; /* 31 bits */ 08268 i->dowmask = 0x7f; /* 7 bits */ 08269 /* on each call, use strsep() to move info to the next argument */ 08270 get_timerange(i, strsep(&info, "|,")); 08271 if (info) 08272 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08273 if (info) 08274 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08275 if (info) 08276 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08277 return 1; 08278 }
| 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 5368 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().
05369 { 05370 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05371 }
| 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 8280 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08281 { 08282 return ast_check_timing2(i, ast_tvnow()); 08283 }
| 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 8285 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().
08286 { 08287 struct ast_tm tm; 08288 08289 ast_localtime(&tv, &tm, i->timezone); 08290 08291 /* If it's not the right month, return */ 08292 if (!(i->monthmask & (1 << tm.tm_mon))) 08293 return 0; 08294 08295 /* If it's not that time of the month.... */ 08296 /* Warning, tm_mday has range 1..31! */ 08297 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08298 return 0; 08299 08300 /* If it's not the right day of the week */ 08301 if (!(i->dowmask & (1 << tm.tm_wday))) 08302 return 0; 08303 08304 /* Sanity check the hour just to be safe */ 08305 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08306 ast_log(LOG_WARNING, "Insane time...\n"); 08307 return 0; 08308 } 08309 08310 /* Now the tough part, we calculate if it fits 08311 in the right time based on min/hour */ 08312 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)))) 08313 return 0; 08314 08315 /* If we got this far, then we're good */ 08316 return 1; 08317 }
| 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 11164 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().
11165 { 11166 struct ast_app *app = NULL; 11167 int which = 0; 11168 char *ret = NULL; 11169 size_t wordlen = strlen(word); 11170 11171 AST_RWLIST_RDLOCK(&apps); 11172 AST_RWLIST_TRAVERSE(&apps, app, list) { 11173 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 11174 ret = ast_strdup(app->name); 11175 break; 11176 } 11177 } 11178 AST_RWLIST_UNLOCK(&apps); 11179 11180 return ret; 11181 }
| 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 8521 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08522 { 08523 int ret = -1; 08524 struct ast_context *c; 08525 08526 c = find_context_locked(context); 08527 if (c) { 08528 ret = ast_context_add_ignorepat2(c, value, registrar); 08529 ast_unlock_contexts(); 08530 } 08531 return ret; 08532 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8534 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().
08535 { 08536 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08537 int length; 08538 char *pattern; 08539 length = sizeof(struct ast_ignorepat); 08540 length += strlen(value) + 1; 08541 if (!(ignorepat = ast_calloc(1, length))) 08542 return -1; 08543 /* The cast to char * is because we need to write the initial value. 08544 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08545 * sees the cast as dereferencing a type-punned pointer and warns about 08546 * it. This is the workaround (we're telling gcc, yes, that's really 08547 * what we wanted to do). 08548 */ 08549 pattern = (char *) ignorepat->pattern; 08550 strcpy(pattern, value); 08551 ignorepat->next = NULL; 08552 ignorepat->registrar = registrar; 08553 ast_wrlock_context(con); 08554 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08555 ignorepatl = ignorepatc; 08556 if (!strcasecmp(ignorepatc->pattern, value)) { 08557 /* Already there */ 08558 ast_unlock_context(con); 08559 ast_free(ignorepat); 08560 errno = EEXIST; 08561 return -1; 08562 } 08563 } 08564 if (ignorepatl) 08565 ignorepatl->next = ignorepat; 08566 else 08567 con->ignorepats = ignorepat; 08568 ast_unlock_context(con); 08569 return 0; 08570 08571 }
| 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 8065 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
08066 { 08067 int ret = -1; 08068 struct ast_context *c; 08069 08070 c = find_context_locked(context); 08071 if (c) { 08072 ret = ast_context_add_include2(c, include, registrar); 08073 ast_unlock_contexts(); 08074 } 08075 return ret; 08076 }
| 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 8334 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().
08336 { 08337 struct ast_include *new_include; 08338 char *c; 08339 struct ast_include *i, *il = NULL; /* include, include_last */ 08340 int length; 08341 char *p; 08342 08343 length = sizeof(struct ast_include); 08344 length += 2 * (strlen(value) + 1); 08345 08346 /* allocate new include structure ... */ 08347 if (!(new_include = ast_calloc(1, length))) 08348 return -1; 08349 /* Fill in this structure. Use 'p' for assignments, as the fields 08350 * in the structure are 'const char *' 08351 */ 08352 p = new_include->stuff; 08353 new_include->name = p; 08354 strcpy(p, value); 08355 p += strlen(value) + 1; 08356 new_include->rname = p; 08357 strcpy(p, value); 08358 /* Strip off timing info, and process if it is there */ 08359 if ( (c = strchr(p, ',')) ) { 08360 *c++ = '\0'; 08361 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08362 } 08363 new_include->next = NULL; 08364 new_include->registrar = registrar; 08365 08366 ast_wrlock_context(con); 08367 08368 /* ... go to last include and check if context is already included too... */ 08369 for (i = con->includes; i; i = i->next) { 08370 if (!strcasecmp(i->name, new_include->name)) { 08371 ast_destroy_timing(&(new_include->timing)); 08372 ast_free(new_include); 08373 ast_unlock_context(con); 08374 errno = EEXIST; 08375 return -1; 08376 } 08377 il = i; 08378 } 08379 08380 /* ... include new context into context list, unlock, return */ 08381 if (il) 08382 il->next = new_include; 08383 else 08384 con->includes = new_include; 08385 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08386 08387 ast_unlock_context(con); 08388 08389 return 0; 08390 }
| 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 8397 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08398 { 08399 int ret = -1; 08400 struct ast_context *c; 08401 08402 c = find_context_locked(context); 08403 if (c) { /* found, add switch to this context */ 08404 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08405 ast_unlock_contexts(); 08406 } 08407 return ret; 08408 }
| 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 8417 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().
08419 { 08420 struct ast_sw *new_sw; 08421 struct ast_sw *i; 08422 int length; 08423 char *p; 08424 08425 length = sizeof(struct ast_sw); 08426 length += strlen(value) + 1; 08427 if (data) 08428 length += strlen(data); 08429 length++; 08430 08431 /* allocate new sw structure ... */ 08432 if (!(new_sw = ast_calloc(1, length))) 08433 return -1; 08434 /* ... fill in this structure ... */ 08435 p = new_sw->stuff; 08436 new_sw->name = p; 08437 strcpy(new_sw->name, value); 08438 p += strlen(value) + 1; 08439 new_sw->data = p; 08440 if (data) { 08441 strcpy(new_sw->data, data); 08442 p += strlen(data) + 1; 08443 } else { 08444 strcpy(new_sw->data, ""); 08445 p++; 08446 } 08447 new_sw->eval = eval; 08448 new_sw->registrar = registrar; 08449 08450 /* ... try to lock this context ... */ 08451 ast_wrlock_context(con); 08452 08453 /* ... go to last sw and check if context is already swd too... */ 08454 AST_LIST_TRAVERSE(&con->alts, i, list) { 08455 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08456 ast_free(new_sw); 08457 ast_unlock_context(con); 08458 errno = EEXIST; 08459 return -1; 08460 } 08461 } 08462 08463 /* ... sw new context into context list, unlock, return */ 08464 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08465 08466 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08467 08468 ast_unlock_context(con); 08469 08470 return 0; 08471 }
| 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 9798 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().
09799 { 09800 ast_wrlock_contexts(); 09801 __ast_context_destroy(contexts, contexts_table, con,registrar); 09802 ast_unlock_contexts(); 09803 }
| 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 2929 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().
02930 { 02931 struct ast_context *tmp; 02932 struct fake_context item; 02933 02934 if (!name) { 02935 return NULL; 02936 } 02937 ast_rdlock_contexts(); 02938 if (contexts_table) { 02939 ast_copy_string(item.name, name, sizeof(item.name)); 02940 tmp = ast_hashtab_lookup(contexts_table, &item); 02941 } else { 02942 tmp = NULL; 02943 while ((tmp = ast_walk_contexts(tmp))) { 02944 if (!strcasecmp(name, tmp->name)) { 02945 break; 02946 } 02947 } 02948 } 02949 ast_unlock_contexts(); 02950 return tmp; 02951 }
| 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 7664 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().
07665 { 07666 struct ast_context *tmp, **local_contexts; 07667 struct fake_context search; 07668 int length = sizeof(struct ast_context) + strlen(name) + 1; 07669 07670 if (!contexts_table) { 07671 /* Protect creation of contexts_table from reentrancy. */ 07672 ast_wrlock_contexts(); 07673 if (!contexts_table) { 07674 contexts_table = ast_hashtab_create(17, 07675 ast_hashtab_compare_contexts, 07676 ast_hashtab_resize_java, 07677 ast_hashtab_newsize_java, 07678 ast_hashtab_hash_contexts, 07679 0); 07680 } 07681 ast_unlock_contexts(); 07682 } 07683 07684 ast_copy_string(search.name, name, sizeof(search.name)); 07685 if (!extcontexts) { 07686 ast_rdlock_contexts(); 07687 local_contexts = &contexts; 07688 tmp = ast_hashtab_lookup(contexts_table, &search); 07689 ast_unlock_contexts(); 07690 if (tmp) { 07691 tmp->refcount++; 07692 return tmp; 07693 } 07694 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07695 local_contexts = extcontexts; 07696 tmp = ast_hashtab_lookup(exttable, &search); 07697 if (tmp) { 07698 tmp->refcount++; 07699 return tmp; 07700 } 07701 } 07702 07703 if ((tmp = ast_calloc(1, length))) { 07704 ast_rwlock_init(&tmp->lock); 07705 ast_mutex_init(&tmp->macrolock); 07706 strcpy(tmp->name, name); 07707 tmp->root = NULL; 07708 tmp->root_table = NULL; 07709 tmp->registrar = ast_strdup(registrar); 07710 tmp->includes = NULL; 07711 tmp->ignorepats = NULL; 07712 tmp->refcount = 1; 07713 } else { 07714 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07715 return NULL; 07716 } 07717 07718 if (!extcontexts) { 07719 ast_wrlock_contexts(); 07720 tmp->next = *local_contexts; 07721 *local_contexts = tmp; 07722 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07723 ast_unlock_contexts(); 07724 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07725 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07726 } else { 07727 tmp->next = *local_contexts; 07728 if (exttable) 07729 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07730 07731 *local_contexts = tmp; 07732 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07733 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07734 } 07735 return tmp; 07736 }
| 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 6259 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06260 { 06261 struct ast_context *c; 06262 int ret = -1; 06263 06264 c = find_context_locked(context); 06265 if (c) { 06266 ast_unlock_contexts(); 06267 06268 /* if we found context, lock macrolock */ 06269 ret = ast_mutex_lock(&c->macrolock); 06270 } 06271 06272 return ret; 06273 }
| 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 6067 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().
06068 { 06069 return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar); 06070 }
| 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 6097 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().
06098 { 06099 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked); 06100 }
| 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 6072 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().
06073 { 06074 int ret = -1; /* default error return */ 06075 struct ast_context *c; 06076 06077 c = find_context_locked(context); 06078 if (c) { /* ... remove extension ... */ 06079 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 06080 matchcallerid, registrar, 0); 06081 ast_unlock_contexts(); 06082 } 06083 06084 return ret; 06085 }
| 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 6102 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().
06103 { 06104 struct ast_exten *exten, *prev_exten = NULL; 06105 struct ast_exten *peer; 06106 struct ast_exten ex, *exten2, *exten3; 06107 char dummy_name[1024]; 06108 struct ast_exten *previous_peer = NULL; 06109 struct ast_exten *next_peer = NULL; 06110 int found = 0; 06111 06112 if (!already_locked) 06113 ast_wrlock_context(con); 06114 06115 #ifdef NEED_DEBUG 06116 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 06117 #endif 06118 #ifdef CONTEXT_DEBUG 06119 check_contexts(__FILE__, __LINE__); 06120 #endif 06121 /* find this particular extension */ 06122 ex.exten = dummy_name; 06123 ex.matchcid = matchcallerid; 06124 ex.cidmatch = callerid; 06125 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 06126 exten = ast_hashtab_lookup(con->root_table, &ex); 06127 if (exten) { 06128 if (priority == 0) { 06129 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06130 if (!exten2) 06131 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); 06132 if (con->pattern_tree) { 06133 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06134 06135 if (x->exten) { /* this test for safety purposes */ 06136 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06137 x->exten = 0; /* get rid of what will become a bad pointer */ 06138 } else { 06139 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 06140 } 06141 } 06142 } else { 06143 ex.priority = priority; 06144 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 06145 if (exten2) { 06146 if (exten2->label) { /* if this exten has a label, remove that, too */ 06147 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 06148 if (!exten3) 06149 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); 06150 } 06151 06152 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 06153 if (!exten3) 06154 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); 06155 if (exten2 == exten && exten2->peer) { 06156 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06157 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 06158 } 06159 if (ast_hashtab_size(exten->peer_table) == 0) { 06160 /* well, if the last priority of an exten is to be removed, 06161 then, the extension is removed, too! */ 06162 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 06163 if (!exten3) 06164 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 06165 if (con->pattern_tree) { 06166 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06167 if (x->exten) { /* this test for safety purposes */ 06168 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06169 x->exten = 0; /* get rid of what will become a bad pointer */ 06170 } 06171 } 06172 } 06173 } else { 06174 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 06175 priority, exten->exten, con->name); 06176 } 06177 } 06178 } else { 06179 /* hmmm? this exten is not in this pattern tree? */ 06180 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 06181 extension, con->name); 06182 } 06183 #ifdef NEED_DEBUG 06184 if (con->pattern_tree) { 06185 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 06186 log_match_char_tree(con->pattern_tree, " "); 06187 } 06188 #endif 06189 06190 /* scan the extension list to find first matching extension-registrar */ 06191 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 06192 if (!strcmp(exten->exten, extension) && 06193 (!registrar || !strcmp(exten->registrar, registrar)) && 06194 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 06195 break; 06196 } 06197 if (!exten) { 06198 /* we can't find right extension */ 06199 if (!already_locked) 06200 ast_unlock_context(con); 06201 return -1; 06202 } 06203 06204 /* scan the priority list to remove extension with exten->priority == priority */ 06205 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 06206 peer && !strcmp(peer->exten, extension) && 06207 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ; 06208 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 06209 06210 if ((priority == 0 || peer->priority == priority) && 06211 (!registrar || !strcmp(peer->registrar, registrar) )) { 06212 found = 1; 06213 06214 /* we are first priority extension? */ 06215 if (!previous_peer) { 06216 /* 06217 * We are first in the priority chain, so must update the extension chain. 06218 * The next node is either the next priority or the next extension 06219 */ 06220 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 06221 if (peer->peer) { 06222 /* move the peer_table and peer_label_table down to the next peer, if 06223 it is there */ 06224 peer->peer->peer_table = peer->peer_table; 06225 peer->peer->peer_label_table = peer->peer_label_table; 06226 peer->peer_table = NULL; 06227 peer->peer_label_table = NULL; 06228 } 06229 if (!prev_exten) { /* change the root... */ 06230 con->root = next_node; 06231 } else { 06232 prev_exten->next = next_node; /* unlink */ 06233 } 06234 if (peer->peer) { /* update the new head of the pri list */ 06235 peer->peer->next = peer->next; 06236 } 06237 } else { /* easy, we are not first priority in extension */ 06238 previous_peer->peer = peer->peer; 06239 } 06240 06241 06242 /* now, free whole priority extension */ 06243 destroy_exten(peer); 06244 } else { 06245 previous_peer = peer; 06246 } 06247 } 06248 if (!already_locked) 06249 ast_unlock_context(con); 06250 return found ? 0 : -1; 06251 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8477 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08478 { 08479 int ret = -1; 08480 struct ast_context *c; 08481 08482 c = find_context_locked(context); 08483 if (c) { 08484 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08485 ast_unlock_contexts(); 08486 } 08487 return ret; 08488 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8490 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().
08491 { 08492 struct ast_ignorepat *ip, *ipl = NULL; 08493 08494 ast_wrlock_context(con); 08495 08496 for (ip = con->ignorepats; ip; ip = ip->next) { 08497 if (!strcmp(ip->pattern, ignorepat) && 08498 (!registrar || (registrar == ip->registrar))) { 08499 if (ipl) { 08500 ipl->next = ip->next; 08501 ast_free(ip); 08502 } else { 08503 con->ignorepats = ip->next; 08504 ast_free(ip); 08505 } 08506 ast_unlock_context(con); 08507 return 0; 08508 } 08509 ipl = ip; 08510 } 08511 08512 ast_unlock_context(con); 08513 errno = EINVAL; 08514 return -1; 08515 }
| 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 5960 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05961 { 05962 int ret = -1; 05963 struct ast_context *c; 05964 05965 c = find_context_locked(context); 05966 if (c) { 05967 /* found, remove include from this context ... */ 05968 ret = ast_context_remove_include2(c, include, registrar); 05969 ast_unlock_contexts(); 05970 } 05971 return ret; 05972 }
| 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 5983 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().
05984 { 05985 struct ast_include *i, *pi = NULL; 05986 int ret = -1; 05987 05988 ast_wrlock_context(con); 05989 05990 /* find our include */ 05991 for (i = con->includes; i; pi = i, i = i->next) { 05992 if (!strcmp(i->name, include) && 05993 (!registrar || !strcmp(i->registrar, registrar))) { 05994 /* remove from list */ 05995 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05996 if (pi) 05997 pi->next = i->next; 05998 else 05999 con->includes = i->next; 06000 /* free include and return */ 06001 ast_destroy_timing(&(i->timing)); 06002 ast_free(i); 06003 ret = 0; 06004 break; 06005 } 06006 } 06007 06008 ast_unlock_context(con); 06009 06010 return ret; 06011 }
| 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 6018 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
06019 { 06020 int ret = -1; /* default error return */ 06021 struct ast_context *c; 06022 06023 c = find_context_locked(context); 06024 if (c) { 06025 /* remove switch from this context ... */ 06026 ret = ast_context_remove_switch2(c, sw, data, registrar); 06027 ast_unlock_contexts(); 06028 } 06029 return ret; 06030 }
| 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 6040 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().
06041 { 06042 struct ast_sw *i; 06043 int ret = -1; 06044 06045 ast_wrlock_context(con); 06046 06047 /* walk switches */ 06048 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 06049 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 06050 (!registrar || !strcmp(i->registrar, registrar))) { 06051 /* found, remove from list */ 06052 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 06053 AST_LIST_REMOVE_CURRENT(list); 06054 ast_free(i); /* free switch and return */ 06055 ret = 0; 06056 break; 06057 } 06058 } 06059 AST_LIST_TRAVERSE_SAFE_END; 06060 06061 ast_unlock_context(con); 06062 06063 return ret; 06064 }
| 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 6280 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06281 { 06282 struct ast_context *c; 06283 int ret = -1; 06284 06285 c = find_context_locked(context); 06286 if (c) { 06287 ast_unlock_contexts(); 06288 06289 /* if we found context, unlock macrolock */ 06290 ret = ast_mutex_unlock(&c->macrolock); 06291 } 06292 06293 return ret; 06294 }
| 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 11049 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().
11050 { 11051 struct ast_include *inc = NULL; 11052 int res = 0; 11053 11054 while ( (inc = ast_walk_context_includes(con, inc)) ) { 11055 if (ast_context_find(inc->rname)) 11056 continue; 11057 11058 res = -1; 11059 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 11060 ast_get_context_name(con), inc->rname); 11061 break; 11062 } 11063 11064 return res; 11065 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3758 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().
03759 { 03760 struct ast_custom_function *acf = NULL; 03761 03762 AST_RWLIST_RDLOCK(&acf_root); 03763 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03764 if (!strcmp(name, acf->name)) 03765 break; 03766 } 03767 AST_RWLIST_UNLOCK(&acf_root); 03768 03769 return acf; 03770 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3772 of file pbx.c.
References ast_custom_escalating_function::acf, 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().
03773 { 03774 struct ast_custom_function *cur; 03775 struct ast_custom_escalating_function *cur_escalation; 03776 03777 if (!acf) { 03778 return -1; 03779 } 03780 03781 AST_RWLIST_WRLOCK(&acf_root); 03782 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03783 #ifdef AST_XML_DOCS 03784 if (cur->docsrc == AST_XML_DOC) { 03785 ast_string_field_free_memory(acf); 03786 } 03787 #endif 03788 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03789 } 03790 AST_RWLIST_UNLOCK(&acf_root); 03791 03792 /* Remove from the escalation list */ 03793 AST_RWLIST_WRLOCK(&escalation_root); 03794 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) { 03795 if (cur_escalation->acf == acf) { 03796 AST_RWLIST_REMOVE_CURRENT(list); 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 8319 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 4801 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().
04802 { 04803 switch (devstate) { 04804 case AST_DEVICE_ONHOLD: 04805 return AST_EXTENSION_ONHOLD; 04806 case AST_DEVICE_BUSY: 04807 return AST_EXTENSION_BUSY; 04808 case AST_DEVICE_UNKNOWN: 04809 return AST_EXTENSION_NOT_INUSE; 04810 case AST_DEVICE_UNAVAILABLE: 04811 case AST_DEVICE_INVALID: 04812 return AST_EXTENSION_UNAVAILABLE; 04813 case AST_DEVICE_RINGINUSE: 04814 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04815 case AST_DEVICE_RINGING: 04816 return AST_EXTENSION_RINGING; 04817 case AST_DEVICE_INUSE: 04818 return AST_EXTENSION_INUSE; 04819 case AST_DEVICE_NOT_INUSE: 04820 return AST_EXTENSION_NOT_INUSE; 04821 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04822 break; 04823 } 04824 04825 return AST_EXTENSION_NOT_INUSE; 04826 }
| 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 5353 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().
05354 { 05355 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05356 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 8631 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(), pbx_parseable_goto(), and return_exec().
08632 { 08633 if (!chan) 08634 return -1; 08635 08636 ast_channel_lock(chan); 08637 08638 if (!ast_strlen_zero(context)) 08639 ast_copy_string(chan->context, context, sizeof(chan->context)); 08640 if (!ast_strlen_zero(exten)) 08641 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08642 if (priority > -1) { 08643 chan->priority = priority; 08644 /* see flag description in channel.h for explanation */ 08645 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08646 chan->priority--; 08647 } 08648 08649 ast_channel_unlock(chan); 08650 08651 return 0; 08652 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 2906 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().
02907 { 02908 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02909 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02910 return extension_match_core(pattern, data, needmore); 02911 }
| 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 2671 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02672 { 02673 int cmp; 02674 02675 cmp = ext_cmp(a, b); 02676 if (cmp < 0) { 02677 return -1; 02678 } 02679 if (cmp > 0) { 02680 return 1; 02681 } 02682 return 0; 02683 }
| 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 2901 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().
02902 { 02903 return extension_match_core(pattern, data, E_MATCH); 02904 }
| 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 4871 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().
04872 { 04873 struct ast_exten *e; 04874 04875 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04876 return -1; /* No hint, return -1 */ 04877 } 04878 04879 if (e->exten[0] == '_') { 04880 /* Create this hint on-the-fly */ 04881 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04882 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04883 e->registrar); 04884 if (!(e = ast_hint_extension(c, context, exten))) { 04885 /* Improbable, but not impossible */ 04886 return -1; 04887 } 04888 } 04889 04890 return ast_extension_state2(e); /* Check all devices in the hint */ 04891 }
| 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 4859 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().
04860 { 04861 int i; 04862 04863 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04864 if (extension_states[i].extension_state == extension_state) 04865 return extension_states[i].text; 04866 } 04867 return "Unknown"; 04868 }
| 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 5092 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
05094 { 05095 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 05096 }
| 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 5005 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().
05007 { 05008 struct ast_hint *hint; 05009 struct ast_state_cb *state_cb; 05010 struct ast_exten *e; 05011 int id; 05012 05013 /* If there's no context and extension: add callback to statecbs list */ 05014 if (!context && !exten) { 05015 /* Prevent multiple adds from adding the same change_cb at the same time. */ 05016 ao2_lock(statecbs); 05017 05018 /* Remove any existing change_cb. */ 05019 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 05020 05021 /* Now insert the change_cb */ 05022 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05023 ao2_unlock(statecbs); 05024 return -1; 05025 } 05026 state_cb->id = 0; 05027 state_cb->change_cb = change_cb; 05028 state_cb->destroy_cb = destroy_cb; 05029 state_cb->data = data; 05030 ao2_link(statecbs, state_cb); 05031 05032 ao2_ref(state_cb, -1); 05033 ao2_unlock(statecbs); 05034 return 0; 05035 } 05036 05037 if (!context || !exten) 05038 return -1; 05039 05040 /* This callback type is for only one hint, so get the hint */ 05041 e = ast_hint_extension(NULL, context, exten); 05042 if (!e) { 05043 return -1; 05044 } 05045 05046 /* If this is a pattern, dynamically create a new extension for this 05047 * particular match. Note that this will only happen once for each 05048 * individual extension, because the pattern will no longer match first. 05049 */ 05050 if (e->exten[0] == '_') { 05051 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 05052 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 05053 e->registrar); 05054 e = ast_hint_extension(NULL, context, exten); 05055 if (!e || e->exten[0] == '_') { 05056 return -1; 05057 } 05058 } 05059 05060 /* Find the hint in the hints container */ 05061 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05062 hint = ao2_find(hints, e, 0); 05063 if (!hint) { 05064 ao2_unlock(hints); 05065 return -1; 05066 } 05067 05068 /* Now insert the callback in the callback list */ 05069 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05070 ao2_ref(hint, -1); 05071 ao2_unlock(hints); 05072 return -1; 05073 } 05074 do { 05075 id = stateid++; /* Unique ID for this callback */ 05076 /* Do not allow id to ever be -1 or 0. */ 05077 } while (id == -1 || id == 0); 05078 state_cb->id = id; 05079 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 05080 state_cb->destroy_cb = destroy_cb; 05081 state_cb->data = data; /* Data for the callback */ 05082 ao2_link(hint->callbacks, state_cb); 05083 05084 ao2_ref(state_cb, -1); 05085 ao2_ref(hint, -1); 05086 ao2_unlock(hints); 05087 05088 return id; 05089 }
| 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 5114 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().
05115 { 05116 struct ast_state_cb *p_cur; 05117 int ret = -1; 05118 05119 if (!id) { /* id == 0 is a callback without extension */ 05120 if (!change_cb) { 05121 return ret; 05122 } 05123 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 05124 if (p_cur) { 05125 ret = 0; 05126 ao2_ref(p_cur, -1); 05127 } 05128 } else { /* callback with extension, find the callback based on ID */ 05129 struct ast_hint *hint; 05130 05131 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05132 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 05133 if (hint) { 05134 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 05135 if (p_cur) { 05136 ret = 0; 05137 ao2_ref(p_cur, -1); 05138 } 05139 ao2_ref(hint, -1); 05140 } 05141 ao2_unlock(hints); 05142 } 05143 05144 return ret; 05145 }
| 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 5358 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().
05359 { 05360 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05361 }
| 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 5363 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05364 { 05365 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05366 }
| 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 10901 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().
10902 { 10903 return con ? con->name : NULL; 10904 }
| const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10939 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10940 { 10941 return c ? c->registrar : NULL; 10942 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10969 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().
10970 { 10971 return e ? e->app : NULL; 10972 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10974 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().
10975 { 10976 return e ? e->data : NULL; 10977 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10964 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10965 { 10966 return e ? e->cidmatch : NULL; 10967 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10906 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().
10907 { 10908 return exten ? exten->parent : NULL; 10909 }
| const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 10916 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 10959 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10960 { 10961 return e ? e->matchcid : 0; 10962 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10911 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().
10912 { 10913 return exten ? exten->exten : NULL; 10914 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10931 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().
10932 { 10933 return exten ? exten->priority : -1; 10934 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10944 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10945 { 10946 return e ? e->registrar : NULL; 10947 }
| 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 5315 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().
05316 { 05317 struct ast_exten *e = ast_hint_extension(c, context, exten); 05318 05319 if (e) { 05320 if (hint) 05321 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05322 if (name) { 05323 const char *tmp = ast_get_extension_app_data(e); 05324 if (tmp) 05325 ast_copy_string(name, tmp, namesize); 05326 } 05327 return -1; 05328 } 05329 return 0; 05330 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10926 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().
10927 { 10928 return ip ? ip->pattern : NULL; 10929 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10954 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().
10955 { 10956 return ip ? ip->registrar : NULL; 10957 }
| const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 10921 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 10949 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().
10950 { 10951 return i ? i->registrar : NULL; 10952 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10984 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().
10985 { 10986 return sw ? sw->data : NULL; 10987 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10989 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10990 { 10991 return sw->eval; 10992 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10979 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().
10980 { 10981 return sw ? sw->name : NULL; 10982 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10994 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().
10995 { 10996 return sw ? sw->registrar : NULL; 10997 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 11089 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().
11090 { 11091 return __ast_goto_if_exists(chan, context, exten, priority, 0); 11092 }
| 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 8573 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().
08574 { 08575 struct ast_context *con = ast_context_find(context); 08576 08577 if (con) { 08578 struct ast_ignorepat *pat; 08579 08580 for (pat = con->ignorepats; pat; pat = pat->next) { 08581 if (ast_extension_match(pat->pattern, pattern)) 08582 return 1; 08583 } 08584 } 08585 08586 return 0; 08587 }
| 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 5373 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().
05374 { 05375 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05376 }
| 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 7870 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().
07871 { 07872 double ft; 07873 struct ast_context *tmp; 07874 struct ast_context *oldcontextslist; 07875 struct ast_hashtab *oldtable; 07876 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07877 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07878 struct store_hint *saved_hint; 07879 struct ast_hint *hint; 07880 struct ast_exten *exten; 07881 int length; 07882 struct ast_state_cb *thiscb; 07883 struct ast_hashtab_iter *iter; 07884 struct ao2_iterator i; 07885 struct timeval begintime; 07886 struct timeval writelocktime; 07887 struct timeval endlocktime; 07888 struct timeval enddeltime; 07889 07890 /* 07891 * It is very important that this function hold the hints 07892 * container lock _and_ the conlock during its operation; not 07893 * only do we need to ensure that the list of contexts and 07894 * extensions does not change, but also that no hint callbacks 07895 * (watchers) are added or removed during the merge/delete 07896 * process 07897 * 07898 * In addition, the locks _must_ be taken in this order, because 07899 * there are already other code paths that use this order 07900 */ 07901 07902 begintime = ast_tvnow(); 07903 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07904 ast_wrlock_contexts(); 07905 iter = ast_hashtab_start_traversal(contexts_table); 07906 while ((tmp = ast_hashtab_next(iter))) { 07907 context_merge(extcontexts, exttable, tmp, registrar); 07908 } 07909 ast_hashtab_end_traversal(iter); 07910 07911 ao2_lock(hints); 07912 writelocktime = ast_tvnow(); 07913 07914 /* preserve all watchers for hints */ 07915 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07916 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07917 if (ao2_container_count(hint->callbacks)) { 07918 ao2_lock(hint); 07919 if (!hint->exten) { 07920 /* The extension has already been destroyed. (Should never happen here) */ 07921 ao2_unlock(hint); 07922 continue; 07923 } 07924 07925 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07926 + sizeof(*saved_hint); 07927 if (!(saved_hint = ast_calloc(1, length))) { 07928 ao2_unlock(hint); 07929 continue; 07930 } 07931 07932 /* This removes all the callbacks from the hint into saved_hint. */ 07933 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07934 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07935 /* 07936 * We intentionally do not unref thiscb to account for the 07937 * non-ao2 reference in saved_hint->callbacks 07938 */ 07939 } 07940 07941 saved_hint->laststate = hint->laststate; 07942 saved_hint->context = saved_hint->data; 07943 strcpy(saved_hint->data, hint->exten->parent->name); 07944 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07945 strcpy(saved_hint->exten, hint->exten->exten); 07946 ao2_unlock(hint); 07947 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07948 } 07949 } 07950 ao2_iterator_destroy(&i); 07951 07952 /* save the old table and list */ 07953 oldtable = contexts_table; 07954 oldcontextslist = contexts; 07955 07956 /* move in the new table and list */ 07957 contexts_table = exttable; 07958 contexts = *extcontexts; 07959 07960 /* 07961 * Restore the watchers for hints that can be found; notify 07962 * those that cannot be restored. 07963 */ 07964 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07965 struct pbx_find_info q = { .stacklen = 0 }; 07966 07967 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07968 PRIORITY_HINT, NULL, "", E_MATCH); 07969 /* 07970 * If this is a pattern, dynamically create a new extension for this 07971 * particular match. Note that this will only happen once for each 07972 * individual extension, because the pattern will no longer match first. 07973 */ 07974 if (exten && exten->exten[0] == '_') { 07975 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07976 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07977 exten->registrar); 07978 /* rwlocks are not recursive locks */ 07979 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07980 saved_hint->exten); 07981 } 07982 07983 /* Find the hint in the hints container */ 07984 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07985 if (!hint) { 07986 /* 07987 * Notify watchers of this removed hint later when we aren't 07988 * encumberd by so many locks. 07989 */ 07990 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07991 } else { 07992 ao2_lock(hint); 07993 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07994 ao2_link(hint->callbacks, thiscb); 07995 /* Ref that we added when putting into saved_hint->callbacks */ 07996 ao2_ref(thiscb, -1); 07997 } 07998 hint->laststate = saved_hint->laststate; 07999 ao2_unlock(hint); 08000 ao2_ref(hint, -1); 08001 ast_free(saved_hint); 08002 } 08003 } 08004 08005 ao2_unlock(hints); 08006 ast_unlock_contexts(); 08007 08008 /* 08009 * Notify watchers of all removed hints with the same lock 08010 * environment as handle_statechange(). 08011 */ 08012 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 08013 /* this hint has been removed, notify the watchers */ 08014 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08015 thiscb->change_cb(saved_hint->context, saved_hint->exten, 08016 AST_EXTENSION_REMOVED, thiscb->data); 08017 /* Ref that we added when putting into saved_hint->callbacks */ 08018 ao2_ref(thiscb, -1); 08019 } 08020 ast_free(saved_hint); 08021 } 08022 08023 ast_mutex_unlock(&context_merge_lock); 08024 endlocktime = ast_tvnow(); 08025 08026 /* 08027 * The old list and hashtab no longer are relevant, delete them 08028 * while the rest of asterisk is now freely using the new stuff 08029 * instead. 08030 */ 08031 08032 ast_hashtab_destroy(oldtable, NULL); 08033 08034 for (tmp = oldcontextslist; tmp; ) { 08035 struct ast_context *next; /* next starting point */ 08036 08037 next = tmp->next; 08038 __ast_internal_context_destroy(tmp); 08039 tmp = next; 08040 } 08041 enddeltime = ast_tvnow(); 08042 08043 ft = ast_tvdiff_us(writelocktime, begintime); 08044 ft /= 1000000.0; 08045 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 08046 08047 ft = ast_tvdiff_us(endlocktime, writelocktime); 08048 ft /= 1000000.0; 08049 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 08050 08051 ft = ast_tvdiff_us(enddeltime, endlocktime); 08052 ft /= 1000000.0; 08053 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 08054 08055 ft = ast_tvdiff_us(enddeltime, begintime); 08056 ft /= 1000000.0; 08057 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 08058 }
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 11154 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().
11155 { 11156 return pbx_parseable_goto(chan, goto_string, 0); 11157 }
| 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 9467 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().
09468 { 09469 struct ast_channel *chan; 09470 struct app_tmp *tmp; 09471 int res = -1, cdr_res = -1; 09472 struct outgoing_helper oh; 09473 09474 memset(&oh, 0, sizeof(oh)); 09475 oh.vars = vars; 09476 oh.account = account; 09477 09478 if (locked_channel) 09479 *locked_channel = NULL; 09480 if (ast_strlen_zero(app)) { 09481 res = -1; 09482 goto outgoing_app_cleanup; 09483 } 09484 if (synchronous) { 09485 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09486 if (chan) { 09487 ast_set_variables(chan, vars); 09488 if (account) 09489 ast_cdr_setaccount(chan, account); 09490 if (chan->_state == AST_STATE_UP) { 09491 res = 0; 09492 ast_verb(4, "Channel %s was answered.\n", chan->name); 09493 tmp = ast_calloc(1, sizeof(*tmp)); 09494 if (!tmp || ast_string_field_init(tmp, 252)) { 09495 if (tmp) { 09496 ast_free(tmp); 09497 } 09498 res = -1; 09499 } else { 09500 ast_string_field_set(tmp, app, app); 09501 ast_string_field_set(tmp, data, appdata); 09502 tmp->chan = chan; 09503 if (synchronous > 1) { 09504 if (locked_channel) 09505 ast_channel_unlock(chan); 09506 ast_pbx_run_app(tmp); 09507 } else { 09508 if (locked_channel) 09509 ast_channel_lock(chan); 09510 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09511 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09512 ast_string_field_free_memory(tmp); 09513 ast_free(tmp); 09514 if (locked_channel) 09515 ast_channel_unlock(chan); 09516 ast_hangup(chan); 09517 res = -1; 09518 } else { 09519 if (locked_channel) 09520 *locked_channel = chan; 09521 } 09522 } 09523 } 09524 } else { 09525 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09526 if (chan->cdr) { /* update the cdr */ 09527 /* here we update the status of the call, which sould be busy. 09528 * if that fails then we set the status to failed */ 09529 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09530 ast_cdr_failed(chan->cdr); 09531 } 09532 ast_hangup(chan); 09533 } 09534 } 09535 09536 if (res < 0) { /* the call failed for some reason */ 09537 if (*reason == 0) { /* if the call failed (not busy or no answer) 09538 * update the cdr with the failed message */ 09539 cdr_res = ast_pbx_outgoing_cdr_failed(); 09540 if (cdr_res != 0) { 09541 res = cdr_res; 09542 goto outgoing_app_cleanup; 09543 } 09544 } 09545 } 09546 09547 } else { 09548 struct async_stat *as; 09549 if (!(as = ast_calloc(1, sizeof(*as)))) { 09550 res = -1; 09551 goto outgoing_app_cleanup; 09552 } 09553 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09554 if (!chan) { 09555 ast_free(as); 09556 res = -1; 09557 goto outgoing_app_cleanup; 09558 } 09559 as->chan = chan; 09560 ast_copy_string(as->app, app, sizeof(as->app)); 09561 if (appdata) 09562 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09563 as->timeout = timeout; 09564 ast_set_variables(chan, vars); 09565 if (account) 09566 ast_cdr_setaccount(chan, account); 09567 /* Start a new thread, and get something handling this channel. */ 09568 if (locked_channel) 09569 ast_channel_lock(chan); 09570 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09571 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09572 ast_free(as); 09573 if (locked_channel) 09574 ast_channel_unlock(chan); 09575 ast_hangup(chan); 09576 res = -1; 09577 goto outgoing_app_cleanup; 09578 } else { 09579 if (locked_channel) 09580 *locked_channel = chan; 09581 } 09582 res = 0; 09583 } 09584 outgoing_app_cleanup: 09585 ast_variables_destroy(vars); 09586 return res; 09587 }
| 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 9298 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().
09299 { 09300 struct ast_channel *chan; 09301 struct async_stat *as; 09302 int res = -1, cdr_res = -1; 09303 struct outgoing_helper oh; 09304 09305 if (synchronous) { 09306 oh.context = context; 09307 oh.exten = exten; 09308 oh.priority = priority; 09309 oh.cid_num = cid_num; 09310 oh.cid_name = cid_name; 09311 oh.account = account; 09312 oh.vars = vars; 09313 oh.parent_channel = NULL; 09314 09315 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09316 if (channel) { 09317 *channel = chan; 09318 if (chan) 09319 ast_channel_lock(chan); 09320 } 09321 if (chan) { 09322 if (chan->_state == AST_STATE_UP) { 09323 res = 0; 09324 ast_verb(4, "Channel %s was answered.\n", chan->name); 09325 09326 if (synchronous > 1) { 09327 if (channel) 09328 ast_channel_unlock(chan); 09329 if (ast_pbx_run(chan)) { 09330 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09331 if (channel) 09332 *channel = NULL; 09333 ast_hangup(chan); 09334 chan = NULL; 09335 res = -1; 09336 } 09337 } else { 09338 if (ast_pbx_start(chan)) { 09339 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09340 if (channel) { 09341 *channel = NULL; 09342 ast_channel_unlock(chan); 09343 } 09344 ast_hangup(chan); 09345 res = -1; 09346 } 09347 chan = NULL; 09348 } 09349 } else { 09350 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09351 09352 if (chan->cdr) { /* update the cdr */ 09353 /* here we update the status of the call, which sould be busy. 09354 * if that fails then we set the status to failed */ 09355 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09356 ast_cdr_failed(chan->cdr); 09357 } 09358 09359 if (channel) { 09360 *channel = NULL; 09361 ast_channel_unlock(chan); 09362 } 09363 ast_hangup(chan); 09364 chan = NULL; 09365 } 09366 } 09367 09368 if (res < 0) { /* the call failed for some reason */ 09369 if (*reason == 0) { /* if the call failed (not busy or no answer) 09370 * update the cdr with the failed message */ 09371 cdr_res = ast_pbx_outgoing_cdr_failed(); 09372 if (cdr_res != 0) { 09373 res = cdr_res; 09374 goto outgoing_exten_cleanup; 09375 } 09376 } 09377 09378 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09379 /* check if "failed" exists */ 09380 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09381 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09382 if (chan) { 09383 char failed_reason[4] = ""; 09384 if (!ast_strlen_zero(context)) 09385 ast_copy_string(chan->context, context, sizeof(chan->context)); 09386 set_ext_pri(chan, "failed", 1); 09387 ast_set_variables(chan, vars); 09388 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09389 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09390 if (account) 09391 ast_cdr_setaccount(chan, account); 09392 if (ast_pbx_run(chan)) { 09393 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09394 ast_hangup(chan); 09395 } 09396 chan = NULL; 09397 } 09398 } 09399 } 09400 } else { 09401 if (!(as = ast_calloc(1, sizeof(*as)))) { 09402 res = -1; 09403 goto outgoing_exten_cleanup; 09404 } 09405 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09406 if (channel) { 09407 *channel = chan; 09408 if (chan) 09409 ast_channel_lock(chan); 09410 } 09411 if (!chan) { 09412 ast_free(as); 09413 res = -1; 09414 goto outgoing_exten_cleanup; 09415 } 09416 as->chan = chan; 09417 ast_copy_string(as->context, context, sizeof(as->context)); 09418 set_ext_pri(as->chan, exten, priority); 09419 as->timeout = timeout; 09420 ast_set_variables(chan, vars); 09421 if (account) 09422 ast_cdr_setaccount(chan, account); 09423 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09424 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09425 ast_free(as); 09426 if (channel) { 09427 *channel = NULL; 09428 ast_channel_unlock(chan); 09429 } 09430 ast_hangup(chan); 09431 res = -1; 09432 goto outgoing_exten_cleanup; 09433 } 09434 res = 0; 09435 } 09436 outgoing_exten_cleanup: 09437 ast_variables_destroy(vars); 09438 return res; 09439 }
| 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 5879 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().
05880 { 05881 return ast_pbx_run_args(c, NULL); 05882 }
| 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 5859 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().
05860 { 05861 enum ast_pbx_result res = AST_PBX_SUCCESS; 05862 05863 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05864 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05865 return AST_PBX_FAILED; 05866 } 05867 05868 if (increase_call_count(c)) { 05869 return AST_PBX_CALL_LIMIT; 05870 } 05871 05872 res = __ast_pbx_run(c, args); 05873 05874 decrease_call_count(); 05875 05876 return res; 05877 }
| 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 5832 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().
05833 { 05834 pthread_t t; 05835 05836 if (!c) { 05837 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05838 return AST_PBX_FAILED; 05839 } 05840 05841 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05842 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05843 return AST_PBX_FAILED; 05844 } 05845 05846 if (increase_call_count(c)) 05847 return AST_PBX_CALL_LIMIT; 05848 05849 /* Start a new thread, and get something handling this channel. */ 05850 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05851 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05852 decrease_call_count(); 05853 return AST_PBX_FAILED; 05854 } 05855 05856 return AST_PBX_SUCCESS; 05857 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5889 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05890 { 05891 return totalcalls; 05892 }
| 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 10888 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().
10889 { 10890 return ast_rwlock_rdlock(&con->lock); 10891 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 10870 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().
10871 { 10872 return ast_mutex_lock(&conlock); 10873 }
| 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 6392 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().
06393 { 06394 struct ast_switch *tmp; 06395 06396 AST_RWLIST_WRLOCK(&switches); 06397 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06398 if (!strcasecmp(tmp->name, sw->name)) { 06399 AST_RWLIST_UNLOCK(&switches); 06400 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06401 return -1; 06402 } 06403 } 06404 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06405 AST_RWLIST_UNLOCK(&switches); 06406 06407 return 0; 06408 }
| 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 5378 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), and loopback_exec().
05379 { 05380 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05381 }
| 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 5333 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().
05334 { 05335 struct ast_exten *e = ast_hint_extension(c, context, exten); 05336 05337 if (!e) { 05338 return 0; 05339 } 05340 05341 if (hint) { 05342 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05343 } 05344 if (name) { 05345 const char *tmp = ast_get_extension_app_data(e); 05346 if (tmp) { 05347 ast_str_set(name, namesize, "%s", tmp); 05348 } 05349 } 05350 return -1; 05351 }
| 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 3403 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().
03404 { 03405 const char not_found = '\0'; 03406 char *tmpvar; 03407 const char *ret; 03408 const char *s; /* the result */ 03409 int offset, length; 03410 int i, need_substring; 03411 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03412 char workspace[20]; 03413 03414 if (c) { 03415 ast_channel_lock(c); 03416 places[0] = &c->varshead; 03417 } 03418 /* 03419 * Make a copy of var because parse_variable_name() modifies the string. 03420 * Then if called directly, we might need to run substring() on the result; 03421 * remember this for later in 'need_substring', 'offset' and 'length' 03422 */ 03423 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03424 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03425 03426 /* 03427 * Look first into predefined variables, then into variable lists. 03428 * Variable 's' points to the result, according to the following rules: 03429 * s == ¬_found (set at the beginning) means that we did not find a 03430 * matching variable and need to look into more places. 03431 * If s != ¬_found, s is a valid result string as follows: 03432 * s = NULL if the variable does not have a value; 03433 * you typically do this when looking for an unset predefined variable. 03434 * s = workspace if the result has been assembled there; 03435 * typically done when the result is built e.g. with an snprintf(), 03436 * so we don't need to do an additional copy. 03437 * s != workspace in case we have a string, that needs to be copied 03438 * (the ast_copy_string is done once for all at the end). 03439 * Typically done when the result is already available in some string. 03440 */ 03441 s = ¬_found; /* default value */ 03442 if (c) { /* This group requires a valid channel */ 03443 /* Names with common parts are looked up a piece at a time using strncmp. */ 03444 if (!strncmp(var, "CALL", 4)) { 03445 if (!strncmp(var + 4, "ING", 3)) { 03446 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03447 ast_str_set(str, maxlen, "%d", 03448 ast_party_id_presentation(&c->caller.id)); 03449 s = ast_str_buffer(*str); 03450 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03451 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03452 s = ast_str_buffer(*str); 03453 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03454 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03455 s = ast_str_buffer(*str); 03456 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03457 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03458 s = ast_str_buffer(*str); 03459 } 03460 } 03461 } else if (!strcmp(var, "HINT")) { 03462 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03463 } else if (!strcmp(var, "HINTNAME")) { 03464 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03465 } else if (!strcmp(var, "EXTEN")) { 03466 s = c->exten; 03467 } else if (!strcmp(var, "CONTEXT")) { 03468 s = c->context; 03469 } else if (!strcmp(var, "PRIORITY")) { 03470 ast_str_set(str, maxlen, "%d", c->priority); 03471 s = ast_str_buffer(*str); 03472 } else if (!strcmp(var, "CHANNEL")) { 03473 s = c->name; 03474 } else if (!strcmp(var, "UNIQUEID")) { 03475 s = c->uniqueid; 03476 } else if (!strcmp(var, "HANGUPCAUSE")) { 03477 ast_str_set(str, maxlen, "%d", c->hangupcause); 03478 s = ast_str_buffer(*str); 03479 } 03480 } 03481 if (s == ¬_found) { /* look for more */ 03482 if (!strcmp(var, "EPOCH")) { 03483 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03484 s = ast_str_buffer(*str); 03485 } else if (!strcmp(var, "SYSTEMNAME")) { 03486 s = ast_config_AST_SYSTEM_NAME; 03487 } else if (!strcmp(var, "ENTITYID")) { 03488 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03489 s = workspace; 03490 } 03491 } 03492 /* if not found, look into chanvars or global vars */ 03493 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03494 struct ast_var_t *variables; 03495 if (!places[i]) 03496 continue; 03497 if (places[i] == &globals) 03498 ast_rwlock_rdlock(&globalslock); 03499 AST_LIST_TRAVERSE(places[i], variables, entries) { 03500 if (!strcasecmp(ast_var_name(variables), var)) { 03501 s = ast_var_value(variables); 03502 break; 03503 } 03504 } 03505 if (places[i] == &globals) 03506 ast_rwlock_unlock(&globalslock); 03507 } 03508 if (s == ¬_found || s == NULL) { 03509 ast_debug(5, "Result of '%s' is NULL\n", var); 03510 ret = NULL; 03511 } else { 03512 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03513 if (s != ast_str_buffer(*str)) { 03514 ast_str_set(str, maxlen, "%s", s); 03515 } 03516 ret = ast_str_buffer(*str); 03517 if (need_substring) { 03518 ret = ast_str_substring(*str, offset, length); 03519 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03520 } 03521 } 03522 03523 if (c) { 03524 ast_channel_unlock(c); 03525 } 03526 return ret; 03527 }
| 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 10893 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().
10894 { 10895 return ast_rwlock_unlock(&con->lock); 10896 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 10875 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().
10876 { 10877 return ast_mutex_unlock(&conlock); 10878 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6410 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06411 { 06412 AST_RWLIST_WRLOCK(&switches); 06413 AST_RWLIST_REMOVE(&switches, sw, list); 06414 AST_RWLIST_UNLOCK(&switches); 06415 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 11007 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 11040 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().
11042 { 11043 if (!ip) 11044 return con ? con->ignorepats : NULL; 11045 else 11046 return ip->next; 11047 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 11031 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 11016 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().
11018 { 11019 if (!sw) 11020 return con ? AST_LIST_FIRST(&con->alts) : NULL; 11021 else 11022 return AST_LIST_NEXT(sw, list); 11023 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 11002 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 11025 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().
11027 { 11028 return priority ? priority->peer : exten; 11029 }
| 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 10883 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().
10884 { 10885 return ast_rwlock_wrlock(&con->lock); 10886 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 10865 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().
10866 { 10867 return ast_mutex_lock(&conlock); 10868 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10632 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().
10633 { 10634 struct ast_var_t *vardata; 10635 10636 ast_rwlock_wrlock(&globalslock); 10637 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10638 ast_var_delete(vardata); 10639 ast_rwlock_unlock(&globalslock); 10640 }
| 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 10398 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(), 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().
10399 { 10400 struct ast_var_t *variables; 10401 const char *ret = NULL; 10402 int i; 10403 struct varshead *places[2] = { NULL, &globals }; 10404 10405 if (!name) 10406 return NULL; 10407 10408 if (chan) { 10409 ast_channel_lock(chan); 10410 places[0] = &chan->varshead; 10411 } 10412 10413 for (i = 0; i < 2; i++) { 10414 if (!places[i]) 10415 continue; 10416 if (places[i] == &globals) 10417 ast_rwlock_rdlock(&globalslock); 10418 AST_LIST_TRAVERSE(places[i], variables, entries) { 10419 if (!strcmp(name, ast_var_name(variables))) { 10420 ret = ast_var_value(variables); 10421 break; 10422 } 10423 } 10424 if (places[i] == &globals) 10425 ast_rwlock_unlock(&globalslock); 10426 if (ret) 10427 break; 10428 } 10429 10430 if (chan) 10431 ast_channel_unlock(chan); 10432 10433 return ret; 10434 }
| 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 10436 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().
10437 { 10438 struct ast_var_t *newvariable; 10439 struct varshead *headp; 10440 10441 if (name[strlen(name)-1] == ')') { 10442 char *function = ast_strdupa(name); 10443 10444 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10445 ast_func_write(chan, function, value); 10446 return; 10447 } 10448 10449 if (chan) { 10450 ast_channel_lock(chan); 10451 headp = &chan->varshead; 10452 } else { 10453 ast_rwlock_wrlock(&globalslock); 10454 headp = &globals; 10455 } 10456 10457 if (value && (newvariable = ast_var_assign(name, value))) { 10458 if (headp == &globals) 10459 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10460 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10461 } 10462 10463 if (chan) 10464 ast_channel_unlock(chan); 10465 else 10466 ast_rwlock_unlock(&globalslock); 10467 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Definition at line 3578 of file pbx.c.
References raise_exception().
03579 { 03580 /* Priority will become 1, next time through the AUTOLOOP */ 03581 return raise_exception(chan, reason, 0); 03582 }
| 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 10367 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().
10368 { 10369 struct ast_var_t *variables; 10370 const char *var, *val; 10371 int total = 0; 10372 10373 if (!chan) 10374 return 0; 10375 10376 ast_str_reset(*buf); 10377 10378 ast_channel_lock(chan); 10379 10380 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10381 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10382 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10383 ) { 10384 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10385 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10386 break; 10387 } else 10388 total++; 10389 } else 10390 break; 10391 } 10392 10393 ast_channel_unlock(chan); 10394 10395 return total; 10396 }
| 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 10526 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().
10527 { 10528 char *name, *value, *mydata; 10529 10530 if (ast_compat_app_set) { 10531 return pbx_builtin_setvar_multiple(chan, data); 10532 } 10533 10534 if (ast_strlen_zero(data)) { 10535 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10536 return 0; 10537 } 10538 10539 mydata = ast_strdupa(data); 10540 name = strsep(&mydata, "="); 10541 value = mydata; 10542 if (!value) { 10543 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10544 return 0; 10545 } 10546 10547 if (strchr(name, ' ')) { 10548 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10549 } 10550 10551 pbx_builtin_setvar_helper(chan, name, value); 10552 10553 return 0; 10554 }
| 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 10469 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), 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(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), 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().
10470 { 10471 struct ast_var_t *newvariable; 10472 struct varshead *headp; 10473 const char *nametail = name; 10474 10475 if (name[strlen(name) - 1] == ')') { 10476 char *function = ast_strdupa(name); 10477 10478 return ast_func_write(chan, function, value); 10479 } 10480 10481 if (chan) { 10482 ast_channel_lock(chan); 10483 headp = &chan->varshead; 10484 } else { 10485 ast_rwlock_wrlock(&globalslock); 10486 headp = &globals; 10487 } 10488 10489 /* For comparison purposes, we have to strip leading underscores */ 10490 if (*nametail == '_') { 10491 nametail++; 10492 if (*nametail == '_') 10493 nametail++; 10494 } 10495 10496 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10497 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10498 /* there is already such a variable, delete it */ 10499 AST_LIST_REMOVE_CURRENT(entries); 10500 ast_var_delete(newvariable); 10501 break; 10502 } 10503 } 10504 AST_LIST_TRAVERSE_SAFE_END; 10505 10506 if (value && (newvariable = ast_var_assign(name, value))) { 10507 if (headp == &globals) 10508 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10509 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10510 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10511 "Channel: %s\r\n" 10512 "Variable: %s\r\n" 10513 "Value: %s\r\n" 10514 "Uniqueid: %s\r\n", 10515 chan ? chan->name : "none", name, value, 10516 chan ? chan->uniqueid : "none"); 10517 } 10518 10519 if (chan) 10520 ast_channel_unlock(chan); 10521 else 10522 ast_rwlock_unlock(&globalslock); 10523 return 0; 10524 }
| 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 10556 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().
10557 { 10558 char *data; 10559 int x; 10560 AST_DECLARE_APP_ARGS(args, 10561 AST_APP_ARG(pair)[24]; 10562 ); 10563 AST_DECLARE_APP_ARGS(pair, 10564 AST_APP_ARG(name); 10565 AST_APP_ARG(value); 10566 ); 10567 10568 if (ast_strlen_zero(vdata)) { 10569 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10570 return 0; 10571 } 10572 10573 data = ast_strdupa(vdata); 10574 AST_STANDARD_APP_ARGS(args, data); 10575 10576 for (x = 0; x < args.argc; x++) { 10577 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10578 if (pair.argc == 2) { 10579 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10580 if (strchr(pair.name, ' ')) 10581 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); 10582 } else if (!chan) { 10583 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10584 } else { 10585 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10586 } 10587 } 10588 10589 return 0; 10590 }
| 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 10642 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().
10643 { 10644 int res; 10645 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10646 return 0; 10647 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10648 return res; 10649 } else { /* Strings are true */ 10650 return 1; 10651 } 10652 }
| int pbx_exec | ( | struct ast_channel * | c, | |
| struct ast_app * | app, | |||
| const char * | data | |||
| ) |
Execute an application.
| c | channel to execute on | |
| app | which app to execute | |
| data | the data passed into the app |
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.
| 0 | success | |
| -1 | failure |
| c | Channel | |
| app | Application | |
| data | Data for execution |
Definition at line 1451 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_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(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01454 { 01455 int res; 01456 struct ast_module_user *u = NULL; 01457 const char *saved_c_appl; 01458 const char *saved_c_data; 01459 01460 if (c->cdr && !ast_check_hangup(c)) 01461 ast_cdr_setapp(c->cdr, app->name, data); 01462 01463 /* save channel values */ 01464 saved_c_appl= c->appl; 01465 saved_c_data= c->data; 01466 01467 c->appl = app->name; 01468 c->data = data; 01469 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01470 01471 if (app->module) 01472 u = __ast_module_user_add(app->module, c); 01473 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01474 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01475 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01476 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01477 app->name, (char *) data); 01478 } 01479 res = app->execute(c, S_OR(data, "")); 01480 if (app->module && u) 01481 __ast_module_user_remove(app->module, u); 01482 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01483 /* restore channel values */ 01484 c->appl = saved_c_appl; 01485 c->data = saved_c_data; 01486 return res; 01487 }
| struct ast_exten* pbx_find_extension | ( | struct ast_channel * | chan, | |
| struct ast_context * | bypass, | |||
| struct pbx_find_info * | q, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| enum ext_match_t | action | |||
| ) | [read] |
Definition at line 2971 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().
02975 { 02976 int x, res; 02977 struct ast_context *tmp = NULL; 02978 struct ast_exten *e = NULL, *eroot = NULL; 02979 struct ast_include *i = NULL; 02980 struct ast_sw *sw = NULL; 02981 struct ast_exten pattern = {NULL, }; 02982 struct scoreboard score = {0, }; 02983 struct ast_str *tmpdata = NULL; 02984 02985 pattern.label = label; 02986 pattern.priority = priority; 02987 #ifdef NEED_DEBUG_HERE 02988 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02989 #endif 02990 02991 /* Initialize status if appropriate */ 02992 if (q->stacklen == 0) { 02993 q->status = STATUS_NO_CONTEXT; 02994 q->swo = NULL; 02995 q->data = NULL; 02996 q->foundcontext = NULL; 02997 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02998 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02999 return NULL; 03000 } 03001 03002 /* Check first to see if we've already been checked */ 03003 for (x = 0; x < q->stacklen; x++) { 03004 if (!strcasecmp(q->incstack[x], context)) 03005 return NULL; 03006 } 03007 03008 if (bypass) { /* bypass means we only look there */ 03009 tmp = bypass; 03010 } else { /* look in contexts */ 03011 tmp = find_context(context); 03012 if (!tmp) { 03013 return NULL; 03014 } 03015 } 03016 03017 if (q->status < STATUS_NO_EXTENSION) 03018 q->status = STATUS_NO_EXTENSION; 03019 03020 /* Do a search for matching extension */ 03021 03022 eroot = NULL; 03023 score.total_specificity = 0; 03024 score.exten = 0; 03025 score.total_length = 0; 03026 if (!tmp->pattern_tree && tmp->root_table) { 03027 create_match_char_tree(tmp); 03028 #ifdef NEED_DEBUG 03029 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 03030 log_match_char_tree(tmp->pattern_tree," "); 03031 #endif 03032 } 03033 #ifdef NEED_DEBUG 03034 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03035 log_match_char_tree(tmp->pattern_tree, ":: "); 03036 #endif 03037 03038 do { 03039 if (!ast_strlen_zero(overrideswitch)) { 03040 char *osw = ast_strdupa(overrideswitch), *name; 03041 struct ast_switch *asw; 03042 ast_switch_f *aswf = NULL; 03043 char *datap; 03044 int eval = 0; 03045 03046 name = strsep(&osw, "/"); 03047 asw = pbx_findswitch(name); 03048 03049 if (!asw) { 03050 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03051 break; 03052 } 03053 03054 if (osw && strchr(osw, '$')) { 03055 eval = 1; 03056 } 03057 03058 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03059 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03060 break; 03061 } else if (eval) { 03062 /* Substitute variables now */ 03063 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03064 datap = ast_str_buffer(tmpdata); 03065 } else { 03066 datap = osw; 03067 } 03068 03069 /* equivalent of extension_match_core() at the switch level */ 03070 if (action == E_CANMATCH) 03071 aswf = asw->canmatch; 03072 else if (action == E_MATCHMORE) 03073 aswf = asw->matchmore; 03074 else /* action == E_MATCH */ 03075 aswf = asw->exists; 03076 if (!aswf) { 03077 res = 0; 03078 } else { 03079 if (chan) { 03080 ast_autoservice_start(chan); 03081 } 03082 res = aswf(chan, context, exten, priority, callerid, datap); 03083 if (chan) { 03084 ast_autoservice_stop(chan); 03085 } 03086 } 03087 if (res) { /* Got a match */ 03088 q->swo = asw; 03089 q->data = datap; 03090 q->foundcontext = context; 03091 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03092 return NULL; 03093 } 03094 } 03095 } while (0); 03096 03097 if (extenpatternmatchnew) { 03098 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03099 eroot = score.exten; 03100 03101 if (score.last_char == '!' && action == E_MATCHMORE) { 03102 /* We match an extension ending in '!'. 03103 * The decision in this case is final and is NULL (no match). 03104 */ 03105 #ifdef NEED_DEBUG_HERE 03106 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03107 #endif 03108 return NULL; 03109 } 03110 03111 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03112 q->status = STATUS_SUCCESS; 03113 #ifdef NEED_DEBUG_HERE 03114 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03115 #endif 03116 return score.canmatch_exten; 03117 } 03118 03119 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03120 if (score.node) { 03121 struct ast_exten *z = trie_find_next_match(score.node); 03122 if (z) { 03123 #ifdef NEED_DEBUG_HERE 03124 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03125 #endif 03126 } else { 03127 if (score.canmatch_exten) { 03128 #ifdef NEED_DEBUG_HERE 03129 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03130 #endif 03131 return score.canmatch_exten; 03132 } else { 03133 #ifdef NEED_DEBUG_HERE 03134 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03135 #endif 03136 } 03137 } 03138 return z; 03139 } 03140 #ifdef NEED_DEBUG_HERE 03141 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03142 #endif 03143 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03144 } 03145 03146 if (eroot) { 03147 /* found entry, now look for the right priority */ 03148 if (q->status < STATUS_NO_PRIORITY) 03149 q->status = STATUS_NO_PRIORITY; 03150 e = NULL; 03151 if (action == E_FINDLABEL && label ) { 03152 if (q->status < STATUS_NO_LABEL) 03153 q->status = STATUS_NO_LABEL; 03154 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03155 } else { 03156 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03157 } 03158 if (e) { /* found a valid match */ 03159 q->status = STATUS_SUCCESS; 03160 q->foundcontext = context; 03161 #ifdef NEED_DEBUG_HERE 03162 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03163 #endif 03164 return e; 03165 } 03166 } 03167 } else { /* the old/current default exten pattern match algorithm */ 03168 03169 /* scan the list trying to match extension and CID */ 03170 eroot = NULL; 03171 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03172 int match = extension_match_core(eroot->exten, exten, action); 03173 /* 0 on fail, 1 on match, 2 on earlymatch */ 03174 03175 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03176 continue; /* keep trying */ 03177 if (match == 2 && action == E_MATCHMORE) { 03178 /* We match an extension ending in '!'. 03179 * The decision in this case is final and is NULL (no match). 03180 */ 03181 return NULL; 03182 } 03183 /* found entry, now look for the right priority */ 03184 if (q->status < STATUS_NO_PRIORITY) 03185 q->status = STATUS_NO_PRIORITY; 03186 e = NULL; 03187 if (action == E_FINDLABEL && label ) { 03188 if (q->status < STATUS_NO_LABEL) 03189 q->status = STATUS_NO_LABEL; 03190 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03191 } else { 03192 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03193 } 03194 if (e) { /* found a valid match */ 03195 q->status = STATUS_SUCCESS; 03196 q->foundcontext = context; 03197 return e; 03198 } 03199 } 03200 } 03201 03202 /* Check alternative switches */ 03203 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03204 struct ast_switch *asw = pbx_findswitch(sw->name); 03205 ast_switch_f *aswf = NULL; 03206 char *datap; 03207 03208 if (!asw) { 03209 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03210 continue; 03211 } 03212 03213 /* Substitute variables now */ 03214 if (sw->eval) { 03215 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03216 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03217 continue; 03218 } 03219 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03220 } 03221 03222 /* equivalent of extension_match_core() at the switch level */ 03223 if (action == E_CANMATCH) 03224 aswf = asw->canmatch; 03225 else if (action == E_MATCHMORE) 03226 aswf = asw->matchmore; 03227 else /* action == E_MATCH */ 03228 aswf = asw->exists; 03229 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03230 if (!aswf) 03231 res = 0; 03232 else { 03233 if (chan) 03234 ast_autoservice_start(chan); 03235 res = aswf(chan, context, exten, priority, callerid, datap); 03236 if (chan) 03237 ast_autoservice_stop(chan); 03238 } 03239 if (res) { /* Got a match */ 03240 q->swo = asw; 03241 q->data = datap; 03242 q->foundcontext = context; 03243 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03244 return NULL; 03245 } 03246 } 03247 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03248 /* Now try any includes we have in this context */ 03249 for (i = tmp->includes; i; i = i->next) { 03250 if (include_valid(i)) { 03251 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03252 #ifdef NEED_DEBUG_HERE 03253 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03254 #endif 03255 return e; 03256 } 03257 if (q->swo) 03258 return NULL; 03259 } 03260 } 03261 return NULL; 03262 }
| 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 1495 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_run_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(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01496 { 01497 struct ast_app *tmp; 01498 01499 AST_RWLIST_RDLOCK(&apps); 01500 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01501 if (!strcasecmp(tmp->name, app)) 01502 break; 01503 } 01504 AST_RWLIST_UNLOCK(&apps); 01505 01506 return tmp; 01507 }
| 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 3392 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().
03393 { 03394 struct ast_str *str = ast_str_create(16); 03395 const char *cret; 03396 03397 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03398 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03399 *ret = cret ? workspace : NULL; 03400 ast_free(str); 03401 }
| 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 5894 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05895 { 05896 int oldval = autofallthrough; 05897 autofallthrough = newval; 05898 return oldval; 05899 }
| 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 5901 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05902 { 05903 int oldval = extenpatternmatchnew; 05904 extenpatternmatchnew = newval; 05905 return oldval; 05906 }
| 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 5908 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05909 { 05910 if (overrideswitch) { 05911 ast_free(overrideswitch); 05912 } 05913 if (!ast_strlen_zero(newval)) { 05914 overrideswitch = ast_strdup(newval); 05915 } else { 05916 overrideswitch = NULL; 05917 } 05918 }
| 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 }
1.6.1