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 3946 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().
03947 { 03948 struct ast_custom_function *cur; 03949 char tmps[80]; 03950 03951 if (!acf) { 03952 return -1; 03953 } 03954 03955 acf->mod = mod; 03956 #ifdef AST_XML_DOCS 03957 acf->docsrc = AST_STATIC_DOC; 03958 #endif 03959 03960 if (acf_retrieve_docs(acf)) { 03961 return -1; 03962 } 03963 03964 AST_RWLIST_WRLOCK(&acf_root); 03965 03966 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03967 if (!strcmp(acf->name, cur->name)) { 03968 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03969 AST_RWLIST_UNLOCK(&acf_root); 03970 return -1; 03971 } 03972 } 03973 03974 /* Store in alphabetical order */ 03975 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03976 if (strcasecmp(acf->name, cur->name) < 0) { 03977 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03978 break; 03979 } 03980 } 03981 AST_RWLIST_TRAVERSE_SAFE_END; 03982 03983 if (!cur) { 03984 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03985 } 03986 03987 AST_RWLIST_UNLOCK(&acf_root); 03988 03989 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03990 03991 return 0; 03992 }
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 3994 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.
03995 { 03996 struct ast_custom_escalating_function *acf_escalation = NULL; 03997 int res; 03998 03999 res = __ast_custom_function_register(acf, mod); 04000 if (res != 0) { 04001 return -1; 04002 } 04003 04004 if (escalation == AST_CFE_NONE) { 04005 /* No escalations; no need to do anything else */ 04006 return 0; 04007 } 04008 04009 acf_escalation = ast_calloc(1, sizeof(*acf_escalation)); 04010 if (!acf_escalation) { 04011 ast_custom_function_unregister(acf); 04012 return -1; 04013 } 04014 04015 acf_escalation->acf = acf; 04016 switch (escalation) { 04017 case AST_CFE_NONE: 04018 break; 04019 case AST_CFE_READ: 04020 acf_escalation->read_escalates = 1; 04021 break; 04022 case AST_CFE_WRITE: 04023 acf_escalation->write_escalates = 1; 04024 break; 04025 case AST_CFE_BOTH: 04026 acf_escalation->read_escalates = 1; 04027 acf_escalation->write_escalates = 1; 04028 break; 04029 } 04030 04031 AST_RWLIST_WRLOCK(&escalation_root); 04032 AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list); 04033 AST_RWLIST_UNLOCK(&escalation_root); 04034 04035 return 0; 04036 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5931 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05932 { 05933 return countcalls; 05934 }
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 8691 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().
08694 { 08695 int ret = -1; 08696 struct ast_context *c; 08697 08698 c = find_context_locked(context); 08699 if (c) { 08700 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08701 application, data, datad, registrar); 08702 ast_unlock_contexts(); 08703 } 08704 08705 return ret; 08706 }
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 9052 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().
09056 { 09057 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 09058 application, data, datad, registrar, 1); 09059 }
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 8731 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().
08732 { 08733 int res = 0; 08734 struct ast_channel *tmpchan; 08735 struct { 08736 char *accountcode; 08737 char *exten; 08738 char *context; 08739 char *linkedid; 08740 char *name; 08741 struct ast_cdr *cdr; 08742 int amaflags; 08743 int state; 08744 format_t readformat; 08745 format_t writeformat; 08746 } tmpvars = { 0, }; 08747 08748 ast_channel_lock(chan); 08749 if (chan->pbx) { /* This channel is currently in the PBX */ 08750 ast_explicit_goto(chan, context, exten, priority + 1); 08751 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08752 ast_channel_unlock(chan); 08753 return res; 08754 } 08755 08756 /* In order to do it when the channel doesn't really exist within 08757 * the PBX, we have to make a new channel, masquerade, and start the PBX 08758 * at the new location */ 08759 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08760 tmpvars.exten = ast_strdupa(chan->exten); 08761 tmpvars.context = ast_strdupa(chan->context); 08762 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08763 tmpvars.name = ast_strdupa(chan->name); 08764 tmpvars.amaflags = chan->amaflags; 08765 tmpvars.state = chan->_state; 08766 tmpvars.writeformat = chan->writeformat; 08767 tmpvars.readformat = chan->readformat; 08768 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08769 08770 ast_channel_unlock(chan); 08771 08772 /* Do not hold any channel locks while calling channel_alloc() since the function 08773 * locks the channel container when linking the new channel in. */ 08774 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08775 ast_cdr_discard(tmpvars.cdr); 08776 return -1; 08777 } 08778 08779 /* copy the cdr info over */ 08780 if (tmpvars.cdr) { 08781 ast_cdr_discard(tmpchan->cdr); 08782 tmpchan->cdr = tmpvars.cdr; 08783 tmpvars.cdr = NULL; 08784 } 08785 08786 /* Make formats okay */ 08787 tmpchan->readformat = tmpvars.readformat; 08788 tmpchan->writeformat = tmpvars.writeformat; 08789 08790 /* Setup proper location. Never hold another channel lock while calling this function. */ 08791 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08792 08793 /* Masquerade into tmp channel */ 08794 if (ast_channel_masquerade(tmpchan, chan)) { 08795 /* Failed to set up the masquerade. It's probably chan_local 08796 * in the middle of optimizing itself out. Sad. :( */ 08797 ast_hangup(tmpchan); 08798 tmpchan = NULL; 08799 res = -1; 08800 } else { 08801 ast_do_masquerade(tmpchan); 08802 /* Start the PBX going on our stolen channel */ 08803 if (ast_pbx_start(tmpchan)) { 08804 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08805 ast_hangup(tmpchan); 08806 res = -1; 08807 } 08808 } 08809 08810 return res; 08811 }
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 8813 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08814 { 08815 struct ast_channel *chan; 08816 int res = -1; 08817 08818 if ((chan = ast_channel_get_by_name(channame))) { 08819 res = ast_async_goto(chan, context, exten, priority); 08820 chan = ast_channel_unref(chan); 08821 } 08822 08823 return res; 08824 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11266 of file pbx.c.
References __ast_goto_if_exists().
11267 { 11268 return __ast_goto_if_exists(chan, context, exten, priority, 1); 11269 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11331 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
11332 { 11333 return pbx_parseable_goto(chan, goto_string, 1); 11334 }
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 8314 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().
08315 { 08316 char *info; 08317 int j, num_fields, last_sep = -1; 08318 08319 i->timezone = NULL; 08320 08321 /* Check for empty just in case */ 08322 if (ast_strlen_zero(info_in)) { 08323 return 0; 08324 } 08325 08326 /* make a copy just in case we were passed a static string */ 08327 info = ast_strdupa(info_in); 08328 08329 /* count the number of fields in the timespec */ 08330 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08331 if (info[j] == ',') { 08332 last_sep = j; 08333 num_fields++; 08334 } 08335 } 08336 08337 /* save the timezone, if it is specified */ 08338 if (num_fields == 5) { 08339 i->timezone = ast_strdup(info + last_sep + 1); 08340 } 08341 08342 /* Assume everything except time */ 08343 i->monthmask = 0xfff; /* 12 bits */ 08344 i->daymask = 0x7fffffffU; /* 31 bits */ 08345 i->dowmask = 0x7f; /* 7 bits */ 08346 /* on each call, use strsep() to move info to the next argument */ 08347 get_timerange(i, strsep(&info, "|,")); 08348 if (info) 08349 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08350 if (info) 08351 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08352 if (info) 08353 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08354 return 1; 08355 }
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 5415 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().
05416 { 05417 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05418 }
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 8357 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08358 { 08359 return ast_check_timing2(i, ast_tvnow()); 08360 }
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 8362 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().
08363 { 08364 struct ast_tm tm; 08365 08366 ast_localtime(&tv, &tm, i->timezone); 08367 08368 /* If it's not the right month, return */ 08369 if (!(i->monthmask & (1 << tm.tm_mon))) 08370 return 0; 08371 08372 /* If it's not that time of the month.... */ 08373 /* Warning, tm_mday has range 1..31! */ 08374 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08375 return 0; 08376 08377 /* If it's not the right day of the week */ 08378 if (!(i->dowmask & (1 << tm.tm_wday))) 08379 return 0; 08380 08381 /* Sanity check the hour just to be safe */ 08382 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08383 ast_log(LOG_WARNING, "Insane time...\n"); 08384 return 0; 08385 } 08386 08387 /* Now the tough part, we calculate if it fits 08388 in the right time based on min/hour */ 08389 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)))) 08390 return 0; 08391 08392 /* If we got this far, then we're good */ 08393 return 1; 08394 }
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 11336 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().
11337 { 11338 struct ast_app *app = NULL; 11339 int which = 0; 11340 char *ret = NULL; 11341 size_t wordlen = strlen(word); 11342 11343 AST_RWLIST_RDLOCK(&apps); 11344 AST_RWLIST_TRAVERSE(&apps, app, list) { 11345 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 11346 ret = ast_strdup(app->name); 11347 break; 11348 } 11349 } 11350 AST_RWLIST_UNLOCK(&apps); 11351 11352 return ret; 11353 }
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 8598 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08599 { 08600 int ret = -1; 08601 struct ast_context *c; 08602 08603 c = find_context_locked(context); 08604 if (c) { 08605 ret = ast_context_add_ignorepat2(c, value, registrar); 08606 ast_unlock_contexts(); 08607 } 08608 return ret; 08609 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8611 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().
08612 { 08613 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08614 int length; 08615 char *pattern; 08616 length = sizeof(struct ast_ignorepat); 08617 length += strlen(value) + 1; 08618 if (!(ignorepat = ast_calloc(1, length))) 08619 return -1; 08620 /* The cast to char * is because we need to write the initial value. 08621 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08622 * sees the cast as dereferencing a type-punned pointer and warns about 08623 * it. This is the workaround (we're telling gcc, yes, that's really 08624 * what we wanted to do). 08625 */ 08626 pattern = (char *) ignorepat->pattern; 08627 strcpy(pattern, value); 08628 ignorepat->next = NULL; 08629 ignorepat->registrar = registrar; 08630 ast_wrlock_context(con); 08631 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08632 ignorepatl = ignorepatc; 08633 if (!strcasecmp(ignorepatc->pattern, value)) { 08634 /* Already there */ 08635 ast_unlock_context(con); 08636 ast_free(ignorepat); 08637 errno = EEXIST; 08638 return -1; 08639 } 08640 } 08641 if (ignorepatl) 08642 ignorepatl->next = ignorepat; 08643 else 08644 con->ignorepats = ignorepat; 08645 ast_unlock_context(con); 08646 return 0; 08647 08648 }
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 8142 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
08143 { 08144 int ret = -1; 08145 struct ast_context *c; 08146 08147 c = find_context_locked(context); 08148 if (c) { 08149 ret = ast_context_add_include2(c, include, registrar); 08150 ast_unlock_contexts(); 08151 } 08152 return ret; 08153 }
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 8411 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().
08413 { 08414 struct ast_include *new_include; 08415 char *c; 08416 struct ast_include *i, *il = NULL; /* include, include_last */ 08417 int length; 08418 char *p; 08419 08420 length = sizeof(struct ast_include); 08421 length += 2 * (strlen(value) + 1); 08422 08423 /* allocate new include structure ... */ 08424 if (!(new_include = ast_calloc(1, length))) 08425 return -1; 08426 /* Fill in this structure. Use 'p' for assignments, as the fields 08427 * in the structure are 'const char *' 08428 */ 08429 p = new_include->stuff; 08430 new_include->name = p; 08431 strcpy(p, value); 08432 p += strlen(value) + 1; 08433 new_include->rname = p; 08434 strcpy(p, value); 08435 /* Strip off timing info, and process if it is there */ 08436 if ( (c = strchr(p, ',')) ) { 08437 *c++ = '\0'; 08438 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08439 } 08440 new_include->next = NULL; 08441 new_include->registrar = registrar; 08442 08443 ast_wrlock_context(con); 08444 08445 /* ... go to last include and check if context is already included too... */ 08446 for (i = con->includes; i; i = i->next) { 08447 if (!strcasecmp(i->name, new_include->name)) { 08448 ast_destroy_timing(&(new_include->timing)); 08449 ast_free(new_include); 08450 ast_unlock_context(con); 08451 errno = EEXIST; 08452 return -1; 08453 } 08454 il = i; 08455 } 08456 08457 /* ... include new context into context list, unlock, return */ 08458 if (il) 08459 il->next = new_include; 08460 else 08461 con->includes = new_include; 08462 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08463 08464 ast_unlock_context(con); 08465 08466 return 0; 08467 }
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 8474 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08475 { 08476 int ret = -1; 08477 struct ast_context *c; 08478 08479 c = find_context_locked(context); 08480 if (c) { /* found, add switch to this context */ 08481 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08482 ast_unlock_contexts(); 08483 } 08484 return ret; 08485 }
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 8494 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().
08496 { 08497 struct ast_sw *new_sw; 08498 struct ast_sw *i; 08499 int length; 08500 char *p; 08501 08502 length = sizeof(struct ast_sw); 08503 length += strlen(value) + 1; 08504 if (data) 08505 length += strlen(data); 08506 length++; 08507 08508 /* allocate new sw structure ... */ 08509 if (!(new_sw = ast_calloc(1, length))) 08510 return -1; 08511 /* ... fill in this structure ... */ 08512 p = new_sw->stuff; 08513 new_sw->name = p; 08514 strcpy(new_sw->name, value); 08515 p += strlen(value) + 1; 08516 new_sw->data = p; 08517 if (data) { 08518 strcpy(new_sw->data, data); 08519 p += strlen(data) + 1; 08520 } else { 08521 strcpy(new_sw->data, ""); 08522 p++; 08523 } 08524 new_sw->eval = eval; 08525 new_sw->registrar = registrar; 08526 08527 /* ... try to lock this context ... */ 08528 ast_wrlock_context(con); 08529 08530 /* ... go to last sw and check if context is already swd too... */ 08531 AST_LIST_TRAVERSE(&con->alts, i, list) { 08532 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08533 ast_free(new_sw); 08534 ast_unlock_context(con); 08535 errno = EEXIST; 08536 return -1; 08537 } 08538 } 08539 08540 /* ... sw new context into context list, unlock, return */ 08541 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08542 08543 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08544 08545 ast_unlock_context(con); 08546 08547 return 0; 08548 }
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 9875 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().
09876 { 09877 ast_wrlock_contexts(); 09878 __ast_context_destroy(contexts, contexts_table, con,registrar); 09879 ast_unlock_contexts(); 09880 }
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 2971 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().
02972 { 02973 struct ast_context *tmp; 02974 struct fake_context item; 02975 02976 if (!name) { 02977 return NULL; 02978 } 02979 ast_rdlock_contexts(); 02980 if (contexts_table) { 02981 ast_copy_string(item.name, name, sizeof(item.name)); 02982 tmp = ast_hashtab_lookup(contexts_table, &item); 02983 } else { 02984 tmp = NULL; 02985 while ((tmp = ast_walk_contexts(tmp))) { 02986 if (!strcasecmp(name, tmp->name)) { 02987 break; 02988 } 02989 } 02990 } 02991 ast_unlock_contexts(); 02992 return tmp; 02993 }
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 7726 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().
07727 { 07728 struct ast_context *tmp, **local_contexts; 07729 struct fake_context search; 07730 int length = sizeof(struct ast_context) + strlen(name) + 1; 07731 07732 if (!contexts_table) { 07733 /* Protect creation of contexts_table from reentrancy. */ 07734 ast_wrlock_contexts(); 07735 if (!contexts_table) { 07736 contexts_table = ast_hashtab_create(17, 07737 ast_hashtab_compare_contexts, 07738 ast_hashtab_resize_java, 07739 ast_hashtab_newsize_java, 07740 ast_hashtab_hash_contexts, 07741 0); 07742 } 07743 ast_unlock_contexts(); 07744 } 07745 07746 ast_copy_string(search.name, name, sizeof(search.name)); 07747 if (!extcontexts) { 07748 ast_rdlock_contexts(); 07749 local_contexts = &contexts; 07750 tmp = ast_hashtab_lookup(contexts_table, &search); 07751 ast_unlock_contexts(); 07752 if (tmp) { 07753 tmp->refcount++; 07754 return tmp; 07755 } 07756 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07757 local_contexts = extcontexts; 07758 tmp = ast_hashtab_lookup(exttable, &search); 07759 if (tmp) { 07760 tmp->refcount++; 07761 return tmp; 07762 } 07763 } 07764 07765 if ((tmp = ast_calloc(1, length))) { 07766 ast_rwlock_init(&tmp->lock); 07767 ast_mutex_init(&tmp->macrolock); 07768 strcpy(tmp->name, name); 07769 tmp->root = NULL; 07770 tmp->root_table = NULL; 07771 tmp->registrar = ast_strdup(registrar); 07772 tmp->includes = NULL; 07773 tmp->ignorepats = NULL; 07774 tmp->refcount = 1; 07775 } else { 07776 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07777 return NULL; 07778 } 07779 07780 if (!extcontexts) { 07781 ast_wrlock_contexts(); 07782 tmp->next = *local_contexts; 07783 *local_contexts = tmp; 07784 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07785 ast_unlock_contexts(); 07786 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07787 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07788 } else { 07789 tmp->next = *local_contexts; 07790 if (exttable) 07791 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07792 07793 *local_contexts = tmp; 07794 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07795 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07796 } 07797 return tmp; 07798 }
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 6306 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06307 { 06308 struct ast_context *c; 06309 int ret = -1; 06310 06311 c = find_context_locked(context); 06312 if (c) { 06313 ast_unlock_contexts(); 06314 06315 /* if we found context, lock macrolock */ 06316 ret = ast_mutex_lock(&c->macrolock); 06317 } 06318 06319 return ret; 06320 }
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 6114 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().
06115 { 06116 return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar); 06117 }
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 6144 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().
06145 { 06146 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked); 06147 }
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 6119 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().
06120 { 06121 int ret = -1; /* default error return */ 06122 struct ast_context *c; 06123 06124 c = find_context_locked(context); 06125 if (c) { /* ... remove extension ... */ 06126 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 06127 matchcallerid, registrar, 0); 06128 ast_unlock_contexts(); 06129 } 06130 06131 return ret; 06132 }
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 6149 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().
06150 { 06151 struct ast_exten *exten, *prev_exten = NULL; 06152 struct ast_exten *peer; 06153 struct ast_exten ex, *exten2, *exten3; 06154 char dummy_name[1024]; 06155 struct ast_exten *previous_peer = NULL; 06156 struct ast_exten *next_peer = NULL; 06157 int found = 0; 06158 06159 if (!already_locked) 06160 ast_wrlock_context(con); 06161 06162 #ifdef NEED_DEBUG 06163 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 06164 #endif 06165 #ifdef CONTEXT_DEBUG 06166 check_contexts(__FILE__, __LINE__); 06167 #endif 06168 /* find this particular extension */ 06169 ex.exten = dummy_name; 06170 ex.matchcid = matchcallerid; 06171 ex.cidmatch = callerid; 06172 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 06173 exten = ast_hashtab_lookup(con->root_table, &ex); 06174 if (exten) { 06175 if (priority == 0) { 06176 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06177 if (!exten2) 06178 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); 06179 if (con->pattern_tree) { 06180 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06181 06182 if (x->exten) { /* this test for safety purposes */ 06183 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06184 x->exten = 0; /* get rid of what will become a bad pointer */ 06185 } else { 06186 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 06187 } 06188 } 06189 } else { 06190 ex.priority = priority; 06191 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 06192 if (exten2) { 06193 if (exten2->label) { /* if this exten has a label, remove that, too */ 06194 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 06195 if (!exten3) 06196 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); 06197 } 06198 06199 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 06200 if (!exten3) 06201 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); 06202 if (exten2 == exten && exten2->peer) { 06203 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06204 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 06205 } 06206 if (ast_hashtab_size(exten->peer_table) == 0) { 06207 /* well, if the last priority of an exten is to be removed, 06208 then, the extension is removed, too! */ 06209 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 06210 if (!exten3) 06211 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 06212 if (con->pattern_tree) { 06213 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06214 if (x->exten) { /* this test for safety purposes */ 06215 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06216 x->exten = 0; /* get rid of what will become a bad pointer */ 06217 } 06218 } 06219 } 06220 } else { 06221 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 06222 priority, exten->exten, con->name); 06223 } 06224 } 06225 } else { 06226 /* hmmm? this exten is not in this pattern tree? */ 06227 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 06228 extension, con->name); 06229 } 06230 #ifdef NEED_DEBUG 06231 if (con->pattern_tree) { 06232 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 06233 log_match_char_tree(con->pattern_tree, " "); 06234 } 06235 #endif 06236 06237 /* scan the extension list to find first matching extension-registrar */ 06238 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 06239 if (!strcmp(exten->exten, extension) && 06240 (!registrar || !strcmp(exten->registrar, registrar)) && 06241 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 06242 break; 06243 } 06244 if (!exten) { 06245 /* we can't find right extension */ 06246 if (!already_locked) 06247 ast_unlock_context(con); 06248 return -1; 06249 } 06250 06251 /* scan the priority list to remove extension with exten->priority == priority */ 06252 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 06253 peer && !strcmp(peer->exten, extension) && 06254 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ; 06255 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 06256 06257 if ((priority == 0 || peer->priority == priority) && 06258 (!registrar || !strcmp(peer->registrar, registrar) )) { 06259 found = 1; 06260 06261 /* we are first priority extension? */ 06262 if (!previous_peer) { 06263 /* 06264 * We are first in the priority chain, so must update the extension chain. 06265 * The next node is either the next priority or the next extension 06266 */ 06267 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 06268 if (peer->peer) { 06269 /* move the peer_table and peer_label_table down to the next peer, if 06270 it is there */ 06271 peer->peer->peer_table = peer->peer_table; 06272 peer->peer->peer_label_table = peer->peer_label_table; 06273 peer->peer_table = NULL; 06274 peer->peer_label_table = NULL; 06275 } 06276 if (!prev_exten) { /* change the root... */ 06277 con->root = next_node; 06278 } else { 06279 prev_exten->next = next_node; /* unlink */ 06280 } 06281 if (peer->peer) { /* update the new head of the pri list */ 06282 peer->peer->next = peer->next; 06283 } 06284 } else { /* easy, we are not first priority in extension */ 06285 previous_peer->peer = peer->peer; 06286 } 06287 06288 06289 /* now, free whole priority extension */ 06290 destroy_exten(peer); 06291 } else { 06292 previous_peer = peer; 06293 } 06294 } 06295 if (!already_locked) 06296 ast_unlock_context(con); 06297 return found ? 0 : -1; 06298 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8554 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08555 { 08556 int ret = -1; 08557 struct ast_context *c; 08558 08559 c = find_context_locked(context); 08560 if (c) { 08561 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08562 ast_unlock_contexts(); 08563 } 08564 return ret; 08565 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8567 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().
08568 { 08569 struct ast_ignorepat *ip, *ipl = NULL; 08570 08571 ast_wrlock_context(con); 08572 08573 for (ip = con->ignorepats; ip; ip = ip->next) { 08574 if (!strcmp(ip->pattern, ignorepat) && 08575 (!registrar || (registrar == ip->registrar))) { 08576 if (ipl) { 08577 ipl->next = ip->next; 08578 ast_free(ip); 08579 } else { 08580 con->ignorepats = ip->next; 08581 ast_free(ip); 08582 } 08583 ast_unlock_context(con); 08584 return 0; 08585 } 08586 ipl = ip; 08587 } 08588 08589 ast_unlock_context(con); 08590 errno = EINVAL; 08591 return -1; 08592 }
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 6007 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
06008 { 06009 int ret = -1; 06010 struct ast_context *c; 06011 06012 c = find_context_locked(context); 06013 if (c) { 06014 /* found, remove include from this context ... */ 06015 ret = ast_context_remove_include2(c, include, registrar); 06016 ast_unlock_contexts(); 06017 } 06018 return ret; 06019 }
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 6030 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().
06031 { 06032 struct ast_include *i, *pi = NULL; 06033 int ret = -1; 06034 06035 ast_wrlock_context(con); 06036 06037 /* find our include */ 06038 for (i = con->includes; i; pi = i, i = i->next) { 06039 if (!strcmp(i->name, include) && 06040 (!registrar || !strcmp(i->registrar, registrar))) { 06041 /* remove from list */ 06042 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 06043 if (pi) 06044 pi->next = i->next; 06045 else 06046 con->includes = i->next; 06047 /* free include and return */ 06048 ast_destroy_timing(&(i->timing)); 06049 ast_free(i); 06050 ret = 0; 06051 break; 06052 } 06053 } 06054 06055 ast_unlock_context(con); 06056 06057 return ret; 06058 }
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 6065 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
06066 { 06067 int ret = -1; /* default error return */ 06068 struct ast_context *c; 06069 06070 c = find_context_locked(context); 06071 if (c) { 06072 /* remove switch from this context ... */ 06073 ret = ast_context_remove_switch2(c, sw, data, registrar); 06074 ast_unlock_contexts(); 06075 } 06076 return ret; 06077 }
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 6087 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().
06088 { 06089 struct ast_sw *i; 06090 int ret = -1; 06091 06092 ast_wrlock_context(con); 06093 06094 /* walk switches */ 06095 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 06096 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 06097 (!registrar || !strcmp(i->registrar, registrar))) { 06098 /* found, remove from list */ 06099 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 06100 AST_LIST_REMOVE_CURRENT(list); 06101 ast_free(i); /* free switch and return */ 06102 ret = 0; 06103 break; 06104 } 06105 } 06106 AST_LIST_TRAVERSE_SAFE_END; 06107 06108 ast_unlock_context(con); 06109 06110 return ret; 06111 }
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 6327 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06328 { 06329 struct ast_context *c; 06330 int ret = -1; 06331 06332 c = find_context_locked(context); 06333 if (c) { 06334 ast_unlock_contexts(); 06335 06336 /* if we found context, unlock macrolock */ 06337 ret = ast_mutex_unlock(&c->macrolock); 06338 } 06339 06340 return ret; 06341 }
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 11221 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().
11222 { 11223 struct ast_include *inc = NULL; 11224 int res = 0; 11225 11226 while ( (inc = ast_walk_context_includes(con, inc)) ) { 11227 if (ast_context_find(inc->rname)) 11228 continue; 11229 11230 res = -1; 11231 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 11232 ast_get_context_name(con), inc->rname); 11233 break; 11234 } 11235 11236 return res; 11237 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3800 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().
03801 { 03802 struct ast_custom_function *acf = NULL; 03803 03804 AST_RWLIST_RDLOCK(&acf_root); 03805 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03806 if (!strcmp(name, acf->name)) 03807 break; 03808 } 03809 AST_RWLIST_UNLOCK(&acf_root); 03810 03811 return acf; 03812 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3814 of file pbx.c.
References ast_custom_escalating_function::acf, ast_free, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by __ast_custom_function_register_escalating(), _unload_module(), load_module(), reload(), unload_module(), and unload_pbx().
03815 { 03816 struct ast_custom_function *cur; 03817 struct ast_custom_escalating_function *cur_escalation; 03818 03819 if (!acf) { 03820 return -1; 03821 } 03822 03823 AST_RWLIST_WRLOCK(&acf_root); 03824 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03825 #ifdef AST_XML_DOCS 03826 if (cur->docsrc == AST_XML_DOC) { 03827 ast_string_field_free_memory(acf); 03828 } 03829 #endif 03830 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03831 } 03832 AST_RWLIST_UNLOCK(&acf_root); 03833 03834 /* Remove from the escalation list */ 03835 AST_RWLIST_WRLOCK(&escalation_root); 03836 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) { 03837 if (cur_escalation->acf == acf) { 03838 AST_RWLIST_REMOVE_CURRENT(list); 03839 ast_free(cur_escalation); 03840 break; 03841 } 03842 } 03843 AST_RWLIST_TRAVERSE_SAFE_END; 03844 AST_RWLIST_UNLOCK(&escalation_root); 03845 03846 return cur ? 0 : -1; 03847 }
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 8396 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 4844 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().
04845 { 04846 switch (devstate) { 04847 case AST_DEVICE_ONHOLD: 04848 return AST_EXTENSION_ONHOLD; 04849 case AST_DEVICE_BUSY: 04850 return AST_EXTENSION_BUSY; 04851 case AST_DEVICE_UNKNOWN: 04852 return AST_EXTENSION_NOT_INUSE; 04853 case AST_DEVICE_UNAVAILABLE: 04854 case AST_DEVICE_INVALID: 04855 return AST_EXTENSION_UNAVAILABLE; 04856 case AST_DEVICE_RINGINUSE: 04857 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04858 case AST_DEVICE_RINGING: 04859 return AST_EXTENSION_RINGING; 04860 case AST_DEVICE_INUSE: 04861 return AST_EXTENSION_INUSE; 04862 case AST_DEVICE_NOT_INUSE: 04863 return AST_EXTENSION_NOT_INUSE; 04864 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04865 break; 04866 } 04867 04868 return AST_EXTENSION_NOT_INUSE; 04869 }
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 5400 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().
05401 { 05402 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05403 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8708 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), and pbx_parseable_goto().
08709 { 08710 if (!chan) 08711 return -1; 08712 08713 ast_channel_lock(chan); 08714 08715 if (!ast_strlen_zero(context)) 08716 ast_copy_string(chan->context, context, sizeof(chan->context)); 08717 if (!ast_strlen_zero(exten)) 08718 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08719 if (priority > -1) { 08720 chan->priority = priority; 08721 /* see flag description in channel.h for explanation */ 08722 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08723 chan->priority--; 08724 } 08725 08726 ast_channel_unlock(chan); 08727 08728 return 0; 08729 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2948 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().
02949 { 02950 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02951 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02952 return extension_match_core(pattern, data, needmore); 02953 }
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 2713 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02714 { 02715 int cmp; 02716 02717 cmp = ext_cmp(a, b); 02718 if (cmp < 0) { 02719 return -1; 02720 } 02721 if (cmp > 0) { 02722 return 1; 02723 } 02724 return 0; 02725 }
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 2943 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().
02944 { 02945 return extension_match_core(pattern, data, E_MATCH); 02946 }
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 4914 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().
04915 { 04916 struct ast_exten *e; 04917 04918 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04919 return -1; /* No hint, return -1 */ 04920 } 04921 04922 if (e->exten[0] == '_') { 04923 /* Create this hint on-the-fly */ 04924 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04925 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04926 e->registrar); 04927 if (!(e = ast_hint_extension(c, context, exten))) { 04928 /* Improbable, but not impossible */ 04929 return -1; 04930 } 04931 } 04932 04933 return ast_extension_state2(e); /* Check all devices in the hint */ 04934 }
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 4902 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().
04903 { 04904 int i; 04905 04906 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04907 if (extension_states[i].extension_state == extension_state) 04908 return extension_states[i].text; 04909 } 04910 return "Unknown"; 04911 }
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 5135 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
05137 { 05138 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 05139 }
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 5048 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().
05050 { 05051 struct ast_hint *hint; 05052 struct ast_state_cb *state_cb; 05053 struct ast_exten *e; 05054 int id; 05055 05056 /* If there's no context and extension: add callback to statecbs list */ 05057 if (!context && !exten) { 05058 /* Prevent multiple adds from adding the same change_cb at the same time. */ 05059 ao2_lock(statecbs); 05060 05061 /* Remove any existing change_cb. */ 05062 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 05063 05064 /* Now insert the change_cb */ 05065 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05066 ao2_unlock(statecbs); 05067 return -1; 05068 } 05069 state_cb->id = 0; 05070 state_cb->change_cb = change_cb; 05071 state_cb->destroy_cb = destroy_cb; 05072 state_cb->data = data; 05073 ao2_link(statecbs, state_cb); 05074 05075 ao2_ref(state_cb, -1); 05076 ao2_unlock(statecbs); 05077 return 0; 05078 } 05079 05080 if (!context || !exten) 05081 return -1; 05082 05083 /* This callback type is for only one hint, so get the hint */ 05084 e = ast_hint_extension(NULL, context, exten); 05085 if (!e) { 05086 return -1; 05087 } 05088 05089 /* If this is a pattern, dynamically create a new extension for this 05090 * particular match. Note that this will only happen once for each 05091 * individual extension, because the pattern will no longer match first. 05092 */ 05093 if (e->exten[0] == '_') { 05094 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 05095 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 05096 e->registrar); 05097 e = ast_hint_extension(NULL, context, exten); 05098 if (!e || e->exten[0] == '_') { 05099 return -1; 05100 } 05101 } 05102 05103 /* Find the hint in the hints container */ 05104 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05105 hint = ao2_find(hints, e, 0); 05106 if (!hint) { 05107 ao2_unlock(hints); 05108 return -1; 05109 } 05110 05111 /* Now insert the callback in the callback list */ 05112 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05113 ao2_ref(hint, -1); 05114 ao2_unlock(hints); 05115 return -1; 05116 } 05117 do { 05118 id = stateid++; /* Unique ID for this callback */ 05119 /* Do not allow id to ever be -1 or 0. */ 05120 } while (id == -1 || id == 0); 05121 state_cb->id = id; 05122 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 05123 state_cb->destroy_cb = destroy_cb; 05124 state_cb->data = data; /* Data for the callback */ 05125 ao2_link(hint->callbacks, state_cb); 05126 05127 ao2_ref(state_cb, -1); 05128 ao2_ref(hint, -1); 05129 ao2_unlock(hints); 05130 05131 return id; 05132 }
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 5157 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().
05158 { 05159 struct ast_state_cb *p_cur; 05160 int ret = -1; 05161 05162 if (!id) { /* id == 0 is a callback without extension */ 05163 if (!change_cb) { 05164 return ret; 05165 } 05166 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 05167 if (p_cur) { 05168 ret = 0; 05169 ao2_ref(p_cur, -1); 05170 } 05171 } else { /* callback with extension, find the callback based on ID */ 05172 struct ast_hint *hint; 05173 05174 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05175 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 05176 if (hint) { 05177 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 05178 if (p_cur) { 05179 ret = 0; 05180 ao2_ref(p_cur, -1); 05181 } 05182 ao2_ref(hint, -1); 05183 } 05184 ao2_unlock(hints); 05185 } 05186 05187 return ret; 05188 }
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 5405 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().
05406 { 05407 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05408 }
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 5410 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05411 { 05412 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05413 }
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 4177 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().
04178 { 04179 char *copy = ast_strdupa(function); 04180 char *args = func_args(copy); 04181 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04182 int res; 04183 struct ast_module_user *u = NULL; 04184 04185 if (acfptr == NULL) { 04186 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04187 } else if (!acfptr->read && !acfptr->read2) { 04188 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04189 } else if (!is_read_allowed(acfptr)) { 04190 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04191 } else if (acfptr->read) { 04192 if (acfptr->mod) { 04193 u = __ast_module_user_add(acfptr->mod, chan); 04194 } 04195 res = acfptr->read(chan, copy, args, workspace, len); 04196 if (acfptr->mod && u) { 04197 __ast_module_user_remove(acfptr->mod, u); 04198 } 04199 return res; 04200 } else { 04201 struct ast_str *str = ast_str_create(16); 04202 if (acfptr->mod) { 04203 u = __ast_module_user_add(acfptr->mod, chan); 04204 } 04205 res = acfptr->read2(chan, copy, args, &str, 0); 04206 if (acfptr->mod && u) { 04207 __ast_module_user_remove(acfptr->mod, u); 04208 } 04209 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 04210 ast_free(str); 04211 return res; 04212 } 04213 return -1; 04214 }
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 4216 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().
04217 { 04218 char *copy = ast_strdupa(function); 04219 char *args = func_args(copy); 04220 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04221 int res; 04222 struct ast_module_user *u = NULL; 04223 04224 if (acfptr == NULL) { 04225 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04226 } else if (!acfptr->read && !acfptr->read2) { 04227 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04228 } else if (!is_read_allowed(acfptr)) { 04229 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04230 } else { 04231 if (acfptr->mod) { 04232 u = __ast_module_user_add(acfptr->mod, chan); 04233 } 04234 ast_str_reset(*str); 04235 if (acfptr->read2) { 04236 /* ast_str enabled */ 04237 res = acfptr->read2(chan, copy, args, str, maxlen); 04238 } else { 04239 /* Legacy function pointer, allocate buffer for result */ 04240 int maxsize = ast_str_size(*str); 04241 if (maxlen > -1) { 04242 if (maxlen == 0) { 04243 if (acfptr->read_max) { 04244 maxsize = acfptr->read_max; 04245 } else { 04246 maxsize = VAR_BUF_SIZE; 04247 } 04248 } else { 04249 maxsize = maxlen; 04250 } 04251 ast_str_make_space(str, maxsize); 04252 } 04253 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 04254 } 04255 if (acfptr->mod && u) { 04256 __ast_module_user_remove(acfptr->mod, u); 04257 } 04258 return res; 04259 } 04260 return -1; 04261 }
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 4263 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().
04264 { 04265 char *copy = ast_strdupa(function); 04266 char *args = func_args(copy); 04267 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04268 04269 if (acfptr == NULL) { 04270 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04271 } else if (!acfptr->write) { 04272 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 04273 } else if (!is_write_allowed(acfptr)) { 04274 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy); 04275 } else { 04276 int res; 04277 struct ast_module_user *u = NULL; 04278 if (acfptr->mod) 04279 u = __ast_module_user_add(acfptr->mod, chan); 04280 res = acfptr->write(chan, copy, args, value); 04281 if (acfptr->mod && u) 04282 __ast_module_user_remove(acfptr->mod, u); 04283 return res; 04284 } 04285 04286 return -1; 04287 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 11073 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().
11074 { 11075 return con ? con->name : NULL; 11076 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 11111 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
11112 { 11113 return c ? c->registrar : NULL; 11114 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 11141 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().
11142 { 11143 return e ? e->app : NULL; 11144 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 11146 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().
11147 { 11148 return e ? e->data : NULL; 11149 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 11136 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
11137 { 11138 return e ? e->cidmatch : NULL; 11139 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 11078 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().
11079 { 11080 return exten ? exten->parent : NULL; 11081 }
const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 11088 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 11131 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
11132 { 11133 return e ? e->matchcid : 0; 11134 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 11083 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().
11084 { 11085 return exten ? exten->exten : NULL; 11086 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 11103 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().
11104 { 11105 return exten ? exten->priority : -1; 11106 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 11116 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11117 { 11118 return e ? e->registrar : NULL; 11119 }
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 5362 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().
05363 { 05364 struct ast_exten *e = ast_hint_extension(c, context, exten); 05365 05366 if (e) { 05367 if (hint) 05368 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05369 if (name) { 05370 const char *tmp = ast_get_extension_app_data(e); 05371 if (tmp) 05372 ast_copy_string(name, tmp, namesize); 05373 } 05374 return -1; 05375 } 05376 return 0; 05377 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 11098 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().
11099 { 11100 return ip ? ip->pattern : NULL; 11101 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 11126 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().
11127 { 11128 return ip ? ip->registrar : NULL; 11129 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 11093 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 11121 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().
11122 { 11123 return i ? i->registrar : NULL; 11124 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 11156 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().
11157 { 11158 return sw ? sw->data : NULL; 11159 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 11161 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
11162 { 11163 return sw->eval; 11164 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 11151 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().
11152 { 11153 return sw ? sw->name : NULL; 11154 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 11166 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().
11167 { 11168 return sw ? sw->registrar : NULL; 11169 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11261 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().
11262 { 11263 return __ast_goto_if_exists(chan, context, exten, priority, 0); 11264 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1136 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01137 { 01138 const struct ast_context *ac = ah_a; 01139 const struct ast_context *bc = ah_b; 01140 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01141 return 1; 01142 /* assume context names are registered in a string table! */ 01143 return strcmp(ac->name, bc->name); 01144 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1188 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().
01189 { 01190 const struct ast_context *ac = obj; 01191 return ast_hashtab_hash_string(ac->name); 01192 }
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 8650 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().
08651 { 08652 struct ast_context *con = ast_context_find(context); 08653 08654 if (con) { 08655 struct ast_ignorepat *pat; 08656 08657 for (pat = con->ignorepats; pat; pat = pat->next) { 08658 if (ast_extension_match(pat->pattern, pattern)) 08659 return 1; 08660 } 08661 } 08662 08663 return 0; 08664 }
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 5420 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().
05421 { 05422 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05423 }
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 7937 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().
07938 { 07939 double ft; 07940 struct ast_context *tmp; 07941 struct ast_context *oldcontextslist; 07942 struct ast_hashtab *oldtable; 07943 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07944 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07945 struct store_hint *saved_hint; 07946 struct ast_hint *hint; 07947 struct ast_exten *exten; 07948 int length; 07949 struct ast_state_cb *thiscb; 07950 struct ast_hashtab_iter *iter; 07951 struct ao2_iterator i; 07952 struct timeval begintime; 07953 struct timeval writelocktime; 07954 struct timeval endlocktime; 07955 struct timeval enddeltime; 07956 07957 /* 07958 * It is very important that this function hold the hints 07959 * container lock _and_ the conlock during its operation; not 07960 * only do we need to ensure that the list of contexts and 07961 * extensions does not change, but also that no hint callbacks 07962 * (watchers) are added or removed during the merge/delete 07963 * process 07964 * 07965 * In addition, the locks _must_ be taken in this order, because 07966 * there are already other code paths that use this order 07967 */ 07968 07969 begintime = ast_tvnow(); 07970 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07971 ast_wrlock_contexts(); 07972 07973 if (!contexts_table) { 07974 /* Well, that's odd. There are no contexts. */ 07975 contexts_table = exttable; 07976 contexts = *extcontexts; 07977 ast_unlock_contexts(); 07978 ast_mutex_unlock(&context_merge_lock); 07979 return; 07980 } 07981 07982 iter = ast_hashtab_start_traversal(contexts_table); 07983 while ((tmp = ast_hashtab_next(iter))) { 07984 context_merge(extcontexts, exttable, tmp, registrar); 07985 } 07986 ast_hashtab_end_traversal(iter); 07987 07988 ao2_lock(hints); 07989 writelocktime = ast_tvnow(); 07990 07991 /* preserve all watchers for hints */ 07992 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07993 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07994 if (ao2_container_count(hint->callbacks)) { 07995 ao2_lock(hint); 07996 if (!hint->exten) { 07997 /* The extension has already been destroyed. (Should never happen here) */ 07998 ao2_unlock(hint); 07999 continue; 08000 } 08001 08002 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 08003 + sizeof(*saved_hint); 08004 if (!(saved_hint = ast_calloc(1, length))) { 08005 ao2_unlock(hint); 08006 continue; 08007 } 08008 08009 /* This removes all the callbacks from the hint into saved_hint. */ 08010 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 08011 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 08012 /* 08013 * We intentionally do not unref thiscb to account for the 08014 * non-ao2 reference in saved_hint->callbacks 08015 */ 08016 } 08017 08018 saved_hint->laststate = hint->laststate; 08019 saved_hint->context = saved_hint->data; 08020 strcpy(saved_hint->data, hint->exten->parent->name); 08021 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 08022 strcpy(saved_hint->exten, hint->exten->exten); 08023 ao2_unlock(hint); 08024 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 08025 } 08026 } 08027 ao2_iterator_destroy(&i); 08028 08029 /* save the old table and list */ 08030 oldtable = contexts_table; 08031 oldcontextslist = contexts; 08032 08033 /* move in the new table and list */ 08034 contexts_table = exttable; 08035 contexts = *extcontexts; 08036 08037 /* 08038 * Restore the watchers for hints that can be found; notify 08039 * those that cannot be restored. 08040 */ 08041 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 08042 struct pbx_find_info q = { .stacklen = 0 }; 08043 08044 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 08045 PRIORITY_HINT, NULL, "", E_MATCH); 08046 /* 08047 * If this is a pattern, dynamically create a new extension for this 08048 * particular match. Note that this will only happen once for each 08049 * individual extension, because the pattern will no longer match first. 08050 */ 08051 if (exten && exten->exten[0] == '_') { 08052 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 08053 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 08054 exten->registrar); 08055 /* rwlocks are not recursive locks */ 08056 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 08057 saved_hint->exten); 08058 } 08059 08060 /* Find the hint in the hints container */ 08061 hint = exten ? ao2_find(hints, exten, 0) : NULL; 08062 if (!hint) { 08063 /* 08064 * Notify watchers of this removed hint later when we aren't 08065 * encumberd by so many locks. 08066 */ 08067 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 08068 } else { 08069 ao2_lock(hint); 08070 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08071 ao2_link(hint->callbacks, thiscb); 08072 /* Ref that we added when putting into saved_hint->callbacks */ 08073 ao2_ref(thiscb, -1); 08074 } 08075 hint->laststate = saved_hint->laststate; 08076 ao2_unlock(hint); 08077 ao2_ref(hint, -1); 08078 ast_free(saved_hint); 08079 } 08080 } 08081 08082 ao2_unlock(hints); 08083 ast_unlock_contexts(); 08084 08085 /* 08086 * Notify watchers of all removed hints with the same lock 08087 * environment as handle_statechange(). 08088 */ 08089 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 08090 /* this hint has been removed, notify the watchers */ 08091 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08092 thiscb->change_cb(saved_hint->context, saved_hint->exten, 08093 AST_EXTENSION_REMOVED, thiscb->data); 08094 /* Ref that we added when putting into saved_hint->callbacks */ 08095 ao2_ref(thiscb, -1); 08096 } 08097 ast_free(saved_hint); 08098 } 08099 08100 ast_mutex_unlock(&context_merge_lock); 08101 endlocktime = ast_tvnow(); 08102 08103 /* 08104 * The old list and hashtab no longer are relevant, delete them 08105 * while the rest of asterisk is now freely using the new stuff 08106 * instead. 08107 */ 08108 08109 ast_hashtab_destroy(oldtable, NULL); 08110 08111 for (tmp = oldcontextslist; tmp; ) { 08112 struct ast_context *next; /* next starting point */ 08113 08114 next = tmp->next; 08115 __ast_internal_context_destroy(tmp); 08116 tmp = next; 08117 } 08118 enddeltime = ast_tvnow(); 08119 08120 ft = ast_tvdiff_us(writelocktime, begintime); 08121 ft /= 1000000.0; 08122 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 08123 08124 ft = ast_tvdiff_us(endlocktime, writelocktime); 08125 ft /= 1000000.0; 08126 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 08127 08128 ft = ast_tvdiff_us(enddeltime, endlocktime); 08129 ft /= 1000000.0; 08130 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 08131 08132 ft = ast_tvdiff_us(enddeltime, begintime); 08133 ft /= 1000000.0; 08134 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 08135 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11326 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().
11327 { 11328 return pbx_parseable_goto(chan, goto_string, 0); 11329 }
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 9544 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().
09545 { 09546 struct ast_channel *chan; 09547 struct app_tmp *tmp; 09548 int res = -1, cdr_res = -1; 09549 struct outgoing_helper oh; 09550 09551 memset(&oh, 0, sizeof(oh)); 09552 oh.vars = vars; 09553 oh.account = account; 09554 09555 if (locked_channel) 09556 *locked_channel = NULL; 09557 if (ast_strlen_zero(app)) { 09558 res = -1; 09559 goto outgoing_app_cleanup; 09560 } 09561 if (synchronous) { 09562 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09563 if (chan) { 09564 ast_set_variables(chan, vars); 09565 if (account) 09566 ast_cdr_setaccount(chan, account); 09567 if (chan->_state == AST_STATE_UP) { 09568 res = 0; 09569 ast_verb(4, "Channel %s was answered.\n", chan->name); 09570 tmp = ast_calloc(1, sizeof(*tmp)); 09571 if (!tmp || ast_string_field_init(tmp, 252)) { 09572 if (tmp) { 09573 ast_free(tmp); 09574 } 09575 res = -1; 09576 } else { 09577 ast_string_field_set(tmp, app, app); 09578 ast_string_field_set(tmp, data, appdata); 09579 tmp->chan = chan; 09580 if (synchronous > 1) { 09581 if (locked_channel) 09582 ast_channel_unlock(chan); 09583 ast_pbx_run_app(tmp); 09584 } else { 09585 if (locked_channel) 09586 ast_channel_lock(chan); 09587 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09588 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09589 ast_string_field_free_memory(tmp); 09590 ast_free(tmp); 09591 if (locked_channel) 09592 ast_channel_unlock(chan); 09593 ast_hangup(chan); 09594 res = -1; 09595 } else { 09596 if (locked_channel) 09597 *locked_channel = chan; 09598 } 09599 } 09600 } 09601 } else { 09602 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09603 if (chan->cdr) { /* update the cdr */ 09604 /* here we update the status of the call, which sould be busy. 09605 * if that fails then we set the status to failed */ 09606 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09607 ast_cdr_failed(chan->cdr); 09608 } 09609 ast_hangup(chan); 09610 } 09611 } 09612 09613 if (res < 0) { /* the call failed for some reason */ 09614 if (*reason == 0) { /* if the call failed (not busy or no answer) 09615 * update the cdr with the failed message */ 09616 cdr_res = ast_pbx_outgoing_cdr_failed(); 09617 if (cdr_res != 0) { 09618 res = cdr_res; 09619 goto outgoing_app_cleanup; 09620 } 09621 } 09622 } 09623 09624 } else { 09625 struct async_stat *as; 09626 if (!(as = ast_calloc(1, sizeof(*as)))) { 09627 res = -1; 09628 goto outgoing_app_cleanup; 09629 } 09630 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09631 if (!chan) { 09632 ast_free(as); 09633 res = -1; 09634 goto outgoing_app_cleanup; 09635 } 09636 as->chan = chan; 09637 ast_copy_string(as->app, app, sizeof(as->app)); 09638 if (appdata) 09639 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09640 as->timeout = timeout; 09641 ast_set_variables(chan, vars); 09642 if (account) 09643 ast_cdr_setaccount(chan, account); 09644 /* Start a new thread, and get something handling this channel. */ 09645 if (locked_channel) 09646 ast_channel_lock(chan); 09647 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09648 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09649 ast_free(as); 09650 if (locked_channel) 09651 ast_channel_unlock(chan); 09652 ast_hangup(chan); 09653 res = -1; 09654 goto outgoing_app_cleanup; 09655 } else { 09656 if (locked_channel) 09657 *locked_channel = chan; 09658 } 09659 res = 0; 09660 } 09661 outgoing_app_cleanup: 09662 ast_variables_destroy(vars); 09663 return res; 09664 }
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 9375 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().
09376 { 09377 struct ast_channel *chan; 09378 struct async_stat *as; 09379 int res = -1, cdr_res = -1; 09380 struct outgoing_helper oh; 09381 09382 if (synchronous) { 09383 oh.context = context; 09384 oh.exten = exten; 09385 oh.priority = priority; 09386 oh.cid_num = cid_num; 09387 oh.cid_name = cid_name; 09388 oh.account = account; 09389 oh.vars = vars; 09390 oh.parent_channel = NULL; 09391 09392 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09393 if (channel) { 09394 *channel = chan; 09395 if (chan) 09396 ast_channel_lock(chan); 09397 } 09398 if (chan) { 09399 if (chan->_state == AST_STATE_UP) { 09400 res = 0; 09401 ast_verb(4, "Channel %s was answered.\n", chan->name); 09402 09403 if (synchronous > 1) { 09404 if (channel) 09405 ast_channel_unlock(chan); 09406 if (ast_pbx_run(chan)) { 09407 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09408 if (channel) 09409 *channel = NULL; 09410 ast_hangup(chan); 09411 chan = NULL; 09412 res = -1; 09413 } 09414 } else { 09415 if (ast_pbx_start(chan)) { 09416 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09417 if (channel) { 09418 *channel = NULL; 09419 ast_channel_unlock(chan); 09420 } 09421 ast_hangup(chan); 09422 res = -1; 09423 } 09424 chan = NULL; 09425 } 09426 } else { 09427 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09428 09429 if (chan->cdr) { /* update the cdr */ 09430 /* here we update the status of the call, which sould be busy. 09431 * if that fails then we set the status to failed */ 09432 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09433 ast_cdr_failed(chan->cdr); 09434 } 09435 09436 if (channel) { 09437 *channel = NULL; 09438 ast_channel_unlock(chan); 09439 } 09440 ast_hangup(chan); 09441 chan = NULL; 09442 } 09443 } 09444 09445 if (res < 0) { /* the call failed for some reason */ 09446 if (*reason == 0) { /* if the call failed (not busy or no answer) 09447 * update the cdr with the failed message */ 09448 cdr_res = ast_pbx_outgoing_cdr_failed(); 09449 if (cdr_res != 0) { 09450 res = cdr_res; 09451 goto outgoing_exten_cleanup; 09452 } 09453 } 09454 09455 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09456 /* check if "failed" exists */ 09457 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09458 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09459 if (chan) { 09460 char failed_reason[4] = ""; 09461 if (!ast_strlen_zero(context)) 09462 ast_copy_string(chan->context, context, sizeof(chan->context)); 09463 set_ext_pri(chan, "failed", 1); 09464 ast_set_variables(chan, vars); 09465 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09466 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09467 if (account) 09468 ast_cdr_setaccount(chan, account); 09469 if (ast_pbx_run(chan)) { 09470 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09471 ast_hangup(chan); 09472 } 09473 chan = NULL; 09474 } 09475 } 09476 } 09477 } else { 09478 if (!(as = ast_calloc(1, sizeof(*as)))) { 09479 res = -1; 09480 goto outgoing_exten_cleanup; 09481 } 09482 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09483 if (channel) { 09484 *channel = chan; 09485 if (chan) 09486 ast_channel_lock(chan); 09487 } 09488 if (!chan) { 09489 ast_free(as); 09490 res = -1; 09491 goto outgoing_exten_cleanup; 09492 } 09493 as->chan = chan; 09494 ast_copy_string(as->context, context, sizeof(as->context)); 09495 set_ext_pri(as->chan, exten, priority); 09496 as->timeout = timeout; 09497 ast_set_variables(chan, vars); 09498 if (account) 09499 ast_cdr_setaccount(chan, account); 09500 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09501 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09502 ast_free(as); 09503 if (channel) { 09504 *channel = NULL; 09505 ast_channel_unlock(chan); 09506 } 09507 ast_hangup(chan); 09508 res = -1; 09509 goto outgoing_exten_cleanup; 09510 } 09511 res = 0; 09512 } 09513 outgoing_exten_cleanup: 09514 ast_variables_destroy(vars); 09515 return res; 09516 }
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 5926 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().
05927 { 05928 return ast_pbx_run_args(c, NULL); 05929 }
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 5906 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().
05907 { 05908 enum ast_pbx_result res = AST_PBX_SUCCESS; 05909 05910 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05911 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05912 return AST_PBX_FAILED; 05913 } 05914 05915 if (increase_call_count(c)) { 05916 return AST_PBX_CALL_LIMIT; 05917 } 05918 05919 res = __ast_pbx_run(c, args); 05920 05921 decrease_call_count(); 05922 05923 return res; 05924 }
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 5879 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().
05880 { 05881 pthread_t t; 05882 05883 if (!c) { 05884 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05885 return AST_PBX_FAILED; 05886 } 05887 05888 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05889 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05890 return AST_PBX_FAILED; 05891 } 05892 05893 if (increase_call_count(c)) 05894 return AST_PBX_CALL_LIMIT; 05895 05896 /* Start a new thread, and get something handling this channel. */ 05897 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05898 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05899 decrease_call_count(); 05900 return AST_PBX_FAILED; 05901 } 05902 05903 return AST_PBX_SUCCESS; 05904 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5936 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05937 { 05938 return totalcalls; 05939 }
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 11060 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().
11061 { 11062 return ast_rwlock_rdlock(&con->lock); 11063 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 11042 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().
11043 { 11044 return ast_mutex_lock(&conlock); 11045 }
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 6439 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().
06440 { 06441 struct ast_switch *tmp; 06442 06443 AST_RWLIST_WRLOCK(&switches); 06444 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06445 if (!strcasecmp(tmp->name, sw->name)) { 06446 AST_RWLIST_UNLOCK(&switches); 06447 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06448 return -1; 06449 } 06450 } 06451 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06452 AST_RWLIST_UNLOCK(&switches); 06453 06454 return 0; 06455 }
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 5425 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), gosub_run(), and loopback_exec().
05426 { 05427 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05428 }
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 5380 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().
05381 { 05382 struct ast_exten *e = ast_hint_extension(c, context, exten); 05383 05384 if (!e) { 05385 return 0; 05386 } 05387 05388 if (hint) { 05389 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05390 } 05391 if (name) { 05392 const char *tmp = ast_get_extension_app_data(e); 05393 if (tmp) { 05394 ast_str_set(name, namesize, "%s", tmp); 05395 } 05396 } 05397 return -1; 05398 }
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 3445 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().
03446 { 03447 const char not_found = '\0'; 03448 char *tmpvar; 03449 const char *ret; 03450 const char *s; /* the result */ 03451 int offset, length; 03452 int i, need_substring; 03453 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03454 char workspace[20]; 03455 03456 if (c) { 03457 ast_channel_lock(c); 03458 places[0] = &c->varshead; 03459 } 03460 /* 03461 * Make a copy of var because parse_variable_name() modifies the string. 03462 * Then if called directly, we might need to run substring() on the result; 03463 * remember this for later in 'need_substring', 'offset' and 'length' 03464 */ 03465 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03466 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03467 03468 /* 03469 * Look first into predefined variables, then into variable lists. 03470 * Variable 's' points to the result, according to the following rules: 03471 * s == ¬_found (set at the beginning) means that we did not find a 03472 * matching variable and need to look into more places. 03473 * If s != ¬_found, s is a valid result string as follows: 03474 * s = NULL if the variable does not have a value; 03475 * you typically do this when looking for an unset predefined variable. 03476 * s = workspace if the result has been assembled there; 03477 * typically done when the result is built e.g. with an snprintf(), 03478 * so we don't need to do an additional copy. 03479 * s != workspace in case we have a string, that needs to be copied 03480 * (the ast_copy_string is done once for all at the end). 03481 * Typically done when the result is already available in some string. 03482 */ 03483 s = ¬_found; /* default value */ 03484 if (c) { /* This group requires a valid channel */ 03485 /* Names with common parts are looked up a piece at a time using strncmp. */ 03486 if (!strncmp(var, "CALL", 4)) { 03487 if (!strncmp(var + 4, "ING", 3)) { 03488 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03489 ast_str_set(str, maxlen, "%d", 03490 ast_party_id_presentation(&c->caller.id)); 03491 s = ast_str_buffer(*str); 03492 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03493 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03494 s = ast_str_buffer(*str); 03495 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03496 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03497 s = ast_str_buffer(*str); 03498 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03499 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03500 s = ast_str_buffer(*str); 03501 } 03502 } 03503 } else if (!strcmp(var, "HINT")) { 03504 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03505 } else if (!strcmp(var, "HINTNAME")) { 03506 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03507 } else if (!strcmp(var, "EXTEN")) { 03508 s = c->exten; 03509 } else if (!strcmp(var, "CONTEXT")) { 03510 s = c->context; 03511 } else if (!strcmp(var, "PRIORITY")) { 03512 ast_str_set(str, maxlen, "%d", c->priority); 03513 s = ast_str_buffer(*str); 03514 } else if (!strcmp(var, "CHANNEL")) { 03515 s = c->name; 03516 } else if (!strcmp(var, "UNIQUEID")) { 03517 s = c->uniqueid; 03518 } else if (!strcmp(var, "HANGUPCAUSE")) { 03519 ast_str_set(str, maxlen, "%d", c->hangupcause); 03520 s = ast_str_buffer(*str); 03521 } 03522 } 03523 if (s == ¬_found) { /* look for more */ 03524 if (!strcmp(var, "EPOCH")) { 03525 ast_str_set(str, maxlen, "%d", (int) time(NULL)); 03526 s = ast_str_buffer(*str); 03527 } else if (!strcmp(var, "SYSTEMNAME")) { 03528 s = ast_config_AST_SYSTEM_NAME; 03529 } else if (!strcmp(var, "ENTITYID")) { 03530 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03531 s = workspace; 03532 } 03533 } 03534 /* if not found, look into chanvars or global vars */ 03535 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03536 struct ast_var_t *variables; 03537 if (!places[i]) 03538 continue; 03539 if (places[i] == &globals) 03540 ast_rwlock_rdlock(&globalslock); 03541 AST_LIST_TRAVERSE(places[i], variables, entries) { 03542 if (!strcasecmp(ast_var_name(variables), var)) { 03543 s = ast_var_value(variables); 03544 break; 03545 } 03546 } 03547 if (places[i] == &globals) 03548 ast_rwlock_unlock(&globalslock); 03549 } 03550 if (s == ¬_found || s == NULL) { 03551 ast_debug(5, "Result of '%s' is NULL\n", var); 03552 ret = NULL; 03553 } else { 03554 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03555 if (s != ast_str_buffer(*str)) { 03556 ast_str_set(str, maxlen, "%s", s); 03557 } 03558 ret = ast_str_buffer(*str); 03559 if (need_substring) { 03560 ret = ast_str_substring(*str, offset, length); 03561 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03562 } 03563 } 03564 03565 if (c) { 03566 ast_channel_unlock(c); 03567 } 03568 return ret; 03569 }
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 4468 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().
04469 { 04470 size_t used; 04471 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04472 }
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 4289 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().
04290 { 04291 /* Substitutes variables into buf, based on string templ */ 04292 char *cp4 = NULL; 04293 const char *tmp, *whereweare; 04294 int orig_size = 0; 04295 int offset, offset2, isfunction; 04296 const char *nextvar, *nextexp, *nextthing; 04297 const char *vars, *vare; 04298 char *finalvars; 04299 int pos, brackets, needsub, len; 04300 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04301 04302 ast_str_reset(*buf); 04303 whereweare = tmp = templ; 04304 while (!ast_strlen_zero(whereweare)) { 04305 /* reset our buffer */ 04306 ast_str_reset(substr3); 04307 04308 /* Assume we're copying the whole remaining string */ 04309 pos = strlen(whereweare); 04310 nextvar = NULL; 04311 nextexp = NULL; 04312 nextthing = strchr(whereweare, '$'); 04313 if (nextthing) { 04314 switch (nextthing[1]) { 04315 case '{': 04316 nextvar = nextthing; 04317 pos = nextvar - whereweare; 04318 break; 04319 case '[': 04320 nextexp = nextthing; 04321 pos = nextexp - whereweare; 04322 break; 04323 default: 04324 pos = 1; 04325 } 04326 } 04327 04328 if (pos) { 04329 /* Copy that many bytes */ 04330 ast_str_append_substr(buf, maxlen, whereweare, pos); 04331 04332 templ += pos; 04333 whereweare += pos; 04334 } 04335 04336 if (nextvar) { 04337 /* We have a variable. Find the start and end, and determine 04338 if we are going to have to recursively call ourselves on the 04339 contents */ 04340 vars = vare = nextvar + 2; 04341 brackets = 1; 04342 needsub = 0; 04343 04344 /* Find the end of it */ 04345 while (brackets && *vare) { 04346 if ((vare[0] == '$') && (vare[1] == '{')) { 04347 needsub++; 04348 } else if (vare[0] == '{') { 04349 brackets++; 04350 } else if (vare[0] == '}') { 04351 brackets--; 04352 } else if ((vare[0] == '$') && (vare[1] == '[')) 04353 needsub++; 04354 vare++; 04355 } 04356 if (brackets) 04357 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04358 len = vare - vars - 1; 04359 04360 /* Skip totally over variable string */ 04361 whereweare += (len + 3); 04362 04363 /* Store variable name (and truncate) */ 04364 ast_str_set_substr(&substr1, 0, vars, len); 04365 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04366 04367 /* Substitute if necessary */ 04368 if (needsub) { 04369 size_t used; 04370 if (!substr2) { 04371 substr2 = ast_str_create(16); 04372 } 04373 04374 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04375 finalvars = ast_str_buffer(substr2); 04376 } else { 04377 finalvars = ast_str_buffer(substr1); 04378 } 04379 04380 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04381 if (isfunction) { 04382 /* Evaluate function */ 04383 if (c || !headp) { 04384 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04385 } else { 04386 struct varshead old; 04387 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04388 if (bogus) { 04389 memcpy(&old, &bogus->varshead, sizeof(old)); 04390 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04391 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04392 /* Don't deallocate the varshead that was passed in */ 04393 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04394 ast_channel_unref(bogus); 04395 } else { 04396 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04397 } 04398 } 04399 ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)"); 04400 } else { 04401 /* Retrieve variable value */ 04402 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04403 cp4 = ast_str_buffer(substr3); 04404 } 04405 if (cp4) { 04406 ast_str_substring(substr3, offset, offset2); 04407 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04408 } 04409 } else if (nextexp) { 04410 /* We have an expression. Find the start and end, and determine 04411 if we are going to have to recursively call ourselves on the 04412 contents */ 04413 vars = vare = nextexp + 2; 04414 brackets = 1; 04415 needsub = 0; 04416 04417 /* Find the end of it */ 04418 while (brackets && *vare) { 04419 if ((vare[0] == '$') && (vare[1] == '[')) { 04420 needsub++; 04421 brackets++; 04422 vare++; 04423 } else if (vare[0] == '[') { 04424 brackets++; 04425 } else if (vare[0] == ']') { 04426 brackets--; 04427 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04428 needsub++; 04429 vare++; 04430 } 04431 vare++; 04432 } 04433 if (brackets) 04434 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04435 len = vare - vars - 1; 04436 04437 /* Skip totally over expression */ 04438 whereweare += (len + 3); 04439 04440 /* Store variable name (and truncate) */ 04441 ast_str_set_substr(&substr1, 0, vars, len); 04442 04443 /* Substitute if necessary */ 04444 if (needsub) { 04445 size_t used; 04446 if (!substr2) { 04447 substr2 = ast_str_create(16); 04448 } 04449 04450 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04451 finalvars = ast_str_buffer(substr2); 04452 } else { 04453 finalvars = ast_str_buffer(substr1); 04454 } 04455 04456 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04457 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04458 } 04459 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04460 } 04461 } 04462 *used = ast_str_strlen(*buf) - orig_size; 04463 ast_free(substr1); 04464 ast_free(substr2); 04465 ast_free(substr3); 04466 }
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 4474 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().
04475 { 04476 size_t used; 04477 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04478 }
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 4072 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by handle_tcptls_connection().
04073 { 04074 int *thread_inhibit_escalations; 04075 04076 thread_inhibit_escalations = ast_threadstorage_get( 04077 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04078 04079 if (thread_inhibit_escalations == NULL) { 04080 ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n"); 04081 return -1; 04082 } 04083 04084 *thread_inhibit_escalations = 1; 04085 return 0; 04086 }
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 11065 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().
11066 { 11067 return ast_rwlock_unlock(&con->lock); 11068 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 11047 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().
11048 { 11049 return ast_mutex_unlock(&conlock); 11050 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6457 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06458 { 06459 AST_RWLIST_WRLOCK(&switches); 06460 AST_RWLIST_REMOVE(&switches, sw, list); 06461 AST_RWLIST_UNLOCK(&switches); 06462 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 11179 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 11212 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().
11214 { 11215 if (!ip) 11216 return con ? con->ignorepats : NULL; 11217 else 11218 return ip->next; 11219 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 11203 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 11188 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().
11190 { 11191 if (!sw) 11192 return con ? AST_LIST_FIRST(&con->alts) : NULL; 11193 else 11194 return AST_LIST_NEXT(sw, list); 11195 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 11174 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 11197 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().
11199 { 11200 return priority ? priority->peer : exten; 11201 }
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 11055 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().
11056 { 11057 return ast_rwlock_wrlock(&con->lock); 11058 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 11037 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().
11038 { 11039 return ast_mutex_lock(&conlock); 11040 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10709 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().
10710 { 10711 struct ast_var_t *vardata; 10712 10713 ast_rwlock_wrlock(&globalslock); 10714 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10715 ast_var_delete(vardata); 10716 ast_rwlock_unlock(&globalslock); 10717 }
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 10475 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), gosub_run(), handle_gosub(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_exec(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
10476 { 10477 struct ast_var_t *variables; 10478 const char *ret = NULL; 10479 int i; 10480 struct varshead *places[2] = { NULL, &globals }; 10481 10482 if (!name) 10483 return NULL; 10484 10485 if (chan) { 10486 ast_channel_lock(chan); 10487 places[0] = &chan->varshead; 10488 } 10489 10490 for (i = 0; i < 2; i++) { 10491 if (!places[i]) 10492 continue; 10493 if (places[i] == &globals) 10494 ast_rwlock_rdlock(&globalslock); 10495 AST_LIST_TRAVERSE(places[i], variables, entries) { 10496 if (!strcmp(name, ast_var_name(variables))) { 10497 ret = ast_var_value(variables); 10498 break; 10499 } 10500 } 10501 if (places[i] == &globals) 10502 ast_rwlock_unlock(&globalslock); 10503 if (ret) 10504 break; 10505 } 10506 10507 if (chan) 10508 ast_channel_unlock(chan); 10509 10510 return ret; 10511 }
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 10513 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().
10514 { 10515 struct ast_var_t *newvariable; 10516 struct varshead *headp; 10517 10518 if (name[strlen(name)-1] == ')') { 10519 char *function = ast_strdupa(name); 10520 10521 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10522 ast_func_write(chan, function, value); 10523 return; 10524 } 10525 10526 if (chan) { 10527 ast_channel_lock(chan); 10528 headp = &chan->varshead; 10529 } else { 10530 ast_rwlock_wrlock(&globalslock); 10531 headp = &globals; 10532 } 10533 10534 if (value && (newvariable = ast_var_assign(name, value))) { 10535 if (headp == &globals) 10536 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10537 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10538 } 10539 10540 if (chan) 10541 ast_channel_unlock(chan); 10542 else 10543 ast_rwlock_unlock(&globalslock); 10544 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Definition at line 3620 of file pbx.c.
References raise_exception().
03621 { 03622 /* Priority will become 1, next time through the AUTOLOOP */ 03623 return raise_exception(chan, reason, 0); 03624 }
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 10444 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().
10445 { 10446 struct ast_var_t *variables; 10447 const char *var, *val; 10448 int total = 0; 10449 10450 if (!chan) 10451 return 0; 10452 10453 ast_str_reset(*buf); 10454 10455 ast_channel_lock(chan); 10456 10457 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10458 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10459 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10460 ) { 10461 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10462 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10463 break; 10464 } else 10465 total++; 10466 } else 10467 break; 10468 } 10469 10470 ast_channel_unlock(chan); 10471 10472 return total; 10473 }
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 10603 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().
10604 { 10605 char *name, *value, *mydata; 10606 10607 if (ast_compat_app_set) { 10608 return pbx_builtin_setvar_multiple(chan, data); 10609 } 10610 10611 if (ast_strlen_zero(data)) { 10612 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10613 return 0; 10614 } 10615 10616 mydata = ast_strdupa(data); 10617 name = strsep(&mydata, "="); 10618 value = mydata; 10619 if (!value) { 10620 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10621 return 0; 10622 } 10623 10624 if (strchr(name, ' ')) { 10625 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10626 } 10627 10628 pbx_builtin_setvar_helper(chan, name, value); 10629 10630 return 0; 10631 }
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 10546 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), gosub_run(), handle_gosub(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_call_full(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_saydate(), pbx_builtin_saytime(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), ring_entry(), rollback_exec(), rotate_file(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
10547 { 10548 struct ast_var_t *newvariable; 10549 struct varshead *headp; 10550 const char *nametail = name; 10551 10552 if (name[strlen(name) - 1] == ')') { 10553 char *function = ast_strdupa(name); 10554 10555 return ast_func_write(chan, function, value); 10556 } 10557 10558 if (chan) { 10559 ast_channel_lock(chan); 10560 headp = &chan->varshead; 10561 } else { 10562 ast_rwlock_wrlock(&globalslock); 10563 headp = &globals; 10564 } 10565 10566 /* For comparison purposes, we have to strip leading underscores */ 10567 if (*nametail == '_') { 10568 nametail++; 10569 if (*nametail == '_') 10570 nametail++; 10571 } 10572 10573 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10574 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10575 /* there is already such a variable, delete it */ 10576 AST_LIST_REMOVE_CURRENT(entries); 10577 ast_var_delete(newvariable); 10578 break; 10579 } 10580 } 10581 AST_LIST_TRAVERSE_SAFE_END; 10582 10583 if (value && (newvariable = ast_var_assign(name, value))) { 10584 if (headp == &globals) 10585 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10586 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10587 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10588 "Channel: %s\r\n" 10589 "Variable: %s\r\n" 10590 "Value: %s\r\n" 10591 "Uniqueid: %s\r\n", 10592 chan ? chan->name : "none", name, value, 10593 chan ? chan->uniqueid : "none"); 10594 } 10595 10596 if (chan) 10597 ast_channel_unlock(chan); 10598 else 10599 ast_rwlock_unlock(&globalslock); 10600 return 0; 10601 }
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 10633 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().
10634 { 10635 char *data; 10636 int x; 10637 AST_DECLARE_APP_ARGS(args, 10638 AST_APP_ARG(pair)[24]; 10639 ); 10640 AST_DECLARE_APP_ARGS(pair, 10641 AST_APP_ARG(name); 10642 AST_APP_ARG(value); 10643 ); 10644 10645 if (ast_strlen_zero(vdata)) { 10646 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10647 return 0; 10648 } 10649 10650 data = ast_strdupa(vdata); 10651 AST_STANDARD_APP_ARGS(args, data); 10652 10653 for (x = 0; x < args.argc; x++) { 10654 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10655 if (pair.argc == 2) { 10656 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10657 if (strchr(pair.name, ' ')) 10658 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); 10659 } else if (!chan) { 10660 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10661 } else { 10662 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10663 } 10664 } 10665 10666 return 0; 10667 }
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 10719 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().
10720 { 10721 int res; 10722 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10723 return 0; 10724 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10725 return res; 10726 } else { /* Strings are true */ 10727 return 1; 10728 } 10729 }
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 1497 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_exec_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01500 { 01501 int res; 01502 struct ast_module_user *u = NULL; 01503 const char *saved_c_appl; 01504 const char *saved_c_data; 01505 01506 if (c->cdr && !ast_check_hangup(c)) 01507 ast_cdr_setapp(c->cdr, app->name, data); 01508 01509 /* save channel values */ 01510 saved_c_appl= c->appl; 01511 saved_c_data= c->data; 01512 01513 c->appl = app->name; 01514 c->data = data; 01515 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01516 01517 if (app->module) 01518 u = __ast_module_user_add(app->module, c); 01519 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01520 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01521 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01522 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01523 app->name, (char *) data); 01524 } 01525 res = app->execute(c, S_OR(data, "")); 01526 if (app->module && u) 01527 __ast_module_user_remove(app->module, u); 01528 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01529 /* restore channel values */ 01530 c->appl = saved_c_appl; 01531 c->data = saved_c_data; 01532 return res; 01533 }
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 3013 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().
03017 { 03018 int x, res; 03019 struct ast_context *tmp = NULL; 03020 struct ast_exten *e = NULL, *eroot = NULL; 03021 struct ast_include *i = NULL; 03022 struct ast_sw *sw = NULL; 03023 struct ast_exten pattern = {NULL, }; 03024 struct scoreboard score = {0, }; 03025 struct ast_str *tmpdata = NULL; 03026 03027 pattern.label = label; 03028 pattern.priority = priority; 03029 #ifdef NEED_DEBUG_HERE 03030 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 03031 #endif 03032 03033 /* Initialize status if appropriate */ 03034 if (q->stacklen == 0) { 03035 q->status = STATUS_NO_CONTEXT; 03036 q->swo = NULL; 03037 q->data = NULL; 03038 q->foundcontext = NULL; 03039 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 03040 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 03041 return NULL; 03042 } 03043 03044 /* Check first to see if we've already been checked */ 03045 for (x = 0; x < q->stacklen; x++) { 03046 if (!strcasecmp(q->incstack[x], context)) 03047 return NULL; 03048 } 03049 03050 if (bypass) { /* bypass means we only look there */ 03051 tmp = bypass; 03052 } else { /* look in contexts */ 03053 tmp = find_context(context); 03054 if (!tmp) { 03055 return NULL; 03056 } 03057 } 03058 03059 if (q->status < STATUS_NO_EXTENSION) 03060 q->status = STATUS_NO_EXTENSION; 03061 03062 /* Do a search for matching extension */ 03063 03064 eroot = NULL; 03065 score.total_specificity = 0; 03066 score.exten = 0; 03067 score.total_length = 0; 03068 if (!tmp->pattern_tree && tmp->root_table) { 03069 create_match_char_tree(tmp); 03070 #ifdef NEED_DEBUG 03071 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 03072 log_match_char_tree(tmp->pattern_tree," "); 03073 #endif 03074 } 03075 #ifdef NEED_DEBUG 03076 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03077 log_match_char_tree(tmp->pattern_tree, ":: "); 03078 #endif 03079 03080 do { 03081 if (!ast_strlen_zero(overrideswitch)) { 03082 char *osw = ast_strdupa(overrideswitch), *name; 03083 struct ast_switch *asw; 03084 ast_switch_f *aswf = NULL; 03085 char *datap; 03086 int eval = 0; 03087 03088 name = strsep(&osw, "/"); 03089 asw = pbx_findswitch(name); 03090 03091 if (!asw) { 03092 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03093 break; 03094 } 03095 03096 if (osw && strchr(osw, '$')) { 03097 eval = 1; 03098 } 03099 03100 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03101 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03102 break; 03103 } else if (eval) { 03104 /* Substitute variables now */ 03105 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03106 datap = ast_str_buffer(tmpdata); 03107 } else { 03108 datap = osw; 03109 } 03110 03111 /* equivalent of extension_match_core() at the switch level */ 03112 if (action == E_CANMATCH) 03113 aswf = asw->canmatch; 03114 else if (action == E_MATCHMORE) 03115 aswf = asw->matchmore; 03116 else /* action == E_MATCH */ 03117 aswf = asw->exists; 03118 if (!aswf) { 03119 res = 0; 03120 } else { 03121 if (chan) { 03122 ast_autoservice_start(chan); 03123 } 03124 res = aswf(chan, context, exten, priority, callerid, datap); 03125 if (chan) { 03126 ast_autoservice_stop(chan); 03127 } 03128 } 03129 if (res) { /* Got a match */ 03130 q->swo = asw; 03131 q->data = datap; 03132 q->foundcontext = context; 03133 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03134 return NULL; 03135 } 03136 } 03137 } while (0); 03138 03139 if (extenpatternmatchnew) { 03140 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03141 eroot = score.exten; 03142 03143 if (score.last_char == '!' && action == E_MATCHMORE) { 03144 /* We match an extension ending in '!'. 03145 * The decision in this case is final and is NULL (no match). 03146 */ 03147 #ifdef NEED_DEBUG_HERE 03148 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03149 #endif 03150 return NULL; 03151 } 03152 03153 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03154 q->status = STATUS_SUCCESS; 03155 #ifdef NEED_DEBUG_HERE 03156 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03157 #endif 03158 return score.canmatch_exten; 03159 } 03160 03161 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03162 if (score.node) { 03163 struct ast_exten *z = trie_find_next_match(score.node); 03164 if (z) { 03165 #ifdef NEED_DEBUG_HERE 03166 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03167 #endif 03168 } else { 03169 if (score.canmatch_exten) { 03170 #ifdef NEED_DEBUG_HERE 03171 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03172 #endif 03173 return score.canmatch_exten; 03174 } else { 03175 #ifdef NEED_DEBUG_HERE 03176 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03177 #endif 03178 } 03179 } 03180 return z; 03181 } 03182 #ifdef NEED_DEBUG_HERE 03183 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03184 #endif 03185 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03186 } 03187 03188 if (eroot) { 03189 /* found entry, now look for the right priority */ 03190 if (q->status < STATUS_NO_PRIORITY) 03191 q->status = STATUS_NO_PRIORITY; 03192 e = NULL; 03193 if (action == E_FINDLABEL && label ) { 03194 if (q->status < STATUS_NO_LABEL) 03195 q->status = STATUS_NO_LABEL; 03196 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03197 } else { 03198 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03199 } 03200 if (e) { /* found a valid match */ 03201 q->status = STATUS_SUCCESS; 03202 q->foundcontext = context; 03203 #ifdef NEED_DEBUG_HERE 03204 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03205 #endif 03206 return e; 03207 } 03208 } 03209 } else { /* the old/current default exten pattern match algorithm */ 03210 03211 /* scan the list trying to match extension and CID */ 03212 eroot = NULL; 03213 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03214 int match = extension_match_core(eroot->exten, exten, action); 03215 /* 0 on fail, 1 on match, 2 on earlymatch */ 03216 03217 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03218 continue; /* keep trying */ 03219 if (match == 2 && action == E_MATCHMORE) { 03220 /* We match an extension ending in '!'. 03221 * The decision in this case is final and is NULL (no match). 03222 */ 03223 return NULL; 03224 } 03225 /* found entry, now look for the right priority */ 03226 if (q->status < STATUS_NO_PRIORITY) 03227 q->status = STATUS_NO_PRIORITY; 03228 e = NULL; 03229 if (action == E_FINDLABEL && label ) { 03230 if (q->status < STATUS_NO_LABEL) 03231 q->status = STATUS_NO_LABEL; 03232 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03233 } else { 03234 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03235 } 03236 if (e) { /* found a valid match */ 03237 q->status = STATUS_SUCCESS; 03238 q->foundcontext = context; 03239 return e; 03240 } 03241 } 03242 } 03243 03244 /* Check alternative switches */ 03245 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03246 struct ast_switch *asw = pbx_findswitch(sw->name); 03247 ast_switch_f *aswf = NULL; 03248 char *datap; 03249 03250 if (!asw) { 03251 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03252 continue; 03253 } 03254 03255 /* Substitute variables now */ 03256 if (sw->eval) { 03257 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03258 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03259 continue; 03260 } 03261 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03262 } 03263 03264 /* equivalent of extension_match_core() at the switch level */ 03265 if (action == E_CANMATCH) 03266 aswf = asw->canmatch; 03267 else if (action == E_MATCHMORE) 03268 aswf = asw->matchmore; 03269 else /* action == E_MATCH */ 03270 aswf = asw->exists; 03271 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03272 if (!aswf) 03273 res = 0; 03274 else { 03275 if (chan) 03276 ast_autoservice_start(chan); 03277 res = aswf(chan, context, exten, priority, callerid, datap); 03278 if (chan) 03279 ast_autoservice_stop(chan); 03280 } 03281 if (res) { /* Got a match */ 03282 q->swo = asw; 03283 q->data = datap; 03284 q->foundcontext = context; 03285 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03286 return NULL; 03287 } 03288 } 03289 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03290 /* Now try any includes we have in this context */ 03291 for (i = tmp->includes; i; i = i->next) { 03292 if (include_valid(i)) { 03293 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03294 #ifdef NEED_DEBUG_HERE 03295 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03296 #endif 03297 return e; 03298 } 03299 if (q->swo) 03300 return NULL; 03301 } 03302 } 03303 return NULL; 03304 }
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 1537 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_exec_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01538 { 01539 struct ast_app *tmp; 01540 01541 AST_RWLIST_RDLOCK(&apps); 01542 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01543 if (!strcasecmp(tmp->name, app)) 01544 break; 01545 } 01546 AST_RWLIST_UNLOCK(&apps); 01547 01548 return tmp; 01549 }
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 4059 of file pbx.c.
References ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by ast_readconfig().
04060 { 04061 if (new_live_dangerously && !live_dangerously) { 04062 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n" 04063 "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n"); 04064 } 04065 04066 if (!new_live_dangerously && live_dangerously) { 04067 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n"); 04068 } 04069 live_dangerously = new_live_dangerously; 04070 }
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 3434 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().
03435 { 03436 struct ast_str *str = ast_str_create(16); 03437 const char *cret; 03438 03439 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03440 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03441 *ret = cret ? workspace : NULL; 03442 ast_free(str); 03443 }
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 5941 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05942 { 05943 int oldval = autofallthrough; 05944 autofallthrough = newval; 05945 return oldval; 05946 }
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 5948 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05949 { 05950 int oldval = extenpatternmatchnew; 05951 extenpatternmatchnew = newval; 05952 return oldval; 05953 }
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 5955 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05956 { 05957 if (overrideswitch) { 05958 ast_free(overrideswitch); 05959 } 05960 if (!ast_strlen_zero(newval)) { 05961 overrideswitch = ast_strdup(newval); 05962 } else { 05963 overrideswitch = NULL; 05964 } 05965 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4676 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().
04677 { 04678 size_t used; 04679 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04680 }
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 4480 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().
04481 { 04482 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04483 char *cp4 = NULL; 04484 const char *tmp, *whereweare, *orig_cp2 = cp2; 04485 int length, offset, offset2, isfunction; 04486 char *workspace = NULL; 04487 char *ltmp = NULL, *var = NULL; 04488 char *nextvar, *nextexp, *nextthing; 04489 char *vars, *vare; 04490 int pos, brackets, needsub, len; 04491 04492 *cp2 = 0; /* just in case nothing ends up there */ 04493 whereweare=tmp=cp1; 04494 while (!ast_strlen_zero(whereweare) && count) { 04495 /* Assume we're copying the whole remaining string */ 04496 pos = strlen(whereweare); 04497 nextvar = NULL; 04498 nextexp = NULL; 04499 nextthing = strchr(whereweare, '$'); 04500 if (nextthing) { 04501 switch (nextthing[1]) { 04502 case '{': 04503 nextvar = nextthing; 04504 pos = nextvar - whereweare; 04505 break; 04506 case '[': 04507 nextexp = nextthing; 04508 pos = nextexp - whereweare; 04509 break; 04510 default: 04511 pos = 1; 04512 } 04513 } 04514 04515 if (pos) { 04516 /* Can't copy more than 'count' bytes */ 04517 if (pos > count) 04518 pos = count; 04519 04520 /* Copy that many bytes */ 04521 memcpy(cp2, whereweare, pos); 04522 04523 count -= pos; 04524 cp2 += pos; 04525 whereweare += pos; 04526 *cp2 = 0; 04527 } 04528 04529 if (nextvar) { 04530 /* We have a variable. Find the start and end, and determine 04531 if we are going to have to recursively call ourselves on the 04532 contents */ 04533 vars = vare = nextvar + 2; 04534 brackets = 1; 04535 needsub = 0; 04536 04537 /* Find the end of it */ 04538 while (brackets && *vare) { 04539 if ((vare[0] == '$') && (vare[1] == '{')) { 04540 needsub++; 04541 } else if (vare[0] == '{') { 04542 brackets++; 04543 } else if (vare[0] == '}') { 04544 brackets--; 04545 } else if ((vare[0] == '$') && (vare[1] == '[')) 04546 needsub++; 04547 vare++; 04548 } 04549 if (brackets) 04550 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04551 len = vare - vars - 1; 04552 04553 /* Skip totally over variable string */ 04554 whereweare += (len + 3); 04555 04556 if (!var) 04557 var = ast_alloca(VAR_BUF_SIZE); 04558 04559 /* Store variable name (and truncate) */ 04560 ast_copy_string(var, vars, len + 1); 04561 04562 /* Substitute if necessary */ 04563 if (needsub) { 04564 size_t used; 04565 if (!ltmp) 04566 ltmp = ast_alloca(VAR_BUF_SIZE); 04567 04568 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04569 vars = ltmp; 04570 } else { 04571 vars = var; 04572 } 04573 04574 if (!workspace) 04575 workspace = ast_alloca(VAR_BUF_SIZE); 04576 04577 workspace[0] = '\0'; 04578 04579 parse_variable_name(vars, &offset, &offset2, &isfunction); 04580 if (isfunction) { 04581 /* Evaluate function */ 04582 if (c || !headp) 04583 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04584 else { 04585 struct varshead old; 04586 struct ast_channel *c = ast_dummy_channel_alloc(); 04587 if (c) { 04588 memcpy(&old, &c->varshead, sizeof(old)); 04589 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04590 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04591 /* Don't deallocate the varshead that was passed in */ 04592 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04593 c = ast_channel_unref(c); 04594 } else { 04595 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04596 } 04597 } 04598 ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)"); 04599 } else { 04600 /* Retrieve variable value */ 04601 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04602 } 04603 if (cp4) { 04604 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04605 04606 length = strlen(cp4); 04607 if (length > count) 04608 length = count; 04609 memcpy(cp2, cp4, length); 04610 count -= length; 04611 cp2 += length; 04612 *cp2 = 0; 04613 } 04614 } else if (nextexp) { 04615 /* We have an expression. Find the start and end, and determine 04616 if we are going to have to recursively call ourselves on the 04617 contents */ 04618 vars = vare = nextexp + 2; 04619 brackets = 1; 04620 needsub = 0; 04621 04622 /* Find the end of it */ 04623 while (brackets && *vare) { 04624 if ((vare[0] == '$') && (vare[1] == '[')) { 04625 needsub++; 04626 brackets++; 04627 vare++; 04628 } else if (vare[0] == '[') { 04629 brackets++; 04630 } else if (vare[0] == ']') { 04631 brackets--; 04632 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04633 needsub++; 04634 vare++; 04635 } 04636 vare++; 04637 } 04638 if (brackets) 04639 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04640 len = vare - vars - 1; 04641 04642 /* Skip totally over expression */ 04643 whereweare += (len + 3); 04644 04645 if (!var) 04646 var = ast_alloca(VAR_BUF_SIZE); 04647 04648 /* Store variable name (and truncate) */ 04649 ast_copy_string(var, vars, len + 1); 04650 04651 /* Substitute if necessary */ 04652 if (needsub) { 04653 size_t used; 04654 if (!ltmp) 04655 ltmp = ast_alloca(VAR_BUF_SIZE); 04656 04657 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04658 vars = ltmp; 04659 } else { 04660 vars = var; 04661 } 04662 04663 length = ast_expr(vars, cp2, count, c); 04664 04665 if (length) { 04666 ast_debug(1, "Expression result is '%s'\n", cp2); 04667 count -= length; 04668 cp2 += length; 04669 *cp2 = 0; 04670 } 04671 } 04672 } 04673 *used = cp2 - orig_cp2; 04674 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4682 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04683 { 04684 size_t used; 04685 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04686 }