#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 |
#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) |
Functions for returning values from structures | |
const char * | ast_get_context_name (struct ast_context *con) |
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) |
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) |
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) |
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 ... | |
ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
ast_context * | ast_walk_contexts (struct ast_context *con) |
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) |
Defines | |
#define | ast_custom_function_register(acf) __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function. | |
#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_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 } |
Functions | |
int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
Register a custom function. | |
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). | |
ast_context * | ast_context_find (const char *name) |
Find a context. | |
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. | |
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_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. | |
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) |
ast_app * | pbx_findapp (const char *app) |
Look up an application. | |
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) |
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 1144 of file pbx.h.
Referenced by load_module(), and reload().
#define AST_MAX_APP 32 |
Max length of an application
Definition at line 39 of file pbx.h.
Referenced by destroy_station(), handle_show_function(), and print_app_docs().
#define AST_PBX_GOTO_FAILED -3 |
#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 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(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_space(), destroy_station(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), and print_ext().
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) |
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 289 of file pbx.h.
00289 { 00290 AST_PBX_SUCCESS = 0, 00291 AST_PBX_FAILED = -1, 00292 AST_PBX_CALL_LIMIT = -2, 00293 };
enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows.
Definition at line 1213 of file pbx.h.
01213 { 01214 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01215 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01216 E_MATCH = 0x02, /* extension is an exact match */ 01217 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01218 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01219 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01220 };
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3574 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 load_pbx().
03575 { 03576 struct ast_custom_function *cur; 03577 char tmps[80]; 03578 03579 if (!acf) { 03580 return -1; 03581 } 03582 03583 acf->mod = mod; 03584 #ifdef AST_XML_DOCS 03585 acf->docsrc = AST_STATIC_DOC; 03586 #endif 03587 03588 if (acf_retrieve_docs(acf)) { 03589 return -1; 03590 } 03591 03592 AST_RWLIST_WRLOCK(&acf_root); 03593 03594 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03595 if (!strcmp(acf->name, cur->name)) { 03596 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03597 AST_RWLIST_UNLOCK(&acf_root); 03598 return -1; 03599 } 03600 } 03601 03602 /* Store in alphabetical order */ 03603 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03604 if (strcasecmp(acf->name, cur->name) < 0) { 03605 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03606 break; 03607 } 03608 } 03609 AST_RWLIST_TRAVERSE_SAFE_END; 03610 03611 if (!cur) { 03612 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03613 } 03614 03615 AST_RWLIST_UNLOCK(&acf_root); 03616 03617 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03618 03619 return 0; 03620 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5387 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05388 { 05389 return countcalls; 05390 }
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 8112 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().
08115 { 08116 int ret = -1; 08117 struct ast_context *c; 08118 08119 c = find_context_locked(context); 08120 if (c) { 08121 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08122 application, data, datad, registrar); 08123 ast_unlock_contexts(); 08124 } 08125 08126 return ret; 08127 }
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 *.
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 8458 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), and pbx_load_users().
08462 { 08463 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08464 application, data, datad, registrar, 1); 08465 }
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 8152 of file pbx.c.
References ast_channel::_state, accountcode, ast_channel::accountcode, amaflags, ast_channel::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, ast_channel::linkedid, LOG_WARNING, ast_channel::name, 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().
08153 { 08154 int res = 0; 08155 struct ast_channel *tmpchan; 08156 struct { 08157 char *accountcode; 08158 char *exten; 08159 char *context; 08160 char *linkedid; 08161 char *name; 08162 struct ast_cdr *cdr; 08163 int amaflags; 08164 int state; 08165 format_t readformat; 08166 format_t writeformat; 08167 } tmpvars = { 0, }; 08168 08169 ast_channel_lock(chan); 08170 if (chan->pbx) { /* This channel is currently in the PBX */ 08171 ast_explicit_goto(chan, context, exten, priority + 1); 08172 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08173 ast_channel_unlock(chan); 08174 return res; 08175 } 08176 08177 /* In order to do it when the channel doesn't really exist within 08178 * the PBX, we have to make a new channel, masquerade, and start the PBX 08179 * at the new location */ 08180 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08181 tmpvars.exten = ast_strdupa(chan->exten); 08182 tmpvars.context = ast_strdupa(chan->context); 08183 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08184 tmpvars.name = ast_strdupa(chan->name); 08185 tmpvars.amaflags = chan->amaflags; 08186 tmpvars.state = chan->_state; 08187 tmpvars.writeformat = chan->writeformat; 08188 tmpvars.readformat = chan->readformat; 08189 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08190 08191 ast_channel_unlock(chan); 08192 08193 /* Do not hold any channel locks while calling channel_alloc() since the function 08194 * locks the channel container when linking the new channel in. */ 08195 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08196 ast_cdr_discard(tmpvars.cdr); 08197 return -1; 08198 } 08199 08200 /* copy the cdr info over */ 08201 if (tmpvars.cdr) { 08202 ast_cdr_discard(tmpchan->cdr); 08203 tmpchan->cdr = tmpvars.cdr; 08204 tmpvars.cdr = NULL; 08205 } 08206 08207 /* Make formats okay */ 08208 tmpchan->readformat = tmpvars.readformat; 08209 tmpchan->writeformat = tmpvars.writeformat; 08210 08211 /* Setup proper location. Never hold another channel lock while calling this function. */ 08212 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08213 08214 /* Masquerade into tmp channel */ 08215 if (ast_channel_masquerade(tmpchan, chan)) { 08216 /* Failed to set up the masquerade. It's probably chan_local 08217 * in the middle of optimizing itself out. Sad. :( */ 08218 ast_hangup(tmpchan); 08219 tmpchan = NULL; 08220 res = -1; 08221 } else { 08222 ast_do_masquerade(tmpchan); 08223 /* Start the PBX going on our stolen channel */ 08224 if (ast_pbx_start(tmpchan)) { 08225 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08226 ast_hangup(tmpchan); 08227 res = -1; 08228 } 08229 } 08230 08231 return res; 08232 }
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 8234 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08235 { 08236 struct ast_channel *chan; 08237 int res = -1; 08238 08239 if ((chan = ast_channel_get_by_name(channame))) { 08240 res = ast_async_goto(chan, context, exten, priority); 08241 chan = ast_channel_unref(chan); 08242 } 08243 08244 return res; 08245 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10547 of file pbx.c.
References __ast_goto_if_exists().
10548 { 10549 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10550 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10612 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10613 { 10614 return pbx_parseable_goto(chan, goto_string, 1); 10615 }
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 7736 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, strsep(), and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07737 { 07738 char *info; 07739 int j, num_fields, last_sep = -1; 07740 07741 /* Check for empty just in case */ 07742 if (ast_strlen_zero(info_in)) { 07743 return 0; 07744 } 07745 07746 /* make a copy just in case we were passed a static string */ 07747 info = ast_strdupa(info_in); 07748 07749 /* count the number of fields in the timespec */ 07750 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07751 if (info[j] == ',') { 07752 last_sep = j; 07753 num_fields++; 07754 } 07755 } 07756 07757 /* save the timezone, if it is specified */ 07758 if (num_fields == 5) { 07759 i->timezone = ast_strdup(info + last_sep + 1); 07760 } else { 07761 i->timezone = NULL; 07762 } 07763 07764 /* Assume everything except time */ 07765 i->monthmask = 0xfff; /* 12 bits */ 07766 i->daymask = 0x7fffffffU; /* 31 bits */ 07767 i->dowmask = 0x7f; /* 7 bits */ 07768 /* on each call, use strsep() to move info to the next argument */ 07769 get_timerange(i, strsep(&info, "|,")); 07770 if (info) 07771 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07772 if (info) 07773 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07774 if (info) 07775 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07776 return 1; 07777 }
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 4875 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(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
04876 { 04877 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04878 }
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 7779 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07780 { 07781 return ast_check_timing2(i, ast_tvnow()); 07782 }
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 7784 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().
07785 { 07786 struct ast_tm tm; 07787 07788 ast_localtime(&tv, &tm, i->timezone); 07789 07790 /* If it's not the right month, return */ 07791 if (!(i->monthmask & (1 << tm.tm_mon))) 07792 return 0; 07793 07794 /* If it's not that time of the month.... */ 07795 /* Warning, tm_mday has range 1..31! */ 07796 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07797 return 0; 07798 07799 /* If it's not the right day of the week */ 07800 if (!(i->dowmask & (1 << tm.tm_wday))) 07801 return 0; 07802 07803 /* Sanity check the hour just to be safe */ 07804 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07805 ast_log(LOG_WARNING, "Insane time...\n"); 07806 return 0; 07807 } 07808 07809 /* Now the tough part, we calculate if it fits 07810 in the right time based on min/hour */ 07811 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)))) 07812 return 0; 07813 07814 /* If we got this far, then we're good */ 07815 return 1; 07816 }
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 10617 of file pbx.c.
References app, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::list.
Referenced by handle_orig(), and handle_show_application().
10618 { 10619 struct ast_app *app = NULL; 10620 int which = 0; 10621 char *ret = NULL; 10622 size_t wordlen = strlen(word); 10623 10624 AST_RWLIST_RDLOCK(&apps); 10625 AST_RWLIST_TRAVERSE(&apps, app, list) { 10626 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10627 ret = ast_strdup(app->name); 10628 break; 10629 } 10630 } 10631 AST_RWLIST_UNLOCK(&apps); 10632 10633 return ret; 10634 }
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 |
0 | on success | |
-1 | on failure |
Definition at line 8020 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08021 { 08022 int ret = -1; 08023 struct ast_context *c; 08024 08025 c = find_context_locked(context); 08026 if (c) { 08027 ret = ast_context_add_ignorepat2(c, value, registrar); 08028 ast_unlock_contexts(); 08029 } 08030 return ret; 08031 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8033 of file pbx.c.
References ast_calloc, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().
08034 { 08035 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08036 int length; 08037 char *pattern; 08038 length = sizeof(struct ast_ignorepat); 08039 length += strlen(value) + 1; 08040 if (!(ignorepat = ast_calloc(1, length))) 08041 return -1; 08042 /* The cast to char * is because we need to write the initial value. 08043 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08044 * sees the cast as dereferencing a type-punned pointer and warns about 08045 * it. This is the workaround (we're telling gcc, yes, that's really 08046 * what we wanted to do). 08047 */ 08048 pattern = (char *) ignorepat->pattern; 08049 strcpy(pattern, value); 08050 ignorepat->next = NULL; 08051 ignorepat->registrar = registrar; 08052 ast_wrlock_context(con); 08053 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08054 ignorepatl = ignorepatc; 08055 if (!strcasecmp(ignorepatc->pattern, value)) { 08056 /* Already there */ 08057 ast_unlock_context(con); 08058 errno = EEXIST; 08059 return -1; 08060 } 08061 } 08062 if (ignorepatl) 08063 ignorepatl->next = ignorepat; 08064 else 08065 con->ignorepats = ignorepat; 08066 ast_unlock_context(con); 08067 return 0; 08068 08069 }
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 |
0 | on success | |
-1 | on error |
Definition at line 7564 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07565 { 07566 int ret = -1; 07567 struct ast_context *c; 07568 07569 c = find_context_locked(context); 07570 if (c) { 07571 ret = ast_context_add_include2(c, include, registrar); 07572 ast_unlock_contexts(); 07573 } 07574 return ret; 07575 }
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 |
0 | on success | |
-1 | on failure |
Definition at line 7833 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_context_add_include(), and context_merge_incls_swits_igps_other_registrars().
07835 { 07836 struct ast_include *new_include; 07837 char *c; 07838 struct ast_include *i, *il = NULL; /* include, include_last */ 07839 int length; 07840 char *p; 07841 07842 length = sizeof(struct ast_include); 07843 length += 2 * (strlen(value) + 1); 07844 07845 /* allocate new include structure ... */ 07846 if (!(new_include = ast_calloc(1, length))) 07847 return -1; 07848 /* Fill in this structure. Use 'p' for assignments, as the fields 07849 * in the structure are 'const char *' 07850 */ 07851 p = new_include->stuff; 07852 new_include->name = p; 07853 strcpy(p, value); 07854 p += strlen(value) + 1; 07855 new_include->rname = p; 07856 strcpy(p, value); 07857 /* Strip off timing info, and process if it is there */ 07858 if ( (c = strchr(p, ',')) ) { 07859 *c++ = '\0'; 07860 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07861 } 07862 new_include->next = NULL; 07863 new_include->registrar = registrar; 07864 07865 ast_wrlock_context(con); 07866 07867 /* ... go to last include and check if context is already included too... */ 07868 for (i = con->includes; i; i = i->next) { 07869 if (!strcasecmp(i->name, new_include->name)) { 07870 ast_destroy_timing(&(new_include->timing)); 07871 ast_free(new_include); 07872 ast_unlock_context(con); 07873 errno = EEXIST; 07874 return -1; 07875 } 07876 il = i; 07877 } 07878 07879 /* ... include new context into context list, unlock, return */ 07880 if (il) 07881 il->next = new_include; 07882 else 07883 con->includes = new_include; 07884 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07885 07886 ast_unlock_context(con); 07887 07888 return 0; 07889 }
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 |
0 | on success | |
-1 | on failure |
Definition at line 7896 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07897 { 07898 int ret = -1; 07899 struct ast_context *c; 07900 07901 c = find_context_locked(context); 07902 if (c) { /* found, add switch to this context */ 07903 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07904 ast_unlock_contexts(); 07905 } 07906 return ret; 07907 }
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 7916 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, store_hint::list, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), and lua_register_switches().
07918 { 07919 struct ast_sw *new_sw; 07920 struct ast_sw *i; 07921 int length; 07922 char *p; 07923 07924 length = sizeof(struct ast_sw); 07925 length += strlen(value) + 1; 07926 if (data) 07927 length += strlen(data); 07928 length++; 07929 07930 /* allocate new sw structure ... */ 07931 if (!(new_sw = ast_calloc(1, length))) 07932 return -1; 07933 /* ... fill in this structure ... */ 07934 p = new_sw->stuff; 07935 new_sw->name = p; 07936 strcpy(new_sw->name, value); 07937 p += strlen(value) + 1; 07938 new_sw->data = p; 07939 if (data) { 07940 strcpy(new_sw->data, data); 07941 p += strlen(data) + 1; 07942 } else { 07943 strcpy(new_sw->data, ""); 07944 p++; 07945 } 07946 new_sw->eval = eval; 07947 new_sw->registrar = registrar; 07948 07949 /* ... try to lock this context ... */ 07950 ast_wrlock_context(con); 07951 07952 /* ... go to last sw and check if context is already swd too... */ 07953 AST_LIST_TRAVERSE(&con->alts, i, list) { 07954 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07955 ast_free(new_sw); 07956 ast_unlock_context(con); 07957 errno = EEXIST; 07958 return -1; 07959 } 07960 } 07961 07962 /* ... sw new context into context list, unlock, return */ 07963 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07964 07965 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07966 07967 ast_unlock_context(con); 07968 07969 return 0; 07970 }
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 |
Definition at line 9279 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(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09280 { 09281 ast_wrlock_contexts(); 09282 __ast_context_destroy(contexts, contexts_table, con,registrar); 09283 ast_unlock_contexts(); 09284 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2656 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, fake_context::name, and ast_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().
02657 { 02658 struct ast_context *tmp; 02659 struct fake_context item; 02660 02661 if (!name) { 02662 return NULL; 02663 } 02664 ast_rdlock_contexts(); 02665 if (contexts_table) { 02666 ast_copy_string(item.name, name, sizeof(item.name)); 02667 tmp = ast_hashtab_lookup(contexts_table, &item); 02668 } else { 02669 tmp = NULL; 02670 while ((tmp = ast_walk_contexts(tmp))) { 02671 if (!strcasecmp(name, tmp->name)) { 02672 break; 02673 } 02674 } 02675 } 02676 ast_unlock_contexts(); 02677 return tmp; 02678 }
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.
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 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 7165 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, name, fake_context::name, ast_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), and set_config().
07166 { 07167 struct ast_context *tmp, **local_contexts; 07168 struct fake_context search; 07169 int length = sizeof(struct ast_context) + strlen(name) + 1; 07170 07171 if (!contexts_table) { 07172 /* Protect creation of contexts_table from reentrancy. */ 07173 ast_wrlock_contexts(); 07174 if (!contexts_table) { 07175 contexts_table = ast_hashtab_create(17, 07176 ast_hashtab_compare_contexts, 07177 ast_hashtab_resize_java, 07178 ast_hashtab_newsize_java, 07179 ast_hashtab_hash_contexts, 07180 0); 07181 } 07182 ast_unlock_contexts(); 07183 } 07184 07185 ast_copy_string(search.name, name, sizeof(search.name)); 07186 if (!extcontexts) { 07187 ast_rdlock_contexts(); 07188 local_contexts = &contexts; 07189 tmp = ast_hashtab_lookup(contexts_table, &search); 07190 ast_unlock_contexts(); 07191 if (tmp) { 07192 tmp->refcount++; 07193 return tmp; 07194 } 07195 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07196 local_contexts = extcontexts; 07197 tmp = ast_hashtab_lookup(exttable, &search); 07198 if (tmp) { 07199 tmp->refcount++; 07200 return tmp; 07201 } 07202 } 07203 07204 if ((tmp = ast_calloc(1, length))) { 07205 ast_rwlock_init(&tmp->lock); 07206 ast_mutex_init(&tmp->macrolock); 07207 strcpy(tmp->name, name); 07208 tmp->root = NULL; 07209 tmp->root_table = NULL; 07210 tmp->registrar = ast_strdup(registrar); 07211 tmp->includes = NULL; 07212 tmp->ignorepats = NULL; 07213 tmp->refcount = 1; 07214 } else { 07215 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07216 return NULL; 07217 } 07218 07219 if (!extcontexts) { 07220 ast_wrlock_contexts(); 07221 tmp->next = *local_contexts; 07222 *local_contexts = tmp; 07223 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07224 ast_unlock_contexts(); 07225 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07226 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07227 } else { 07228 tmp->next = *local_contexts; 07229 if (exttable) 07230 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07231 07232 *local_contexts = tmp; 07233 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07234 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07235 } 07236 return tmp; 07237 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 5765 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05766 { 05767 struct ast_context *c; 05768 int ret = -1; 05769 05770 c = find_context_locked(context); 05771 if (c) { 05772 ast_unlock_contexts(); 05773 05774 /* if we found context, lock macrolock */ 05775 ret = ast_mutex_lock(&c->macrolock); 05776 } 05777 05778 return ret; 05779 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
Definition at line 5570 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), remove_exten_if_exist(), unregister_exten(), and UnregisterExtension().
05571 { 05572 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05573 }
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 5600 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
05601 { 05602 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05603 }
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 5575 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().
05576 { 05577 int ret = -1; /* default error return */ 05578 struct ast_context *c; 05579 05580 c = find_context_locked(context); 05581 if (c) { /* ... remove extension ... */ 05582 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 05583 matchcallerid, registrar, 0); 05584 ast_unlock_contexts(); 05585 } 05586 05587 return ret; 05588 }
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 5605 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, destroy_exten(), exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
05606 { 05607 struct ast_exten *exten, *prev_exten = NULL; 05608 struct ast_exten *peer; 05609 struct ast_exten ex, *exten2, *exten3; 05610 char dummy_name[1024]; 05611 struct ast_exten *previous_peer = NULL; 05612 struct ast_exten *next_peer = NULL; 05613 int found = 0; 05614 05615 if (!already_locked) 05616 ast_wrlock_context(con); 05617 05618 /* Handle this is in the new world */ 05619 05620 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05621 * peers, not just those matching the callerid. */ 05622 #ifdef NEED_DEBUG 05623 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05624 #endif 05625 #ifdef CONTEXT_DEBUG 05626 check_contexts(__FILE__, __LINE__); 05627 #endif 05628 /* find this particular extension */ 05629 ex.exten = dummy_name; 05630 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05631 ex.cidmatch = callerid; 05632 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05633 exten = ast_hashtab_lookup(con->root_table, &ex); 05634 if (exten) { 05635 if (priority == 0) { 05636 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05637 if (!exten2) 05638 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); 05639 if (con->pattern_tree) { 05640 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05641 05642 if (x->exten) { /* this test for safety purposes */ 05643 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05644 x->exten = 0; /* get rid of what will become a bad pointer */ 05645 } else { 05646 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05647 } 05648 } 05649 } else { 05650 ex.priority = priority; 05651 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05652 if (exten2) { 05653 05654 if (exten2->label) { /* if this exten has a label, remove that, too */ 05655 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05656 if (!exten3) 05657 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); 05658 } 05659 05660 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05661 if (!exten3) 05662 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); 05663 if (exten2 == exten && exten2->peer) { 05664 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05665 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05666 } 05667 if (ast_hashtab_size(exten->peer_table) == 0) { 05668 /* well, if the last priority of an exten is to be removed, 05669 then, the extension is removed, too! */ 05670 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05671 if (!exten3) 05672 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05673 if (con->pattern_tree) { 05674 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05675 if (x->exten) { /* this test for safety purposes */ 05676 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05677 x->exten = 0; /* get rid of what will become a bad pointer */ 05678 } 05679 } 05680 } 05681 } else { 05682 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05683 priority, exten->exten, con->name); 05684 } 05685 } 05686 } else { 05687 /* hmmm? this exten is not in this pattern tree? */ 05688 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05689 extension, con->name); 05690 } 05691 #ifdef NEED_DEBUG 05692 if (con->pattern_tree) { 05693 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05694 log_match_char_tree(con->pattern_tree, " "); 05695 } 05696 #endif 05697 05698 /* scan the extension list to find first matching extension-registrar */ 05699 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05700 if (!strcmp(exten->exten, extension) && 05701 (!registrar || !strcmp(exten->registrar, registrar)) && 05702 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05703 break; 05704 } 05705 if (!exten) { 05706 /* we can't find right extension */ 05707 if (!already_locked) 05708 ast_unlock_context(con); 05709 return -1; 05710 } 05711 05712 /* scan the priority list to remove extension with exten->priority == priority */ 05713 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05714 peer && !strcmp(peer->exten, extension) && (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch))); 05715 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05716 if ((priority == 0 || peer->priority == priority) && 05717 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05718 (!registrar || !strcmp(peer->registrar, registrar) )) { 05719 found = 1; 05720 05721 /* we are first priority extension? */ 05722 if (!previous_peer) { 05723 /* 05724 * We are first in the priority chain, so must update the extension chain. 05725 * The next node is either the next priority or the next extension 05726 */ 05727 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05728 if (peer->peer) { 05729 /* move the peer_table and peer_label_table down to the next peer, if 05730 it is there */ 05731 peer->peer->peer_table = peer->peer_table; 05732 peer->peer->peer_label_table = peer->peer_label_table; 05733 peer->peer_table = NULL; 05734 peer->peer_label_table = NULL; 05735 } 05736 if (!prev_exten) { /* change the root... */ 05737 con->root = next_node; 05738 } else { 05739 prev_exten->next = next_node; /* unlink */ 05740 } 05741 if (peer->peer) { /* update the new head of the pri list */ 05742 peer->peer->next = peer->next; 05743 } 05744 } else { /* easy, we are not first priority in extension */ 05745 previous_peer->peer = peer->peer; 05746 } 05747 05748 /* now, free whole priority extension */ 05749 destroy_exten(peer); 05750 } else { 05751 previous_peer = peer; 05752 } 05753 } 05754 if (!already_locked) 05755 ast_unlock_context(con); 05756 return found ? 0 : -1; 05757 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7976 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07977 { 07978 int ret = -1; 07979 struct ast_context *c; 07980 07981 c = find_context_locked(context); 07982 if (c) { 07983 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 07984 ast_unlock_contexts(); 07985 } 07986 return ret; 07987 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7989 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().
07990 { 07991 struct ast_ignorepat *ip, *ipl = NULL; 07992 07993 ast_wrlock_context(con); 07994 07995 for (ip = con->ignorepats; ip; ip = ip->next) { 07996 if (!strcmp(ip->pattern, ignorepat) && 07997 (!registrar || (registrar == ip->registrar))) { 07998 if (ipl) { 07999 ipl->next = ip->next; 08000 ast_free(ip); 08001 } else { 08002 con->ignorepats = ip->next; 08003 ast_free(ip); 08004 } 08005 ast_unlock_context(con); 08006 return 0; 08007 } 08008 ipl = ip; 08009 } 08010 08011 ast_unlock_context(con); 08012 errno = EINVAL; 08013 return -1; 08014 }
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 5463 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05464 { 05465 int ret = -1; 05466 struct ast_context *c; 05467 05468 c = find_context_locked(context); 05469 if (c) { 05470 /* found, remove include from this context ... */ 05471 ret = ast_context_remove_include2(c, include, registrar); 05472 ast_unlock_contexts(); 05473 } 05474 return ret; 05475 }
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 failure. |
Definition at line 5486 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().
05487 { 05488 struct ast_include *i, *pi = NULL; 05489 int ret = -1; 05490 05491 ast_wrlock_context(con); 05492 05493 /* find our include */ 05494 for (i = con->includes; i; pi = i, i = i->next) { 05495 if (!strcmp(i->name, include) && 05496 (!registrar || !strcmp(i->registrar, registrar))) { 05497 /* remove from list */ 05498 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05499 if (pi) 05500 pi->next = i->next; 05501 else 05502 con->includes = i->next; 05503 /* free include and return */ 05504 ast_destroy_timing(&(i->timing)); 05505 ast_free(i); 05506 ret = 0; 05507 break; 05508 } 05509 } 05510 05511 ast_unlock_context(con); 05512 05513 return ret; 05514 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 5521 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05522 { 05523 int ret = -1; /* default error return */ 05524 struct ast_context *c; 05525 05526 c = find_context_locked(context); 05527 if (c) { 05528 /* remove switch from this context ... */ 05529 ret = ast_context_remove_switch2(c, sw, data, registrar); 05530 ast_unlock_contexts(); 05531 } 05532 return ret; 05533 }
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 5543 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::list, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
05544 { 05545 struct ast_sw *i; 05546 int ret = -1; 05547 05548 ast_wrlock_context(con); 05549 05550 /* walk switches */ 05551 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05552 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05553 (!registrar || !strcmp(i->registrar, registrar))) { 05554 /* found, remove from list */ 05555 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05556 AST_LIST_REMOVE_CURRENT(list); 05557 ast_free(i); /* free switch and return */ 05558 ret = 0; 05559 break; 05560 } 05561 } 05562 AST_LIST_TRAVERSE_SAFE_END; 05563 05564 ast_unlock_context(con); 05565 05566 return ret; 05567 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5786 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05787 { 05788 struct ast_context *c; 05789 int ret = -1; 05790 05791 c = find_context_locked(context); 05792 if (c) { 05793 ast_unlock_contexts(); 05794 05795 /* if we found context, unlock macrolock */ 05796 ret = ast_mutex_unlock(&c->macrolock); 05797 } 05798 05799 return ret; 05800 }
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 10502 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().
10503 { 10504 struct ast_include *inc = NULL; 10505 int res = 0; 10506 10507 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10508 if (ast_context_find(inc->rname)) 10509 continue; 10510 10511 res = -1; 10512 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10513 ast_get_context_name(con), inc->rname); 10514 break; 10515 } 10516 10517 return res; 10518 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 3485 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_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().
03486 { 03487 struct ast_custom_function *acf = NULL; 03488 03489 AST_RWLIST_RDLOCK(&acf_root); 03490 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03491 if (!strcmp(name, acf->name)) 03492 break; 03493 } 03494 AST_RWLIST_UNLOCK(&acf_root); 03495 03496 return acf; 03497 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3499 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, 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 _unload_module(), load_module(), reload(), and unload_module().
03500 { 03501 struct ast_custom_function *cur; 03502 03503 if (!acf) { 03504 return -1; 03505 } 03506 03507 AST_RWLIST_WRLOCK(&acf_root); 03508 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03509 #ifdef AST_XML_DOCS 03510 if (cur->docsrc == AST_XML_DOC) { 03511 ast_string_field_free_memory(acf); 03512 } 03513 #endif 03514 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03515 } 03516 AST_RWLIST_UNLOCK(&acf_root); 03517 03518 return cur ? 0 : -1; 03519 }
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 7818 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().
07819 { 07820 if (i->timezone) { 07821 ast_free(i->timezone); 07822 i->timezone = NULL; 07823 } 07824 return 0; 07825 }
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 4308 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().
04309 { 04310 switch (devstate) { 04311 case AST_DEVICE_ONHOLD: 04312 return AST_EXTENSION_ONHOLD; 04313 case AST_DEVICE_BUSY: 04314 return AST_EXTENSION_BUSY; 04315 case AST_DEVICE_UNKNOWN: 04316 return AST_EXTENSION_NOT_INUSE; 04317 case AST_DEVICE_UNAVAILABLE: 04318 case AST_DEVICE_INVALID: 04319 return AST_EXTENSION_UNAVAILABLE; 04320 case AST_DEVICE_RINGINUSE: 04321 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04322 case AST_DEVICE_RINGING: 04323 return AST_EXTENSION_RINGING; 04324 case AST_DEVICE_INUSE: 04325 return AST_EXTENSION_INUSE; 04326 case AST_DEVICE_NOT_INUSE: 04327 return AST_EXTENSION_NOT_INUSE; 04328 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04329 break; 04330 } 04331 04332 return AST_EXTENSION_NOT_INUSE; 04333 }
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 4860 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_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().
04861 { 04862 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04863 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8129 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(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
08130 { 08131 if (!chan) 08132 return -1; 08133 08134 ast_channel_lock(chan); 08135 08136 if (!ast_strlen_zero(context)) 08137 ast_copy_string(chan->context, context, sizeof(chan->context)); 08138 if (!ast_strlen_zero(exten)) 08139 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08140 if (priority > -1) { 08141 chan->priority = priority; 08142 /* see flag description in channel.h for explanation */ 08143 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08144 chan->priority--; 08145 } 08146 08147 ast_channel_unlock(chan); 08148 08149 return 0; 08150 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2633 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().
02634 { 02635 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02636 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02637 return extension_match_core(pattern, data, needmore); 02638 }
int ast_extension_cmp | ( | const char * | a, | |
const char * | b | |||
) |
Determine if one extension should match before another.
a | extension to compare with b | |
b | extension to compare with a |
0 | if the two extensions have equal matching priority | |
1 | on a > b | |
-1 | on a < b |
Definition at line 2435 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02436 { 02437 return ext_cmp(a, b); 02438 }
int ast_extension_match | ( | const char * | pattern, | |
const char * | extension | |||
) |
Determine if a given extension matches a given pattern (in NXX format).
pattern | pattern to match | |
extension | extension to check against the pattern. |
1 | on match | |
0 | on failure |
Definition at line 2628 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(), show_dialplan_helper(), and sig_pri_msn_match().
02629 { 02630 return extension_match_core(pattern, data, E_MATCH); 02631 }
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 4378 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().
04379 { 04380 struct ast_exten *e; 04381 04382 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04383 return -1; /* No hint, return -1 */ 04384 } 04385 04386 if (e->exten[0] == '_') { 04387 /* Create this hint on-the-fly */ 04388 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04389 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04390 e->registrar); 04391 if (!(e = ast_hint_extension(c, context, exten))) { 04392 /* Improbable, but not impossible */ 04393 return -1; 04394 } 04395 } 04396 04397 return ast_extension_state2(e); /* Check all devices in the hint */ 04398 }
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 4366 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().
04367 { 04368 int i; 04369 04370 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04371 if (extension_states[i].extension_state == extension_state) 04372 return extension_states[i].text; 04373 } 04374 return "Unknown"; 04375 }
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 4599 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
04601 { 04602 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 04603 }
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.
10.1.0
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 |
The destroy_cb is called when the registration is deleted so the registerer can release any associated resources.
-1 | on failure | |
ID | on success |
Definition at line 4512 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_exten::cidmatch, ast_exten::data, destroy_state_cb(), ast_exten::exten, hints, 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().
04514 { 04515 struct ast_hint *hint; 04516 struct ast_state_cb *state_cb; 04517 struct ast_exten *e; 04518 int id; 04519 04520 /* If there's no context and extension: add callback to statecbs list */ 04521 if (!context && !exten) { 04522 /* Prevent multiple adds from adding the same change_cb at the same time. */ 04523 ao2_lock(statecbs); 04524 04525 /* Remove any existing change_cb. */ 04526 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 04527 04528 /* Now insert the change_cb */ 04529 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04530 ao2_unlock(statecbs); 04531 return -1; 04532 } 04533 state_cb->id = 0; 04534 state_cb->change_cb = change_cb; 04535 state_cb->destroy_cb = destroy_cb; 04536 state_cb->data = data; 04537 ao2_link(statecbs, state_cb); 04538 04539 ao2_ref(state_cb, -1); 04540 ao2_unlock(statecbs); 04541 return 0; 04542 } 04543 04544 if (!context || !exten) 04545 return -1; 04546 04547 /* This callback type is for only one hint, so get the hint */ 04548 e = ast_hint_extension(NULL, context, exten); 04549 if (!e) { 04550 return -1; 04551 } 04552 04553 /* If this is a pattern, dynamically create a new extension for this 04554 * particular match. Note that this will only happen once for each 04555 * individual extension, because the pattern will no longer match first. 04556 */ 04557 if (e->exten[0] == '_') { 04558 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04559 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04560 e->registrar); 04561 e = ast_hint_extension(NULL, context, exten); 04562 if (!e || e->exten[0] == '_') { 04563 return -1; 04564 } 04565 } 04566 04567 /* Find the hint in the hints container */ 04568 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04569 hint = ao2_find(hints, e, 0); 04570 if (!hint) { 04571 ao2_unlock(hints); 04572 return -1; 04573 } 04574 04575 /* Now insert the callback in the callback list */ 04576 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04577 ao2_ref(hint, -1); 04578 ao2_unlock(hints); 04579 return -1; 04580 } 04581 do { 04582 id = stateid++; /* Unique ID for this callback */ 04583 /* Do not allow id to ever be -1 or 0. */ 04584 } while (id == -1 || id == 0); 04585 state_cb->id = id; 04586 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 04587 state_cb->destroy_cb = destroy_cb; 04588 state_cb->data = data; /* Data for the callback */ 04589 ao2_link(hint->callbacks, state_cb); 04590 04591 ao2_ref(state_cb, -1); 04592 ao2_ref(hint, -1); 04593 ao2_unlock(hints); 04594 04595 return id; 04596 }
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 4621 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().
04622 { 04623 struct ast_state_cb *p_cur; 04624 int ret = -1; 04625 04626 if (!id) { /* id == 0 is a callback without extension */ 04627 if (!change_cb) { 04628 return ret; 04629 } 04630 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 04631 if (p_cur) { 04632 ret = 0; 04633 ao2_ref(p_cur, -1); 04634 } 04635 } else { /* callback with extension, find the callback based on ID */ 04636 struct ast_hint *hint; 04637 04638 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04639 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04640 if (hint) { 04641 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04642 if (p_cur) { 04643 ret = 0; 04644 ao2_ref(p_cur, -1); 04645 } 04646 ao2_ref(hint, -1); 04647 } 04648 ao2_unlock(hints); 04649 } 04650 04651 return ret; 04652 }
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 4865 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().
04866 { 04867 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04868 }
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.
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.
Definition at line 4870 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
04871 { 04872 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04873 }
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 |
0 | success | |
non-zero | failure |
Definition at line 3643 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, ast_module_user::chan, copy(), func_args(), 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().
03644 { 03645 char *copy = ast_strdupa(function); 03646 char *args = func_args(copy); 03647 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03648 int res; 03649 struct ast_module_user *u = NULL; 03650 03651 if (acfptr == NULL) { 03652 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03653 } else if (!acfptr->read && !acfptr->read2) { 03654 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03655 } else if (acfptr->read) { 03656 if (acfptr->mod) { 03657 u = __ast_module_user_add(acfptr->mod, chan); 03658 } 03659 res = acfptr->read(chan, copy, args, workspace, len); 03660 if (acfptr->mod && u) { 03661 __ast_module_user_remove(acfptr->mod, u); 03662 } 03663 return res; 03664 } else { 03665 struct ast_str *str = ast_str_create(16); 03666 if (acfptr->mod) { 03667 u = __ast_module_user_add(acfptr->mod, chan); 03668 } 03669 res = acfptr->read2(chan, copy, args, &str, 0); 03670 if (acfptr->mod && u) { 03671 __ast_module_user_remove(acfptr->mod, u); 03672 } 03673 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03674 ast_free(str); 03675 return res; 03676 } 03677 return -1; 03678 }
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 |
0 | success | |
non-zero | failure |
Definition at line 3680 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, ast_module_user::chan, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, str, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
03681 { 03682 char *copy = ast_strdupa(function); 03683 char *args = func_args(copy); 03684 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03685 int res; 03686 struct ast_module_user *u = NULL; 03687 03688 if (acfptr == NULL) { 03689 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03690 } else if (!acfptr->read && !acfptr->read2) { 03691 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03692 } else { 03693 if (acfptr->mod) { 03694 u = __ast_module_user_add(acfptr->mod, chan); 03695 } 03696 ast_str_reset(*str); 03697 if (acfptr->read2) { 03698 /* ast_str enabled */ 03699 res = acfptr->read2(chan, copy, args, str, maxlen); 03700 } else { 03701 /* Legacy function pointer, allocate buffer for result */ 03702 int maxsize = ast_str_size(*str); 03703 if (maxlen > -1) { 03704 if (maxlen == 0) { 03705 if (acfptr->read_max) { 03706 maxsize = acfptr->read_max; 03707 } else { 03708 maxsize = VAR_BUF_SIZE; 03709 } 03710 } else { 03711 maxsize = maxlen; 03712 } 03713 ast_str_make_space(str, maxsize); 03714 } 03715 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03716 } 03717 if (acfptr->mod && u) { 03718 __ast_module_user_remove(acfptr->mod, u); 03719 } 03720 return res; 03721 } 03722 return -1; 03723 }
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 |
0 | success | |
non-zero | failure |
Definition at line 3725 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, ast_module_user::chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03726 { 03727 char *copy = ast_strdupa(function); 03728 char *args = func_args(copy); 03729 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03730 03731 if (acfptr == NULL) 03732 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03733 else if (!acfptr->write) 03734 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03735 else { 03736 int res; 03737 struct ast_module_user *u = NULL; 03738 if (acfptr->mod) 03739 u = __ast_module_user_add(acfptr->mod, chan); 03740 res = acfptr->write(chan, copy, args, value); 03741 if (acfptr->mod && u) 03742 __ast_module_user_remove(acfptr->mod, u); 03743 return res; 03744 } 03745 03746 return -1; 03747 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10354 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), 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().
10355 { 10356 return con ? con->name : NULL; 10357 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10392 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10393 { 10394 return c ? c->registrar : NULL; 10395 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10422 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().
10423 { 10424 return e ? e->app : NULL; 10425 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10427 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().
10428 { 10429 return e ? e->data : NULL; 10430 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10417 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10418 { 10419 return e ? e->cidmatch : NULL; 10420 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 10359 of file pbx.c.
References exten.
Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 10369 of file pbx.c.
References exten.
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 10412 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10413 { 10414 return e ? e->matchcid : 0; 10415 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10364 of file pbx.c.
References 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().
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10384 of file pbx.c.
References exten.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10397 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10398 { 10399 return e ? e->registrar : NULL; 10400 }
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 4822 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().
04823 { 04824 struct ast_exten *e = ast_hint_extension(c, context, exten); 04825 04826 if (e) { 04827 if (hint) 04828 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04829 if (name) { 04830 const char *tmp = ast_get_extension_app_data(e); 04831 if (tmp) 04832 ast_copy_string(name, tmp, namesize); 04833 } 04834 return -1; 04835 } 04836 return 0; 04837 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10379 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().
10380 { 10381 return ip ? ip->pattern : NULL; 10382 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10407 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().
10408 { 10409 return ip ? ip->registrar : NULL; 10410 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 10374 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 10402 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().
10403 { 10404 return i ? i->registrar : NULL; 10405 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10437 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().
10438 { 10439 return sw ? sw->data : NULL; 10440 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10442 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10443 { 10444 return sw->eval; 10445 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10432 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().
10433 { 10434 return sw ? sw->name : NULL; 10435 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10447 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().
10448 { 10449 return sw ? sw->registrar : NULL; 10450 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10542 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(), priority_jump(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10543 { 10544 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10545 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1065 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01066 { 01067 const struct ast_context *ac = ah_a; 01068 const struct ast_context *bc = ah_b; 01069 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01070 return 1; 01071 /* assume context names are registered in a string table! */ 01072 return strcmp(ac->name, bc->name); 01073 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1108 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().
01109 { 01110 const struct ast_context *ac = obj; 01111 return ast_hashtab_hash_string(ac->name); 01112 }
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 |
0 | if the pattern should not be ignored | |
non-zero | if the pattern should be ignored |
Definition at line 8071 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(), pri_ss_thread(), and skinny_ss().
08072 { 08073 struct ast_context *con = ast_context_find(context); 08074 08075 if (con) { 08076 struct ast_ignorepat *pat; 08077 08078 for (pat = con->ignorepats; pat; pat = pat->next) { 08079 if (ast_extension_match(pat->pattern, pattern)) 08080 return 1; 08081 } 08082 } 08083 08084 return 0; 08085 }
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 4880 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), collect_digits(), dahdi_r2_on_dnis_digit_received(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_ss_thread(), readexten_exec(), and skinny_ss().
04881 { 04882 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04883 }
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 7369 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_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(), ast_hint::callbacks, store_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, store_hint::data, ast_state_cb::data, E_MATCH, store_hint::exten, hints, store_hint::laststate, ast_hint::laststate, store_hint::list, store_hint::next, ast_context::next, OBJ_UNLINK, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07370 { 07371 double ft; 07372 struct ast_context *tmp; 07373 struct ast_context *oldcontextslist; 07374 struct ast_hashtab *oldtable; 07375 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07376 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07377 struct store_hint *saved_hint; 07378 struct ast_hint *hint; 07379 struct ast_exten *exten; 07380 int length; 07381 struct ast_state_cb *thiscb; 07382 struct ast_hashtab_iter *iter; 07383 struct ao2_iterator i; 07384 struct timeval begintime; 07385 struct timeval writelocktime; 07386 struct timeval endlocktime; 07387 struct timeval enddeltime; 07388 07389 /* 07390 * It is very important that this function hold the hints 07391 * container lock _and_ the conlock during its operation; not 07392 * only do we need to ensure that the list of contexts and 07393 * extensions does not change, but also that no hint callbacks 07394 * (watchers) are added or removed during the merge/delete 07395 * process 07396 * 07397 * In addition, the locks _must_ be taken in this order, because 07398 * there are already other code paths that use this order 07399 */ 07400 07401 begintime = ast_tvnow(); 07402 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07403 ast_wrlock_contexts(); 07404 iter = ast_hashtab_start_traversal(contexts_table); 07405 while ((tmp = ast_hashtab_next(iter))) { 07406 context_merge(extcontexts, exttable, tmp, registrar); 07407 } 07408 ast_hashtab_end_traversal(iter); 07409 07410 ao2_lock(hints); 07411 writelocktime = ast_tvnow(); 07412 07413 /* preserve all watchers for hints */ 07414 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07415 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07416 if (ao2_container_count(hint->callbacks)) { 07417 ao2_lock(hint); 07418 if (!hint->exten) { 07419 /* The extension has already been destroyed. (Should never happen here) */ 07420 ao2_unlock(hint); 07421 continue; 07422 } 07423 07424 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07425 + sizeof(*saved_hint); 07426 if (!(saved_hint = ast_calloc(1, length))) { 07427 ao2_unlock(hint); 07428 continue; 07429 } 07430 07431 /* This removes all the callbacks from the hint into saved_hint. */ 07432 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07433 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07434 /* 07435 * We intentionally do not unref thiscb to account for the 07436 * non-ao2 reference in saved_hint->callbacks 07437 */ 07438 } 07439 07440 saved_hint->laststate = hint->laststate; 07441 saved_hint->context = saved_hint->data; 07442 strcpy(saved_hint->data, hint->exten->parent->name); 07443 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07444 strcpy(saved_hint->exten, hint->exten->exten); 07445 ao2_unlock(hint); 07446 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07447 } 07448 } 07449 ao2_iterator_destroy(&i); 07450 07451 /* save the old table and list */ 07452 oldtable = contexts_table; 07453 oldcontextslist = contexts; 07454 07455 /* move in the new table and list */ 07456 contexts_table = exttable; 07457 contexts = *extcontexts; 07458 07459 /* 07460 * Restore the watchers for hints that can be found; notify 07461 * those that cannot be restored. 07462 */ 07463 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07464 struct pbx_find_info q = { .stacklen = 0 }; 07465 07466 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07467 PRIORITY_HINT, NULL, "", E_MATCH); 07468 /* 07469 * If this is a pattern, dynamically create a new extension for this 07470 * particular match. Note that this will only happen once for each 07471 * individual extension, because the pattern will no longer match first. 07472 */ 07473 if (exten && exten->exten[0] == '_') { 07474 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07475 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07476 exten->registrar); 07477 /* rwlocks are not recursive locks */ 07478 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07479 saved_hint->exten); 07480 } 07481 07482 /* Find the hint in the hints container */ 07483 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07484 if (!hint) { 07485 /* 07486 * Notify watchers of this removed hint later when we aren't 07487 * encumberd by so many locks. 07488 */ 07489 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07490 } else { 07491 ao2_lock(hint); 07492 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07493 ao2_link(hint->callbacks, thiscb); 07494 /* Ref that we added when putting into saved_hint->callbacks */ 07495 ao2_ref(thiscb, -1); 07496 } 07497 hint->laststate = saved_hint->laststate; 07498 ao2_unlock(hint); 07499 ao2_ref(hint, -1); 07500 ast_free(saved_hint); 07501 } 07502 } 07503 07504 ao2_unlock(hints); 07505 ast_unlock_contexts(); 07506 07507 /* 07508 * Notify watchers of all removed hints with the same lock 07509 * environment as handle_statechange(). 07510 */ 07511 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 07512 /* this hint has been removed, notify the watchers */ 07513 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07514 thiscb->change_cb(saved_hint->context, saved_hint->exten, 07515 AST_EXTENSION_REMOVED, thiscb->data); 07516 /* Ref that we added when putting into saved_hint->callbacks */ 07517 ao2_ref(thiscb, -1); 07518 } 07519 ast_free(saved_hint); 07520 } 07521 07522 ast_mutex_unlock(&context_merge_lock); 07523 endlocktime = ast_tvnow(); 07524 07525 /* 07526 * The old list and hashtab no longer are relevant, delete them 07527 * while the rest of asterisk is now freely using the new stuff 07528 * instead. 07529 */ 07530 07531 ast_hashtab_destroy(oldtable, NULL); 07532 07533 for (tmp = oldcontextslist; tmp; ) { 07534 struct ast_context *next; /* next starting point */ 07535 07536 next = tmp->next; 07537 __ast_internal_context_destroy(tmp); 07538 tmp = next; 07539 } 07540 enddeltime = ast_tvnow(); 07541 07542 ft = ast_tvdiff_us(writelocktime, begintime); 07543 ft /= 1000000.0; 07544 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07545 07546 ft = ast_tvdiff_us(endlocktime, writelocktime); 07547 ft /= 1000000.0; 07548 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07549 07550 ft = ast_tvdiff_us(enddeltime, endlocktime); 07551 ft /= 1000000.0; 07552 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07553 07554 ft = ast_tvdiff_us(enddeltime, begintime); 07555 ft /= 1000000.0; 07556 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07557 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10607 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().
10608 { 10609 return pbx_parseable_goto(chan, goto_string, 0); 10610 }
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 8948 of file pbx.c.
References __ast_request_and_dial(), 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(), async_stat::chan, errno, LOG_WARNING, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
08949 { 08950 struct ast_channel *chan; 08951 struct app_tmp *tmp; 08952 int res = -1, cdr_res = -1; 08953 struct outgoing_helper oh; 08954 08955 memset(&oh, 0, sizeof(oh)); 08956 oh.vars = vars; 08957 oh.account = account; 08958 08959 if (locked_channel) 08960 *locked_channel = NULL; 08961 if (ast_strlen_zero(app)) { 08962 res = -1; 08963 goto outgoing_app_cleanup; 08964 } 08965 if (synchronous) { 08966 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08967 if (chan) { 08968 ast_set_variables(chan, vars); 08969 if (account) 08970 ast_cdr_setaccount(chan, account); 08971 if (chan->_state == AST_STATE_UP) { 08972 res = 0; 08973 ast_verb(4, "Channel %s was answered.\n", chan->name); 08974 tmp = ast_calloc(1, sizeof(*tmp)); 08975 if (!tmp || ast_string_field_init(tmp, 252)) { 08976 if (tmp) { 08977 ast_free(tmp); 08978 } 08979 res = -1; 08980 } else { 08981 ast_string_field_set(tmp, app, app); 08982 ast_string_field_set(tmp, data, appdata); 08983 tmp->chan = chan; 08984 if (synchronous > 1) { 08985 if (locked_channel) 08986 ast_channel_unlock(chan); 08987 ast_pbx_run_app(tmp); 08988 } else { 08989 if (locked_channel) 08990 ast_channel_lock(chan); 08991 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 08992 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 08993 ast_string_field_free_memory(tmp); 08994 ast_free(tmp); 08995 if (locked_channel) 08996 ast_channel_unlock(chan); 08997 ast_hangup(chan); 08998 res = -1; 08999 } else { 09000 if (locked_channel) 09001 *locked_channel = chan; 09002 } 09003 } 09004 } 09005 } else { 09006 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09007 if (chan->cdr) { /* update the cdr */ 09008 /* here we update the status of the call, which sould be busy. 09009 * if that fails then we set the status to failed */ 09010 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09011 ast_cdr_failed(chan->cdr); 09012 } 09013 ast_hangup(chan); 09014 } 09015 } 09016 09017 if (res < 0) { /* the call failed for some reason */ 09018 if (*reason == 0) { /* if the call failed (not busy or no answer) 09019 * update the cdr with the failed message */ 09020 cdr_res = ast_pbx_outgoing_cdr_failed(); 09021 if (cdr_res != 0) { 09022 res = cdr_res; 09023 goto outgoing_app_cleanup; 09024 } 09025 } 09026 } 09027 09028 } else { 09029 struct async_stat *as; 09030 if (!(as = ast_calloc(1, sizeof(*as)))) { 09031 res = -1; 09032 goto outgoing_app_cleanup; 09033 } 09034 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09035 if (!chan) { 09036 ast_free(as); 09037 res = -1; 09038 goto outgoing_app_cleanup; 09039 } 09040 as->chan = chan; 09041 ast_copy_string(as->app, app, sizeof(as->app)); 09042 if (appdata) 09043 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09044 as->timeout = timeout; 09045 ast_set_variables(chan, vars); 09046 if (account) 09047 ast_cdr_setaccount(chan, account); 09048 /* Start a new thread, and get something handling this channel. */ 09049 if (locked_channel) 09050 ast_channel_lock(chan); 09051 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09052 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09053 ast_free(as); 09054 if (locked_channel) 09055 ast_channel_unlock(chan); 09056 ast_hangup(chan); 09057 res = -1; 09058 goto outgoing_app_cleanup; 09059 } else { 09060 if (locked_channel) 09061 *locked_channel = chan; 09062 } 09063 res = 0; 09064 } 09065 outgoing_app_cleanup: 09066 ast_variables_destroy(vars); 09067 return res; 09068 }
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 8779 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, outgoing_helper::cid_name, outgoing_helper::cid_num, outgoing_helper::context, ast_channel::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
08780 { 08781 struct ast_channel *chan; 08782 struct async_stat *as; 08783 int res = -1, cdr_res = -1; 08784 struct outgoing_helper oh; 08785 08786 if (synchronous) { 08787 oh.context = context; 08788 oh.exten = exten; 08789 oh.priority = priority; 08790 oh.cid_num = cid_num; 08791 oh.cid_name = cid_name; 08792 oh.account = account; 08793 oh.vars = vars; 08794 oh.parent_channel = NULL; 08795 08796 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08797 if (channel) { 08798 *channel = chan; 08799 if (chan) 08800 ast_channel_lock(chan); 08801 } 08802 if (chan) { 08803 if (chan->_state == AST_STATE_UP) { 08804 res = 0; 08805 ast_verb(4, "Channel %s was answered.\n", chan->name); 08806 08807 if (synchronous > 1) { 08808 if (channel) 08809 ast_channel_unlock(chan); 08810 if (ast_pbx_run(chan)) { 08811 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08812 if (channel) 08813 *channel = NULL; 08814 ast_hangup(chan); 08815 chan = NULL; 08816 res = -1; 08817 } 08818 } else { 08819 if (ast_pbx_start(chan)) { 08820 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 08821 if (channel) { 08822 *channel = NULL; 08823 ast_channel_unlock(chan); 08824 } 08825 ast_hangup(chan); 08826 res = -1; 08827 } 08828 chan = NULL; 08829 } 08830 } else { 08831 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08832 08833 if (chan->cdr) { /* update the cdr */ 08834 /* here we update the status of the call, which sould be busy. 08835 * if that fails then we set the status to failed */ 08836 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08837 ast_cdr_failed(chan->cdr); 08838 } 08839 08840 if (channel) { 08841 *channel = NULL; 08842 ast_channel_unlock(chan); 08843 } 08844 ast_hangup(chan); 08845 chan = NULL; 08846 } 08847 } 08848 08849 if (res < 0) { /* the call failed for some reason */ 08850 if (*reason == 0) { /* if the call failed (not busy or no answer) 08851 * update the cdr with the failed message */ 08852 cdr_res = ast_pbx_outgoing_cdr_failed(); 08853 if (cdr_res != 0) { 08854 res = cdr_res; 08855 goto outgoing_exten_cleanup; 08856 } 08857 } 08858 08859 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08860 /* check if "failed" exists */ 08861 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08862 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 08863 if (chan) { 08864 char failed_reason[4] = ""; 08865 if (!ast_strlen_zero(context)) 08866 ast_copy_string(chan->context, context, sizeof(chan->context)); 08867 set_ext_pri(chan, "failed", 1); 08868 ast_set_variables(chan, vars); 08869 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08870 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08871 if (account) 08872 ast_cdr_setaccount(chan, account); 08873 if (ast_pbx_run(chan)) { 08874 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08875 ast_hangup(chan); 08876 } 08877 chan = NULL; 08878 } 08879 } 08880 } 08881 } else { 08882 if (!(as = ast_calloc(1, sizeof(*as)))) { 08883 res = -1; 08884 goto outgoing_exten_cleanup; 08885 } 08886 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 08887 if (channel) { 08888 *channel = chan; 08889 if (chan) 08890 ast_channel_lock(chan); 08891 } 08892 if (!chan) { 08893 ast_free(as); 08894 res = -1; 08895 goto outgoing_exten_cleanup; 08896 } 08897 as->chan = chan; 08898 ast_copy_string(as->context, context, sizeof(as->context)); 08899 set_ext_pri(as->chan, exten, priority); 08900 as->timeout = timeout; 08901 ast_set_variables(chan, vars); 08902 if (account) 08903 ast_cdr_setaccount(chan, account); 08904 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08905 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08906 ast_free(as); 08907 if (channel) { 08908 *channel = NULL; 08909 ast_channel_unlock(chan); 08910 } 08911 ast_hangup(chan); 08912 res = -1; 08913 goto outgoing_exten_cleanup; 08914 } 08915 res = 0; 08916 } 08917 outgoing_exten_cleanup: 08918 ast_variables_destroy(vars); 08919 return res; 08920 }
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 |
Zero | on success | |
non-zero | on failure |
Definition at line 5382 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), do_notify(), mgcp_ss(), pri_ss_thread(), skinny_newcall(), and unistim_ss().
05383 { 05384 return ast_pbx_run_args(c, NULL); 05385 }
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 |
Zero | on success | |
non-zero | on failure |
Definition at line 5362 of file pbx.c.
References __ast_pbx_run(), args, 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(), and handle_gosub().
05363 { 05364 enum ast_pbx_result res = AST_PBX_SUCCESS; 05365 05366 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05367 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05368 return AST_PBX_FAILED; 05369 } 05370 05371 if (increase_call_count(c)) { 05372 return AST_PBX_CALL_LIMIT; 05373 } 05374 05375 res = __ast_pbx_run(c, args); 05376 05377 decrease_call_count(); 05378 05379 return res; 05380 }
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 5335 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(), rpt_call(), skinny_new(), ss7_start_call(), unistim_new(), and usbradio_new().
05336 { 05337 pthread_t t; 05338 05339 if (!c) { 05340 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05341 return AST_PBX_FAILED; 05342 } 05343 05344 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05345 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05346 return AST_PBX_FAILED; 05347 } 05348 05349 if (increase_call_count(c)) 05350 return AST_PBX_CALL_LIMIT; 05351 05352 /* Start a new thread, and get something handling this channel. */ 05353 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05354 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05355 decrease_call_count(); 05356 return AST_PBX_FAILED; 05357 } 05358 05359 return AST_PBX_SUCCESS; 05360 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5392 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05393 { 05394 return totalcalls; 05395 }
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 10341 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().
10342 { 10343 return ast_rwlock_rdlock(&con->lock); 10344 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10323 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().
10324 { 10325 return ast_mutex_lock(&conlock); 10326 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
0 | success | |
non-zero | failure |
Definition at line 5898 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_switch::list, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
05899 { 05900 struct ast_switch *tmp; 05901 05902 AST_RWLIST_WRLOCK(&switches); 05903 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05904 if (!strcasecmp(tmp->name, sw->name)) { 05905 AST_RWLIST_UNLOCK(&switches); 05906 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05907 return -1; 05908 } 05909 } 05910 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05911 AST_RWLIST_UNLOCK(&switches); 05912 05913 return 0; 05914 }
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 4885 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), and loopback_exec().
04886 { 04887 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04888 }
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 4840 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), ast_str_set(), and fake_context::name.
Referenced by ast_str_retrieve_variable().
04841 { 04842 struct ast_exten *e = ast_hint_extension(c, context, exten); 04843 04844 if (!e) { 04845 return 0; 04846 } 04847 04848 if (hint) { 04849 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 04850 } 04851 if (name) { 04852 const char *tmp = ast_get_extension_app_data(e); 04853 if (tmp) { 04854 ast_str_set(name, namesize, "%s", tmp); 04855 } 04856 } 04857 return -1; 04858 }
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 3130 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_channel::name, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, str, ast_party_dialed::transit_network_select, and ast_channel::uniqueid.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03131 { 03132 const char not_found = '\0'; 03133 char *tmpvar; 03134 const char *ret; 03135 const char *s; /* the result */ 03136 int offset, length; 03137 int i, need_substring; 03138 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03139 03140 if (c) { 03141 ast_channel_lock(c); 03142 places[0] = &c->varshead; 03143 } 03144 /* 03145 * Make a copy of var because parse_variable_name() modifies the string. 03146 * Then if called directly, we might need to run substring() on the result; 03147 * remember this for later in 'need_substring', 'offset' and 'length' 03148 */ 03149 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03150 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03151 03152 /* 03153 * Look first into predefined variables, then into variable lists. 03154 * Variable 's' points to the result, according to the following rules: 03155 * s == ¬_found (set at the beginning) means that we did not find a 03156 * matching variable and need to look into more places. 03157 * If s != ¬_found, s is a valid result string as follows: 03158 * s = NULL if the variable does not have a value; 03159 * you typically do this when looking for an unset predefined variable. 03160 * s = workspace if the result has been assembled there; 03161 * typically done when the result is built e.g. with an snprintf(), 03162 * so we don't need to do an additional copy. 03163 * s != workspace in case we have a string, that needs to be copied 03164 * (the ast_copy_string is done once for all at the end). 03165 * Typically done when the result is already available in some string. 03166 */ 03167 s = ¬_found; /* default value */ 03168 if (c) { /* This group requires a valid channel */ 03169 /* Names with common parts are looked up a piece at a time using strncmp. */ 03170 if (!strncmp(var, "CALL", 4)) { 03171 if (!strncmp(var + 4, "ING", 3)) { 03172 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03173 ast_str_set(str, maxlen, "%d", 03174 ast_party_id_presentation(&c->caller.id)); 03175 s = ast_str_buffer(*str); 03176 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03177 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03178 s = ast_str_buffer(*str); 03179 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03180 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03181 s = ast_str_buffer(*str); 03182 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03183 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03184 s = ast_str_buffer(*str); 03185 } 03186 } 03187 } else if (!strcmp(var, "HINT")) { 03188 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03189 } else if (!strcmp(var, "HINTNAME")) { 03190 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03191 } else if (!strcmp(var, "EXTEN")) { 03192 s = c->exten; 03193 } else if (!strcmp(var, "CONTEXT")) { 03194 s = c->context; 03195 } else if (!strcmp(var, "PRIORITY")) { 03196 ast_str_set(str, maxlen, "%d", c->priority); 03197 s = ast_str_buffer(*str); 03198 } else if (!strcmp(var, "CHANNEL")) { 03199 s = c->name; 03200 } else if (!strcmp(var, "UNIQUEID")) { 03201 s = c->uniqueid; 03202 } else if (!strcmp(var, "HANGUPCAUSE")) { 03203 ast_str_set(str, maxlen, "%d", c->hangupcause); 03204 s = ast_str_buffer(*str); 03205 } 03206 } 03207 if (s == ¬_found) { /* look for more */ 03208 if (!strcmp(var, "EPOCH")) { 03209 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03210 s = ast_str_buffer(*str); 03211 } else if (!strcmp(var, "SYSTEMNAME")) { 03212 s = ast_config_AST_SYSTEM_NAME; 03213 } else if (!strcmp(var, "ENTITYID")) { 03214 char workspace[20]; 03215 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03216 s = workspace; 03217 } 03218 } 03219 /* if not found, look into chanvars or global vars */ 03220 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03221 struct ast_var_t *variables; 03222 if (!places[i]) 03223 continue; 03224 if (places[i] == &globals) 03225 ast_rwlock_rdlock(&globalslock); 03226 AST_LIST_TRAVERSE(places[i], variables, entries) { 03227 if (!strcasecmp(ast_var_name(variables), var)) { 03228 s = ast_var_value(variables); 03229 break; 03230 } 03231 } 03232 if (places[i] == &globals) 03233 ast_rwlock_unlock(&globalslock); 03234 } 03235 if (s == ¬_found || s == NULL) { 03236 ast_debug(5, "Result of '%s' is NULL\n", var); 03237 ret = NULL; 03238 } else { 03239 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03240 if (s != ast_str_buffer(*str)) { 03241 ast_str_set(str, maxlen, "%s", s); 03242 } 03243 ret = ast_str_buffer(*str); 03244 if (need_substring) { 03245 ret = ast_str_substring(*str, offset, length); 03246 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03247 } 03248 } 03249 03250 if (c) { 03251 ast_channel_unlock(c); 03252 } 03253 return ret; 03254 }
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 3928 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_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().
03929 { 03930 size_t used; 03931 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 03932 }
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 3749 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().
03750 { 03751 /* Substitutes variables into buf, based on string templ */ 03752 char *cp4 = NULL; 03753 const char *tmp, *whereweare; 03754 int orig_size = 0; 03755 int offset, offset2, isfunction; 03756 const char *nextvar, *nextexp, *nextthing; 03757 const char *vars, *vare; 03758 char *finalvars; 03759 int pos, brackets, needsub, len; 03760 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03761 03762 ast_str_reset(*buf); 03763 whereweare = tmp = templ; 03764 while (!ast_strlen_zero(whereweare)) { 03765 /* reset our buffer */ 03766 ast_str_reset(substr3); 03767 03768 /* Assume we're copying the whole remaining string */ 03769 pos = strlen(whereweare); 03770 nextvar = NULL; 03771 nextexp = NULL; 03772 nextthing = strchr(whereweare, '$'); 03773 if (nextthing) { 03774 switch (nextthing[1]) { 03775 case '{': 03776 nextvar = nextthing; 03777 pos = nextvar - whereweare; 03778 break; 03779 case '[': 03780 nextexp = nextthing; 03781 pos = nextexp - whereweare; 03782 break; 03783 default: 03784 pos = 1; 03785 } 03786 } 03787 03788 if (pos) { 03789 /* Copy that many bytes */ 03790 ast_str_append_substr(buf, maxlen, whereweare, pos); 03791 03792 templ += pos; 03793 whereweare += pos; 03794 } 03795 03796 if (nextvar) { 03797 /* We have a variable. Find the start and end, and determine 03798 if we are going to have to recursively call ourselves on the 03799 contents */ 03800 vars = vare = nextvar + 2; 03801 brackets = 1; 03802 needsub = 0; 03803 03804 /* Find the end of it */ 03805 while (brackets && *vare) { 03806 if ((vare[0] == '$') && (vare[1] == '{')) { 03807 needsub++; 03808 } else if (vare[0] == '{') { 03809 brackets++; 03810 } else if (vare[0] == '}') { 03811 brackets--; 03812 } else if ((vare[0] == '$') && (vare[1] == '[')) 03813 needsub++; 03814 vare++; 03815 } 03816 if (brackets) 03817 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03818 len = vare - vars - 1; 03819 03820 /* Skip totally over variable string */ 03821 whereweare += (len + 3); 03822 03823 /* Store variable name (and truncate) */ 03824 ast_str_set_substr(&substr1, 0, vars, len); 03825 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03826 03827 /* Substitute if necessary */ 03828 if (needsub) { 03829 size_t used; 03830 if (!substr2) { 03831 substr2 = ast_str_create(16); 03832 } 03833 03834 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03835 finalvars = ast_str_buffer(substr2); 03836 } else { 03837 finalvars = ast_str_buffer(substr1); 03838 } 03839 03840 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03841 if (isfunction) { 03842 /* Evaluate function */ 03843 if (c || !headp) { 03844 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03845 } else { 03846 struct varshead old; 03847 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03848 if (bogus) { 03849 memcpy(&old, &bogus->varshead, sizeof(old)); 03850 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03851 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03852 /* Don't deallocate the varshead that was passed in */ 03853 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03854 ast_channel_unref(bogus); 03855 } else { 03856 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03857 } 03858 } 03859 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03860 } else { 03861 /* Retrieve variable value */ 03862 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 03863 cp4 = ast_str_buffer(substr3); 03864 } 03865 if (cp4) { 03866 ast_str_substring(substr3, offset, offset2); 03867 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03868 } 03869 } else if (nextexp) { 03870 /* We have an expression. Find the start and end, and determine 03871 if we are going to have to recursively call ourselves on the 03872 contents */ 03873 vars = vare = nextexp + 2; 03874 brackets = 1; 03875 needsub = 0; 03876 03877 /* Find the end of it */ 03878 while (brackets && *vare) { 03879 if ((vare[0] == '$') && (vare[1] == '[')) { 03880 needsub++; 03881 brackets++; 03882 vare++; 03883 } else if (vare[0] == '[') { 03884 brackets++; 03885 } else if (vare[0] == ']') { 03886 brackets--; 03887 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03888 needsub++; 03889 vare++; 03890 } 03891 vare++; 03892 } 03893 if (brackets) 03894 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03895 len = vare - vars - 1; 03896 03897 /* Skip totally over expression */ 03898 whereweare += (len + 3); 03899 03900 /* Store variable name (and truncate) */ 03901 ast_str_set_substr(&substr1, 0, vars, len); 03902 03903 /* Substitute if necessary */ 03904 if (needsub) { 03905 size_t used; 03906 if (!substr2) { 03907 substr2 = ast_str_create(16); 03908 } 03909 03910 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03911 finalvars = ast_str_buffer(substr2); 03912 } else { 03913 finalvars = ast_str_buffer(substr1); 03914 } 03915 03916 if (ast_str_expr(&substr3, 0, c, finalvars)) { 03917 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 03918 } 03919 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03920 } 03921 } 03922 *used = ast_str_strlen(*buf) - orig_size; 03923 ast_free(substr1); 03924 ast_free(substr2); 03925 ast_free(substr3); 03926 }
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 3934 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().
03935 { 03936 size_t used; 03937 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 03938 }
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 10346 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().
10347 { 10348 return ast_rwlock_unlock(&con->lock); 10349 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10328 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().
10329 { 10330 return ast_mutex_unlock(&conlock); 10331 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 5916 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_switch::list.
Referenced by __unload_module(), and unload_module().
05917 { 05918 AST_RWLIST_WRLOCK(&switches); 05919 AST_RWLIST_REMOVE(&switches, sw, list); 05920 AST_RWLIST_UNLOCK(&switches); 05921 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) |
Definition at line 10460 of file pbx.c.
References exten, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
10462 { 10463 if (!exten) 10464 return con ? con->root : NULL; 10465 else 10466 return exten->next; 10467 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 10493 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(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10495 { 10496 if (!ip) 10497 return con ? con->ignorepats : NULL; 10498 else 10499 return ip->next; 10500 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 10484 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(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
10486 { 10487 if (!inc) 10488 return con ? con->includes : NULL; 10489 else 10490 return inc->next; 10491 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 10469 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, AST_LIST_NEXT, and ast_sw::list.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10471 { 10472 if (!sw) 10473 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10474 else 10475 return AST_LIST_NEXT(sw, list); 10476 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 10455 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 | |||
) |
Definition at line 10478 of file pbx.c.
References exten, and ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
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 10336 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().
10337 { 10338 return ast_rwlock_wrlock(&con->lock); 10339 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10318 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().
10319 { 10320 return ast_mutex_lock(&conlock); 10321 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10112 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), ast_var_t::entries, globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), and reload().
10113 { 10114 struct ast_var_t *vardata; 10115 10116 ast_rwlock_wrlock(&globalslock); 10117 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10118 ast_var_delete(vardata); 10119 ast_rwlock_unlock(&globalslock); 10120 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Return a pointer to the value of the corresponding channel variable.
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
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 9874 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, and globalslock.
Referenced by _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(), dahdi_r2_answer(), dahdi_r2_get_channel_category(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), 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(), sig_pri_call(), sig_pri_hangup(), sig_ss7_call(), sig_ss7_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().
09875 { 09876 struct ast_var_t *variables; 09877 const char *ret = NULL; 09878 int i; 09879 struct varshead *places[2] = { NULL, &globals }; 09880 09881 if (!name) 09882 return NULL; 09883 09884 if (chan) { 09885 ast_channel_lock(chan); 09886 places[0] = &chan->varshead; 09887 } 09888 09889 for (i = 0; i < 2; i++) { 09890 if (!places[i]) 09891 continue; 09892 if (places[i] == &globals) 09893 ast_rwlock_rdlock(&globalslock); 09894 AST_LIST_TRAVERSE(places[i], variables, entries) { 09895 if (!strcmp(name, ast_var_name(variables))) { 09896 ret = ast_var_value(variables); 09897 break; 09898 } 09899 } 09900 if (places[i] == &globals) 09901 ast_rwlock_unlock(&globalslock); 09902 if (ret) 09903 break; 09904 } 09905 09906 if (chan) 09907 ast_channel_unlock(chan); 09908 09909 return ret; 09910 }
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 9912 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, and LOG_WARNING.
Referenced by acf_odbc_read(), acf_odbc_write(), and frame_set_var().
09913 { 09914 struct ast_var_t *newvariable; 09915 struct varshead *headp; 09916 09917 if (name[strlen(name)-1] == ')') { 09918 char *function = ast_strdupa(name); 09919 09920 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 09921 ast_func_write(chan, function, value); 09922 return; 09923 } 09924 09925 if (chan) { 09926 ast_channel_lock(chan); 09927 headp = &chan->varshead; 09928 } else { 09929 ast_rwlock_wrlock(&globalslock); 09930 headp = &globals; 09931 } 09932 09933 if (value) { 09934 if (headp == &globals) 09935 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09936 newvariable = ast_var_assign(name, value); 09937 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09938 } 09939 09940 if (chan) 09941 ast_channel_unlock(chan); 09942 else 09943 ast_rwlock_unlock(&globalslock); 09944 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Definition at line 3305 of file pbx.c.
References raise_exception().
03306 { 03307 /* Priority will become 1, next time through the AUTOLOOP */ 03308 return raise_exception(chan, reason, 0); 03309 }
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 9843 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(), ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
09844 { 09845 struct ast_var_t *variables; 09846 const char *var, *val; 09847 int total = 0; 09848 09849 if (!chan) 09850 return 0; 09851 09852 ast_str_reset(*buf); 09853 09854 ast_channel_lock(chan); 09855 09856 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 09857 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 09858 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 09859 ) { 09860 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 09861 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 09862 break; 09863 } else 09864 total++; 09865 } else 09866 break; 09867 } 09868 09869 ast_channel_unlock(chan); 09870 09871 return total; 09872 }
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 10004 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(), strsep(), and value.
Referenced by ast_compile_ael2(), and rpt_exec().
10005 { 10006 char *name, *value, *mydata; 10007 10008 if (ast_compat_app_set) { 10009 return pbx_builtin_setvar_multiple(chan, data); 10010 } 10011 10012 if (ast_strlen_zero(data)) { 10013 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10014 return 0; 10015 } 10016 10017 mydata = ast_strdupa(data); 10018 name = strsep(&mydata, "="); 10019 value = mydata; 10020 if (!value) { 10021 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10022 return 0; 10023 } 10024 10025 if (strchr(name, ' ')) { 10026 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10027 } 10028 10029 pbx_builtin_setvar_helper(chan, name, value); 10030 10031 return 0; 10032 }
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 9946 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, ast_channel::name, and ast_channel::uniqueid.
Referenced by __analog_ss_thread(), __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(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sig_pri_new_ast_channel(), sig_ss7_new_ast_channel(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss7_start_call(), 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().
09947 { 09948 struct ast_var_t *newvariable; 09949 struct varshead *headp; 09950 const char *nametail = name; 09951 09952 if (name[strlen(name) - 1] == ')') { 09953 char *function = ast_strdupa(name); 09954 09955 return ast_func_write(chan, function, value); 09956 } 09957 09958 if (chan) { 09959 ast_channel_lock(chan); 09960 headp = &chan->varshead; 09961 } else { 09962 ast_rwlock_wrlock(&globalslock); 09963 headp = &globals; 09964 } 09965 09966 /* For comparison purposes, we have to strip leading underscores */ 09967 if (*nametail == '_') { 09968 nametail++; 09969 if (*nametail == '_') 09970 nametail++; 09971 } 09972 09973 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 09974 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 09975 /* there is already such a variable, delete it */ 09976 AST_LIST_REMOVE_CURRENT(entries); 09977 ast_var_delete(newvariable); 09978 break; 09979 } 09980 } 09981 AST_LIST_TRAVERSE_SAFE_END; 09982 09983 if (value) { 09984 if (headp == &globals) 09985 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09986 newvariable = ast_var_assign(name, value); 09987 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09988 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 09989 "Channel: %s\r\n" 09990 "Variable: %s\r\n" 09991 "Value: %s\r\n" 09992 "Uniqueid: %s\r\n", 09993 chan ? chan->name : "none", name, value, 09994 chan ? chan->uniqueid : "none"); 09995 } 09996 09997 if (chan) 09998 ast_channel_unlock(chan); 09999 else 10000 ast_rwlock_unlock(&globalslock); 10001 return 0; 10002 }
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 10034 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, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), and set_queue_variables().
10035 { 10036 char *data; 10037 int x; 10038 AST_DECLARE_APP_ARGS(args, 10039 AST_APP_ARG(pair)[24]; 10040 ); 10041 AST_DECLARE_APP_ARGS(pair, 10042 AST_APP_ARG(name); 10043 AST_APP_ARG(value); 10044 ); 10045 10046 if (ast_strlen_zero(vdata)) { 10047 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10048 return 0; 10049 } 10050 10051 data = ast_strdupa(vdata); 10052 AST_STANDARD_APP_ARGS(args, data); 10053 10054 for (x = 0; x < args.argc; x++) { 10055 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10056 if (pair.argc == 2) { 10057 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10058 if (strchr(pair.name, ' ')) 10059 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); 10060 } else if (!chan) { 10061 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10062 } else { 10063 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10064 } 10065 } 10066 10067 return 0; 10068 }
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 10122 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().
10123 { 10124 int res; 10125 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10126 return 0; 10127 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10128 return res; 10129 } else { /* Strings are true */ 10130 return 1; 10131 } 10132 }
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 |
0 | success | |
-1 | failure |
c | Channel |
app | Application |
data | Data for execution |
Definition at line 1402 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), app, 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, LOG_WARNING, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
01405 { 01406 int res; 01407 struct ast_module_user *u = NULL; 01408 const char *saved_c_appl; 01409 const char *saved_c_data; 01410 01411 if (c->cdr && !ast_check_hangup(c)) 01412 ast_cdr_setapp(c->cdr, app->name, data); 01413 01414 /* save channel values */ 01415 saved_c_appl= c->appl; 01416 saved_c_data= c->data; 01417 01418 c->appl = app->name; 01419 c->data = data; 01420 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01421 01422 if (app->module) 01423 u = __ast_module_user_add(app->module, c); 01424 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01425 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01426 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01427 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01428 app->name, (char *) data); 01429 } 01430 res = app->execute(c, S_OR(data, "")); 01431 if (app->module && u) 01432 __ast_module_user_remove(app->module, u); 01433 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01434 /* restore channel values */ 01435 c->appl = saved_c_appl; 01436 c->data = saved_c_data; 01437 return res; 01438 }
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 | |||
) |
Definition at line 2698 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(), pbx_find_info::data, ast_sw::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, scoreboard::exten, ast_exten::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_sw::name, ast_context::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, strsep(), 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().
02702 { 02703 int x, res; 02704 struct ast_context *tmp = NULL; 02705 struct ast_exten *e = NULL, *eroot = NULL; 02706 struct ast_include *i = NULL; 02707 struct ast_sw *sw = NULL; 02708 struct ast_exten pattern = {NULL, }; 02709 struct scoreboard score = {0, }; 02710 struct ast_str *tmpdata = NULL; 02711 02712 pattern.label = label; 02713 pattern.priority = priority; 02714 #ifdef NEED_DEBUG_HERE 02715 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02716 #endif 02717 02718 /* Initialize status if appropriate */ 02719 if (q->stacklen == 0) { 02720 q->status = STATUS_NO_CONTEXT; 02721 q->swo = NULL; 02722 q->data = NULL; 02723 q->foundcontext = NULL; 02724 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02725 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02726 return NULL; 02727 } 02728 02729 /* Check first to see if we've already been checked */ 02730 for (x = 0; x < q->stacklen; x++) { 02731 if (!strcasecmp(q->incstack[x], context)) 02732 return NULL; 02733 } 02734 02735 if (bypass) { /* bypass means we only look there */ 02736 tmp = bypass; 02737 } else { /* look in contexts */ 02738 tmp = find_context(context); 02739 if (!tmp) { 02740 return NULL; 02741 } 02742 } 02743 02744 if (q->status < STATUS_NO_EXTENSION) 02745 q->status = STATUS_NO_EXTENSION; 02746 02747 /* Do a search for matching extension */ 02748 02749 eroot = NULL; 02750 score.total_specificity = 0; 02751 score.exten = 0; 02752 score.total_length = 0; 02753 if (!tmp->pattern_tree && tmp->root_table) { 02754 create_match_char_tree(tmp); 02755 #ifdef NEED_DEBUG 02756 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02757 log_match_char_tree(tmp->pattern_tree," "); 02758 #endif 02759 } 02760 #ifdef NEED_DEBUG 02761 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02762 log_match_char_tree(tmp->pattern_tree, ":: "); 02763 #endif 02764 02765 do { 02766 if (!ast_strlen_zero(overrideswitch)) { 02767 char *osw = ast_strdupa(overrideswitch), *name; 02768 struct ast_switch *asw; 02769 ast_switch_f *aswf = NULL; 02770 char *datap; 02771 int eval = 0; 02772 02773 name = strsep(&osw, "/"); 02774 asw = pbx_findswitch(name); 02775 02776 if (!asw) { 02777 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02778 break; 02779 } 02780 02781 if (osw && strchr(osw, '$')) { 02782 eval = 1; 02783 } 02784 02785 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02786 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02787 break; 02788 } else if (eval) { 02789 /* Substitute variables now */ 02790 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02791 datap = ast_str_buffer(tmpdata); 02792 } else { 02793 datap = osw; 02794 } 02795 02796 /* equivalent of extension_match_core() at the switch level */ 02797 if (action == E_CANMATCH) 02798 aswf = asw->canmatch; 02799 else if (action == E_MATCHMORE) 02800 aswf = asw->matchmore; 02801 else /* action == E_MATCH */ 02802 aswf = asw->exists; 02803 if (!aswf) { 02804 res = 0; 02805 } else { 02806 if (chan) { 02807 ast_autoservice_start(chan); 02808 } 02809 res = aswf(chan, context, exten, priority, callerid, datap); 02810 if (chan) { 02811 ast_autoservice_stop(chan); 02812 } 02813 } 02814 if (res) { /* Got a match */ 02815 q->swo = asw; 02816 q->data = datap; 02817 q->foundcontext = context; 02818 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02819 return NULL; 02820 } 02821 } 02822 } while (0); 02823 02824 if (extenpatternmatchnew) { 02825 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02826 eroot = score.exten; 02827 02828 if (score.last_char == '!' && action == E_MATCHMORE) { 02829 /* We match an extension ending in '!'. 02830 * The decision in this case is final and is NULL (no match). 02831 */ 02832 #ifdef NEED_DEBUG_HERE 02833 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02834 #endif 02835 return NULL; 02836 } 02837 02838 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02839 q->status = STATUS_SUCCESS; 02840 #ifdef NEED_DEBUG_HERE 02841 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02842 #endif 02843 return score.canmatch_exten; 02844 } 02845 02846 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02847 if (score.node) { 02848 struct ast_exten *z = trie_find_next_match(score.node); 02849 if (z) { 02850 #ifdef NEED_DEBUG_HERE 02851 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02852 #endif 02853 } else { 02854 if (score.canmatch_exten) { 02855 #ifdef NEED_DEBUG_HERE 02856 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02857 #endif 02858 return score.canmatch_exten; 02859 } else { 02860 #ifdef NEED_DEBUG_HERE 02861 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02862 #endif 02863 } 02864 } 02865 return z; 02866 } 02867 #ifdef NEED_DEBUG_HERE 02868 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02869 #endif 02870 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02871 } 02872 02873 if (eroot) { 02874 /* found entry, now look for the right priority */ 02875 if (q->status < STATUS_NO_PRIORITY) 02876 q->status = STATUS_NO_PRIORITY; 02877 e = NULL; 02878 if (action == E_FINDLABEL && label ) { 02879 if (q->status < STATUS_NO_LABEL) 02880 q->status = STATUS_NO_LABEL; 02881 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02882 } else { 02883 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02884 } 02885 if (e) { /* found a valid match */ 02886 q->status = STATUS_SUCCESS; 02887 q->foundcontext = context; 02888 #ifdef NEED_DEBUG_HERE 02889 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02890 #endif 02891 return e; 02892 } 02893 } 02894 } else { /* the old/current default exten pattern match algorithm */ 02895 02896 /* scan the list trying to match extension and CID */ 02897 eroot = NULL; 02898 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02899 int match = extension_match_core(eroot->exten, exten, action); 02900 /* 0 on fail, 1 on match, 2 on earlymatch */ 02901 02902 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02903 continue; /* keep trying */ 02904 if (match == 2 && action == E_MATCHMORE) { 02905 /* We match an extension ending in '!'. 02906 * The decision in this case is final and is NULL (no match). 02907 */ 02908 return NULL; 02909 } 02910 /* found entry, now look for the right priority */ 02911 if (q->status < STATUS_NO_PRIORITY) 02912 q->status = STATUS_NO_PRIORITY; 02913 e = NULL; 02914 if (action == E_FINDLABEL && label ) { 02915 if (q->status < STATUS_NO_LABEL) 02916 q->status = STATUS_NO_LABEL; 02917 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02918 } else { 02919 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02920 } 02921 if (e) { /* found a valid match */ 02922 q->status = STATUS_SUCCESS; 02923 q->foundcontext = context; 02924 return e; 02925 } 02926 } 02927 } 02928 02929 /* Check alternative switches */ 02930 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02931 struct ast_switch *asw = pbx_findswitch(sw->name); 02932 ast_switch_f *aswf = NULL; 02933 char *datap; 02934 02935 if (!asw) { 02936 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02937 continue; 02938 } 02939 02940 /* Substitute variables now */ 02941 if (sw->eval) { 02942 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02943 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02944 continue; 02945 } 02946 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02947 } 02948 02949 /* equivalent of extension_match_core() at the switch level */ 02950 if (action == E_CANMATCH) 02951 aswf = asw->canmatch; 02952 else if (action == E_MATCHMORE) 02953 aswf = asw->matchmore; 02954 else /* action == E_MATCH */ 02955 aswf = asw->exists; 02956 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02957 if (!aswf) 02958 res = 0; 02959 else { 02960 if (chan) 02961 ast_autoservice_start(chan); 02962 res = aswf(chan, context, exten, priority, callerid, datap); 02963 if (chan) 02964 ast_autoservice_stop(chan); 02965 } 02966 if (res) { /* Got a match */ 02967 q->swo = asw; 02968 q->data = datap; 02969 q->foundcontext = context; 02970 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02971 return NULL; 02972 } 02973 } 02974 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02975 /* Now try any includes we have in this context */ 02976 for (i = tmp->includes; i; i = i->next) { 02977 if (include_valid(i)) { 02978 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02979 #ifdef NEED_DEBUG_HERE 02980 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02981 #endif 02982 return e; 02983 } 02984 if (q->swo) 02985 return NULL; 02986 } 02987 } 02988 return NULL; 02989 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 1446 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_app::list, and ast_app::name.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
01447 { 01448 struct ast_app *tmp; 01449 01450 AST_RWLIST_RDLOCK(&apps); 01451 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01452 if (!strcasecmp(tmp->name, app)) 01453 break; 01454 } 01455 AST_RWLIST_UNLOCK(&apps); 01456 01457 return tmp; 01458 }
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.
Definition at line 3119 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().
03120 { 03121 struct ast_str *str = ast_str_create(16); 03122 const char *cret; 03123 03124 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03125 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03126 *ret = cret ? workspace : NULL; 03127 ast_free(str); 03128 }
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 5397 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05398 { 05399 int oldval = autofallthrough; 05400 autofallthrough = newval; 05401 return oldval; 05402 }
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 5404 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05405 { 05406 int oldval = extenpatternmatchnew; 05407 extenpatternmatchnew = newval; 05408 return oldval; 05409 }
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 5411 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05412 { 05413 if (overrideswitch) { 05414 ast_free(overrideswitch); 05415 } 05416 if (!ast_strlen_zero(newval)) { 05417 overrideswitch = ast_strdup(newval); 05418 } else { 05419 overrideswitch = NULL; 05420 } 05421 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4136 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_find_extension(), pbx_load_config(), pbx_substitute_variables(), rotate_file(), rpt_do_lstats(), rpt_exec(), substituted(), and write_cdr().
04137 { 04138 size_t used; 04139 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04140 }
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 3940 of file pbx.c.
References 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().
03941 { 03942 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03943 char *cp4 = NULL; 03944 const char *tmp, *whereweare, *orig_cp2 = cp2; 03945 int length, offset, offset2, isfunction; 03946 char *workspace = NULL; 03947 char *ltmp = NULL, *var = NULL; 03948 char *nextvar, *nextexp, *nextthing; 03949 char *vars, *vare; 03950 int pos, brackets, needsub, len; 03951 03952 *cp2 = 0; /* just in case nothing ends up there */ 03953 whereweare=tmp=cp1; 03954 while (!ast_strlen_zero(whereweare) && count) { 03955 /* Assume we're copying the whole remaining string */ 03956 pos = strlen(whereweare); 03957 nextvar = NULL; 03958 nextexp = NULL; 03959 nextthing = strchr(whereweare, '$'); 03960 if (nextthing) { 03961 switch (nextthing[1]) { 03962 case '{': 03963 nextvar = nextthing; 03964 pos = nextvar - whereweare; 03965 break; 03966 case '[': 03967 nextexp = nextthing; 03968 pos = nextexp - whereweare; 03969 break; 03970 default: 03971 pos = 1; 03972 } 03973 } 03974 03975 if (pos) { 03976 /* Can't copy more than 'count' bytes */ 03977 if (pos > count) 03978 pos = count; 03979 03980 /* Copy that many bytes */ 03981 memcpy(cp2, whereweare, pos); 03982 03983 count -= pos; 03984 cp2 += pos; 03985 whereweare += pos; 03986 *cp2 = 0; 03987 } 03988 03989 if (nextvar) { 03990 /* We have a variable. Find the start and end, and determine 03991 if we are going to have to recursively call ourselves on the 03992 contents */ 03993 vars = vare = nextvar + 2; 03994 brackets = 1; 03995 needsub = 0; 03996 03997 /* Find the end of it */ 03998 while (brackets && *vare) { 03999 if ((vare[0] == '$') && (vare[1] == '{')) { 04000 needsub++; 04001 } else if (vare[0] == '{') { 04002 brackets++; 04003 } else if (vare[0] == '}') { 04004 brackets--; 04005 } else if ((vare[0] == '$') && (vare[1] == '[')) 04006 needsub++; 04007 vare++; 04008 } 04009 if (brackets) 04010 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04011 len = vare - vars - 1; 04012 04013 /* Skip totally over variable string */ 04014 whereweare += (len + 3); 04015 04016 if (!var) 04017 var = alloca(VAR_BUF_SIZE); 04018 04019 /* Store variable name (and truncate) */ 04020 ast_copy_string(var, vars, len + 1); 04021 04022 /* Substitute if necessary */ 04023 if (needsub) { 04024 size_t used; 04025 if (!ltmp) 04026 ltmp = alloca(VAR_BUF_SIZE); 04027 04028 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04029 vars = ltmp; 04030 } else { 04031 vars = var; 04032 } 04033 04034 if (!workspace) 04035 workspace = alloca(VAR_BUF_SIZE); 04036 04037 workspace[0] = '\0'; 04038 04039 parse_variable_name(vars, &offset, &offset2, &isfunction); 04040 if (isfunction) { 04041 /* Evaluate function */ 04042 if (c || !headp) 04043 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04044 else { 04045 struct varshead old; 04046 struct ast_channel *c = ast_dummy_channel_alloc(); 04047 if (c) { 04048 memcpy(&old, &c->varshead, sizeof(old)); 04049 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04050 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04051 /* Don't deallocate the varshead that was passed in */ 04052 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04053 c = ast_channel_unref(c); 04054 } else { 04055 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04056 } 04057 } 04058 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04059 } else { 04060 /* Retrieve variable value */ 04061 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04062 } 04063 if (cp4) { 04064 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04065 04066 length = strlen(cp4); 04067 if (length > count) 04068 length = count; 04069 memcpy(cp2, cp4, length); 04070 count -= length; 04071 cp2 += length; 04072 *cp2 = 0; 04073 } 04074 } else if (nextexp) { 04075 /* We have an expression. Find the start and end, and determine 04076 if we are going to have to recursively call ourselves on the 04077 contents */ 04078 vars = vare = nextexp + 2; 04079 brackets = 1; 04080 needsub = 0; 04081 04082 /* Find the end of it */ 04083 while (brackets && *vare) { 04084 if ((vare[0] == '$') && (vare[1] == '[')) { 04085 needsub++; 04086 brackets++; 04087 vare++; 04088 } else if (vare[0] == '[') { 04089 brackets++; 04090 } else if (vare[0] == ']') { 04091 brackets--; 04092 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04093 needsub++; 04094 vare++; 04095 } 04096 vare++; 04097 } 04098 if (brackets) 04099 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04100 len = vare - vars - 1; 04101 04102 /* Skip totally over expression */ 04103 whereweare += (len + 3); 04104 04105 if (!var) 04106 var = alloca(VAR_BUF_SIZE); 04107 04108 /* Store variable name (and truncate) */ 04109 ast_copy_string(var, vars, len + 1); 04110 04111 /* Substitute if necessary */ 04112 if (needsub) { 04113 size_t used; 04114 if (!ltmp) 04115 ltmp = alloca(VAR_BUF_SIZE); 04116 04117 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04118 vars = ltmp; 04119 } else { 04120 vars = var; 04121 } 04122 04123 length = ast_expr(vars, cp2, count, c); 04124 04125 if (length) { 04126 ast_debug(1, "Expression result is '%s'\n", cp2); 04127 count -= length; 04128 cp2 += length; 04129 *cp2 = 0; 04130 } 04131 } 04132 } 04133 *used = cp2 - orig_cp2; 04134 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4142 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by dundi_lookup_local(), and loopback_subst().
04143 { 04144 size_t used; 04145 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04146 }