#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 3591 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().
03592 { 03593 struct ast_custom_function *cur; 03594 char tmps[80]; 03595 03596 if (!acf) { 03597 return -1; 03598 } 03599 03600 acf->mod = mod; 03601 #ifdef AST_XML_DOCS 03602 acf->docsrc = AST_STATIC_DOC; 03603 #endif 03604 03605 if (acf_retrieve_docs(acf)) { 03606 return -1; 03607 } 03608 03609 AST_RWLIST_WRLOCK(&acf_root); 03610 03611 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03612 if (!strcmp(acf->name, cur->name)) { 03613 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03614 AST_RWLIST_UNLOCK(&acf_root); 03615 return -1; 03616 } 03617 } 03618 03619 /* Store in alphabetical order */ 03620 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03621 if (strcasecmp(acf->name, cur->name) < 0) { 03622 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03623 break; 03624 } 03625 } 03626 AST_RWLIST_TRAVERSE_SAFE_END; 03627 03628 if (!cur) { 03629 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03630 } 03631 03632 AST_RWLIST_UNLOCK(&acf_root); 03633 03634 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03635 03636 return 0; 03637 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5405 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05406 { 05407 return countcalls; 05408 }
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 8135 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().
08138 { 08139 int ret = -1; 08140 struct ast_context *c; 08141 08142 c = find_context_locked(context); 08143 if (c) { 08144 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08145 application, data, datad, registrar); 08146 ast_unlock_contexts(); 08147 } 08148 08149 return ret; 08150 }
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 8481 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), and pbx_load_users().
08485 { 08486 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08487 application, data, datad, registrar, 1); 08488 }
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 8175 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().
08176 { 08177 int res = 0; 08178 struct ast_channel *tmpchan; 08179 struct { 08180 char *accountcode; 08181 char *exten; 08182 char *context; 08183 char *linkedid; 08184 char *name; 08185 struct ast_cdr *cdr; 08186 int amaflags; 08187 int state; 08188 format_t readformat; 08189 format_t writeformat; 08190 } tmpvars = { 0, }; 08191 08192 ast_channel_lock(chan); 08193 if (chan->pbx) { /* This channel is currently in the PBX */ 08194 ast_explicit_goto(chan, context, exten, priority + 1); 08195 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08196 ast_channel_unlock(chan); 08197 return res; 08198 } 08199 08200 /* In order to do it when the channel doesn't really exist within 08201 * the PBX, we have to make a new channel, masquerade, and start the PBX 08202 * at the new location */ 08203 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08204 tmpvars.exten = ast_strdupa(chan->exten); 08205 tmpvars.context = ast_strdupa(chan->context); 08206 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08207 tmpvars.name = ast_strdupa(chan->name); 08208 tmpvars.amaflags = chan->amaflags; 08209 tmpvars.state = chan->_state; 08210 tmpvars.writeformat = chan->writeformat; 08211 tmpvars.readformat = chan->readformat; 08212 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08213 08214 ast_channel_unlock(chan); 08215 08216 /* Do not hold any channel locks while calling channel_alloc() since the function 08217 * locks the channel container when linking the new channel in. */ 08218 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08219 ast_cdr_discard(tmpvars.cdr); 08220 return -1; 08221 } 08222 08223 /* copy the cdr info over */ 08224 if (tmpvars.cdr) { 08225 ast_cdr_discard(tmpchan->cdr); 08226 tmpchan->cdr = tmpvars.cdr; 08227 tmpvars.cdr = NULL; 08228 } 08229 08230 /* Make formats okay */ 08231 tmpchan->readformat = tmpvars.readformat; 08232 tmpchan->writeformat = tmpvars.writeformat; 08233 08234 /* Setup proper location. Never hold another channel lock while calling this function. */ 08235 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08236 08237 /* Masquerade into tmp channel */ 08238 if (ast_channel_masquerade(tmpchan, chan)) { 08239 /* Failed to set up the masquerade. It's probably chan_local 08240 * in the middle of optimizing itself out. Sad. :( */ 08241 ast_hangup(tmpchan); 08242 tmpchan = NULL; 08243 res = -1; 08244 } else { 08245 ast_do_masquerade(tmpchan); 08246 /* Start the PBX going on our stolen channel */ 08247 if (ast_pbx_start(tmpchan)) { 08248 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08249 ast_hangup(tmpchan); 08250 res = -1; 08251 } 08252 } 08253 08254 return res; 08255 }
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 8257 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08258 { 08259 struct ast_channel *chan; 08260 int res = -1; 08261 08262 if ((chan = ast_channel_get_by_name(channame))) { 08263 res = ast_async_goto(chan, context, exten, priority); 08264 chan = ast_channel_unref(chan); 08265 } 08266 08267 return res; 08268 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10575 of file pbx.c.
References __ast_goto_if_exists().
10576 { 10577 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10578 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10640 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10641 { 10642 return pbx_parseable_goto(chan, goto_string, 1); 10643 }
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 7758 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().
07759 { 07760 char *info; 07761 int j, num_fields, last_sep = -1; 07762 07763 /* Check for empty just in case */ 07764 if (ast_strlen_zero(info_in)) { 07765 return 0; 07766 } 07767 07768 /* make a copy just in case we were passed a static string */ 07769 info = ast_strdupa(info_in); 07770 07771 /* count the number of fields in the timespec */ 07772 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07773 if (info[j] == ',') { 07774 last_sep = j; 07775 num_fields++; 07776 } 07777 } 07778 07779 /* save the timezone, if it is specified */ 07780 if (num_fields == 5) { 07781 i->timezone = ast_strdup(info + last_sep + 1); 07782 } else { 07783 i->timezone = NULL; 07784 } 07785 07786 /* Assume everything except time */ 07787 i->monthmask = 0xfff; /* 12 bits */ 07788 i->daymask = 0x7fffffffU; /* 31 bits */ 07789 i->dowmask = 0x7f; /* 7 bits */ 07790 /* on each call, use strsep() to move info to the next argument */ 07791 get_timerange(i, strsep(&info, "|,")); 07792 if (info) 07793 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07794 if (info) 07795 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07796 if (info) 07797 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07798 return 1; 07799 }
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 4892 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
04893 { 04894 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04895 }
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 7801 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07802 { 07803 return ast_check_timing2(i, ast_tvnow()); 07804 }
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 7806 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().
07807 { 07808 struct ast_tm tm; 07809 07810 ast_localtime(&tv, &tm, i->timezone); 07811 07812 /* If it's not the right month, return */ 07813 if (!(i->monthmask & (1 << tm.tm_mon))) 07814 return 0; 07815 07816 /* If it's not that time of the month.... */ 07817 /* Warning, tm_mday has range 1..31! */ 07818 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07819 return 0; 07820 07821 /* If it's not the right day of the week */ 07822 if (!(i->dowmask & (1 << tm.tm_wday))) 07823 return 0; 07824 07825 /* Sanity check the hour just to be safe */ 07826 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07827 ast_log(LOG_WARNING, "Insane time...\n"); 07828 return 0; 07829 } 07830 07831 /* Now the tough part, we calculate if it fits 07832 in the right time based on min/hour */ 07833 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)))) 07834 return 0; 07835 07836 /* If we got this far, then we're good */ 07837 return 1; 07838 }
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 10645 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().
10646 { 10647 struct ast_app *app = NULL; 10648 int which = 0; 10649 char *ret = NULL; 10650 size_t wordlen = strlen(word); 10651 10652 AST_RWLIST_RDLOCK(&apps); 10653 AST_RWLIST_TRAVERSE(&apps, app, list) { 10654 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10655 ret = ast_strdup(app->name); 10656 break; 10657 } 10658 } 10659 AST_RWLIST_UNLOCK(&apps); 10660 10661 return ret; 10662 }
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 8042 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08043 { 08044 int ret = -1; 08045 struct ast_context *c; 08046 08047 c = find_context_locked(context); 08048 if (c) { 08049 ret = ast_context_add_ignorepat2(c, value, registrar); 08050 ast_unlock_contexts(); 08051 } 08052 return ret; 08053 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8055 of file pbx.c.
References ast_calloc, ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().
08056 { 08057 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08058 int length; 08059 char *pattern; 08060 length = sizeof(struct ast_ignorepat); 08061 length += strlen(value) + 1; 08062 if (!(ignorepat = ast_calloc(1, length))) 08063 return -1; 08064 /* The cast to char * is because we need to write the initial value. 08065 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08066 * sees the cast as dereferencing a type-punned pointer and warns about 08067 * it. This is the workaround (we're telling gcc, yes, that's really 08068 * what we wanted to do). 08069 */ 08070 pattern = (char *) ignorepat->pattern; 08071 strcpy(pattern, value); 08072 ignorepat->next = NULL; 08073 ignorepat->registrar = registrar; 08074 ast_wrlock_context(con); 08075 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08076 ignorepatl = ignorepatc; 08077 if (!strcasecmp(ignorepatc->pattern, value)) { 08078 /* Already there */ 08079 ast_unlock_context(con); 08080 ast_free(ignorepat); 08081 errno = EEXIST; 08082 return -1; 08083 } 08084 } 08085 if (ignorepatl) 08086 ignorepatl->next = ignorepat; 08087 else 08088 con->ignorepats = ignorepat; 08089 ast_unlock_context(con); 08090 return 0; 08091 08092 }
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 7586 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07587 { 07588 int ret = -1; 07589 struct ast_context *c; 07590 07591 c = find_context_locked(context); 07592 if (c) { 07593 ret = ast_context_add_include2(c, include, registrar); 07594 ast_unlock_contexts(); 07595 } 07596 return ret; 07597 }
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 7855 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().
07857 { 07858 struct ast_include *new_include; 07859 char *c; 07860 struct ast_include *i, *il = NULL; /* include, include_last */ 07861 int length; 07862 char *p; 07863 07864 length = sizeof(struct ast_include); 07865 length += 2 * (strlen(value) + 1); 07866 07867 /* allocate new include structure ... */ 07868 if (!(new_include = ast_calloc(1, length))) 07869 return -1; 07870 /* Fill in this structure. Use 'p' for assignments, as the fields 07871 * in the structure are 'const char *' 07872 */ 07873 p = new_include->stuff; 07874 new_include->name = p; 07875 strcpy(p, value); 07876 p += strlen(value) + 1; 07877 new_include->rname = p; 07878 strcpy(p, value); 07879 /* Strip off timing info, and process if it is there */ 07880 if ( (c = strchr(p, ',')) ) { 07881 *c++ = '\0'; 07882 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07883 } 07884 new_include->next = NULL; 07885 new_include->registrar = registrar; 07886 07887 ast_wrlock_context(con); 07888 07889 /* ... go to last include and check if context is already included too... */ 07890 for (i = con->includes; i; i = i->next) { 07891 if (!strcasecmp(i->name, new_include->name)) { 07892 ast_destroy_timing(&(new_include->timing)); 07893 ast_free(new_include); 07894 ast_unlock_context(con); 07895 errno = EEXIST; 07896 return -1; 07897 } 07898 il = i; 07899 } 07900 07901 /* ... include new context into context list, unlock, return */ 07902 if (il) 07903 il->next = new_include; 07904 else 07905 con->includes = new_include; 07906 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07907 07908 ast_unlock_context(con); 07909 07910 return 0; 07911 }
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 7918 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07919 { 07920 int ret = -1; 07921 struct ast_context *c; 07922 07923 c = find_context_locked(context); 07924 if (c) { /* found, add switch to this context */ 07925 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07926 ast_unlock_contexts(); 07927 } 07928 return ret; 07929 }
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 7938 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().
07940 { 07941 struct ast_sw *new_sw; 07942 struct ast_sw *i; 07943 int length; 07944 char *p; 07945 07946 length = sizeof(struct ast_sw); 07947 length += strlen(value) + 1; 07948 if (data) 07949 length += strlen(data); 07950 length++; 07951 07952 /* allocate new sw structure ... */ 07953 if (!(new_sw = ast_calloc(1, length))) 07954 return -1; 07955 /* ... fill in this structure ... */ 07956 p = new_sw->stuff; 07957 new_sw->name = p; 07958 strcpy(new_sw->name, value); 07959 p += strlen(value) + 1; 07960 new_sw->data = p; 07961 if (data) { 07962 strcpy(new_sw->data, data); 07963 p += strlen(data) + 1; 07964 } else { 07965 strcpy(new_sw->data, ""); 07966 p++; 07967 } 07968 new_sw->eval = eval; 07969 new_sw->registrar = registrar; 07970 07971 /* ... try to lock this context ... */ 07972 ast_wrlock_context(con); 07973 07974 /* ... go to last sw and check if context is already swd too... */ 07975 AST_LIST_TRAVERSE(&con->alts, i, list) { 07976 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07977 ast_free(new_sw); 07978 ast_unlock_context(con); 07979 errno = EEXIST; 07980 return -1; 07981 } 07982 } 07983 07984 /* ... sw new context into context list, unlock, return */ 07985 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07986 07987 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07988 07989 ast_unlock_context(con); 07990 07991 return 0; 07992 }
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 9302 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().
09303 { 09304 ast_wrlock_contexts(); 09305 __ast_context_destroy(contexts, contexts_table, con,registrar); 09306 ast_unlock_contexts(); 09307 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2673 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().
02674 { 02675 struct ast_context *tmp; 02676 struct fake_context item; 02677 02678 if (!name) { 02679 return NULL; 02680 } 02681 ast_rdlock_contexts(); 02682 if (contexts_table) { 02683 ast_copy_string(item.name, name, sizeof(item.name)); 02684 tmp = ast_hashtab_lookup(contexts_table, &item); 02685 } else { 02686 tmp = NULL; 02687 while ((tmp = ast_walk_contexts(tmp))) { 02688 if (!strcasecmp(name, tmp->name)) { 02689 break; 02690 } 02691 } 02692 } 02693 ast_unlock_contexts(); 02694 return tmp; 02695 }
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 7185 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().
07186 { 07187 struct ast_context *tmp, **local_contexts; 07188 struct fake_context search; 07189 int length = sizeof(struct ast_context) + strlen(name) + 1; 07190 07191 if (!contexts_table) { 07192 /* Protect creation of contexts_table from reentrancy. */ 07193 ast_wrlock_contexts(); 07194 if (!contexts_table) { 07195 contexts_table = ast_hashtab_create(17, 07196 ast_hashtab_compare_contexts, 07197 ast_hashtab_resize_java, 07198 ast_hashtab_newsize_java, 07199 ast_hashtab_hash_contexts, 07200 0); 07201 } 07202 ast_unlock_contexts(); 07203 } 07204 07205 ast_copy_string(search.name, name, sizeof(search.name)); 07206 if (!extcontexts) { 07207 ast_rdlock_contexts(); 07208 local_contexts = &contexts; 07209 tmp = ast_hashtab_lookup(contexts_table, &search); 07210 ast_unlock_contexts(); 07211 if (tmp) { 07212 tmp->refcount++; 07213 return tmp; 07214 } 07215 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07216 local_contexts = extcontexts; 07217 tmp = ast_hashtab_lookup(exttable, &search); 07218 if (tmp) { 07219 tmp->refcount++; 07220 return tmp; 07221 } 07222 } 07223 07224 if ((tmp = ast_calloc(1, length))) { 07225 ast_rwlock_init(&tmp->lock); 07226 ast_mutex_init(&tmp->macrolock); 07227 strcpy(tmp->name, name); 07228 tmp->root = NULL; 07229 tmp->root_table = NULL; 07230 tmp->registrar = ast_strdup(registrar); 07231 tmp->includes = NULL; 07232 tmp->ignorepats = NULL; 07233 tmp->refcount = 1; 07234 } else { 07235 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07236 return NULL; 07237 } 07238 07239 if (!extcontexts) { 07240 ast_wrlock_contexts(); 07241 tmp->next = *local_contexts; 07242 *local_contexts = tmp; 07243 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07244 ast_unlock_contexts(); 07245 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07246 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07247 } else { 07248 tmp->next = *local_contexts; 07249 if (exttable) 07250 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07251 07252 *local_contexts = tmp; 07253 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07254 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07255 } 07256 return tmp; 07257 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 5783 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05784 { 05785 struct ast_context *c; 05786 int ret = -1; 05787 05788 c = find_context_locked(context); 05789 if (c) { 05790 ast_unlock_contexts(); 05791 05792 /* if we found context, lock macrolock */ 05793 ret = ast_mutex_lock(&c->macrolock); 05794 } 05795 05796 return ret; 05797 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
Definition at line 5588 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().
05589 { 05590 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05591 }
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 5618 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
05619 { 05620 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05621 }
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 5593 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().
05594 { 05595 int ret = -1; /* default error return */ 05596 struct ast_context *c; 05597 05598 c = find_context_locked(context); 05599 if (c) { /* ... remove extension ... */ 05600 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 05601 matchcallerid, registrar, 0); 05602 ast_unlock_contexts(); 05603 } 05604 05605 return ret; 05606 }
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 5623 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().
05624 { 05625 struct ast_exten *exten, *prev_exten = NULL; 05626 struct ast_exten *peer; 05627 struct ast_exten ex, *exten2, *exten3; 05628 char dummy_name[1024]; 05629 struct ast_exten *previous_peer = NULL; 05630 struct ast_exten *next_peer = NULL; 05631 int found = 0; 05632 05633 if (!already_locked) 05634 ast_wrlock_context(con); 05635 05636 /* Handle this is in the new world */ 05637 05638 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05639 * peers, not just those matching the callerid. */ 05640 #ifdef NEED_DEBUG 05641 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05642 #endif 05643 #ifdef CONTEXT_DEBUG 05644 check_contexts(__FILE__, __LINE__); 05645 #endif 05646 /* find this particular extension */ 05647 ex.exten = dummy_name; 05648 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05649 ex.cidmatch = callerid; 05650 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05651 exten = ast_hashtab_lookup(con->root_table, &ex); 05652 if (exten) { 05653 if (priority == 0) { 05654 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05655 if (!exten2) 05656 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); 05657 if (con->pattern_tree) { 05658 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05659 05660 if (x->exten) { /* this test for safety purposes */ 05661 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05662 x->exten = 0; /* get rid of what will become a bad pointer */ 05663 } else { 05664 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05665 } 05666 } 05667 } else { 05668 ex.priority = priority; 05669 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05670 if (exten2) { 05671 05672 if (exten2->label) { /* if this exten has a label, remove that, too */ 05673 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05674 if (!exten3) 05675 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); 05676 } 05677 05678 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05679 if (!exten3) 05680 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); 05681 if (exten2 == exten && exten2->peer) { 05682 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05683 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05684 } 05685 if (ast_hashtab_size(exten->peer_table) == 0) { 05686 /* well, if the last priority of an exten is to be removed, 05687 then, the extension is removed, too! */ 05688 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05689 if (!exten3) 05690 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05691 if (con->pattern_tree) { 05692 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05693 if (x->exten) { /* this test for safety purposes */ 05694 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05695 x->exten = 0; /* get rid of what will become a bad pointer */ 05696 } 05697 } 05698 } 05699 } else { 05700 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05701 priority, exten->exten, con->name); 05702 } 05703 } 05704 } else { 05705 /* hmmm? this exten is not in this pattern tree? */ 05706 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05707 extension, con->name); 05708 } 05709 #ifdef NEED_DEBUG 05710 if (con->pattern_tree) { 05711 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05712 log_match_char_tree(con->pattern_tree, " "); 05713 } 05714 #endif 05715 05716 /* scan the extension list to find first matching extension-registrar */ 05717 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05718 if (!strcmp(exten->exten, extension) && 05719 (!registrar || !strcmp(exten->registrar, registrar)) && 05720 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05721 break; 05722 } 05723 if (!exten) { 05724 /* we can't find right extension */ 05725 if (!already_locked) 05726 ast_unlock_context(con); 05727 return -1; 05728 } 05729 05730 /* scan the priority list to remove extension with exten->priority == priority */ 05731 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05732 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))); 05733 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05734 if ((priority == 0 || peer->priority == priority) && 05735 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05736 (!registrar || !strcmp(peer->registrar, registrar) )) { 05737 found = 1; 05738 05739 /* we are first priority extension? */ 05740 if (!previous_peer) { 05741 /* 05742 * We are first in the priority chain, so must update the extension chain. 05743 * The next node is either the next priority or the next extension 05744 */ 05745 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05746 if (peer->peer) { 05747 /* move the peer_table and peer_label_table down to the next peer, if 05748 it is there */ 05749 peer->peer->peer_table = peer->peer_table; 05750 peer->peer->peer_label_table = peer->peer_label_table; 05751 peer->peer_table = NULL; 05752 peer->peer_label_table = NULL; 05753 } 05754 if (!prev_exten) { /* change the root... */ 05755 con->root = next_node; 05756 } else { 05757 prev_exten->next = next_node; /* unlink */ 05758 } 05759 if (peer->peer) { /* update the new head of the pri list */ 05760 peer->peer->next = peer->next; 05761 } 05762 } else { /* easy, we are not first priority in extension */ 05763 previous_peer->peer = peer->peer; 05764 } 05765 05766 /* now, free whole priority extension */ 05767 destroy_exten(peer); 05768 } else { 05769 previous_peer = peer; 05770 } 05771 } 05772 if (!already_locked) 05773 ast_unlock_context(con); 05774 return found ? 0 : -1; 05775 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7998 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07999 { 08000 int ret = -1; 08001 struct ast_context *c; 08002 08003 c = find_context_locked(context); 08004 if (c) { 08005 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08006 ast_unlock_contexts(); 08007 } 08008 return ret; 08009 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8011 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().
08012 { 08013 struct ast_ignorepat *ip, *ipl = NULL; 08014 08015 ast_wrlock_context(con); 08016 08017 for (ip = con->ignorepats; ip; ip = ip->next) { 08018 if (!strcmp(ip->pattern, ignorepat) && 08019 (!registrar || (registrar == ip->registrar))) { 08020 if (ipl) { 08021 ipl->next = ip->next; 08022 ast_free(ip); 08023 } else { 08024 con->ignorepats = ip->next; 08025 ast_free(ip); 08026 } 08027 ast_unlock_context(con); 08028 return 0; 08029 } 08030 ipl = ip; 08031 } 08032 08033 ast_unlock_context(con); 08034 errno = EINVAL; 08035 return -1; 08036 }
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 5481 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05482 { 05483 int ret = -1; 05484 struct ast_context *c; 05485 05486 c = find_context_locked(context); 05487 if (c) { 05488 /* found, remove include from this context ... */ 05489 ret = ast_context_remove_include2(c, include, registrar); 05490 ast_unlock_contexts(); 05491 } 05492 return ret; 05493 }
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 5504 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().
05505 { 05506 struct ast_include *i, *pi = NULL; 05507 int ret = -1; 05508 05509 ast_wrlock_context(con); 05510 05511 /* find our include */ 05512 for (i = con->includes; i; pi = i, i = i->next) { 05513 if (!strcmp(i->name, include) && 05514 (!registrar || !strcmp(i->registrar, registrar))) { 05515 /* remove from list */ 05516 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05517 if (pi) 05518 pi->next = i->next; 05519 else 05520 con->includes = i->next; 05521 /* free include and return */ 05522 ast_destroy_timing(&(i->timing)); 05523 ast_free(i); 05524 ret = 0; 05525 break; 05526 } 05527 } 05528 05529 ast_unlock_context(con); 05530 05531 return ret; 05532 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 5539 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05540 { 05541 int ret = -1; /* default error return */ 05542 struct ast_context *c; 05543 05544 c = find_context_locked(context); 05545 if (c) { 05546 /* remove switch from this context ... */ 05547 ret = ast_context_remove_switch2(c, sw, data, registrar); 05548 ast_unlock_contexts(); 05549 } 05550 return ret; 05551 }
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 5561 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().
05562 { 05563 struct ast_sw *i; 05564 int ret = -1; 05565 05566 ast_wrlock_context(con); 05567 05568 /* walk switches */ 05569 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05570 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05571 (!registrar || !strcmp(i->registrar, registrar))) { 05572 /* found, remove from list */ 05573 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05574 AST_LIST_REMOVE_CURRENT(list); 05575 ast_free(i); /* free switch and return */ 05576 ret = 0; 05577 break; 05578 } 05579 } 05580 AST_LIST_TRAVERSE_SAFE_END; 05581 05582 ast_unlock_context(con); 05583 05584 return ret; 05585 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5804 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05805 { 05806 struct ast_context *c; 05807 int ret = -1; 05808 05809 c = find_context_locked(context); 05810 if (c) { 05811 ast_unlock_contexts(); 05812 05813 /* if we found context, unlock macrolock */ 05814 ret = ast_mutex_unlock(&c->macrolock); 05815 } 05816 05817 return ret; 05818 }
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 10530 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().
10531 { 10532 struct ast_include *inc = NULL; 10533 int res = 0; 10534 10535 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10536 if (ast_context_find(inc->rname)) 10537 continue; 10538 10539 res = -1; 10540 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10541 ast_get_context_name(con), inc->rname); 10542 break; 10543 } 10544 10545 return res; 10546 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 3502 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().
03503 { 03504 struct ast_custom_function *acf = NULL; 03505 03506 AST_RWLIST_RDLOCK(&acf_root); 03507 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03508 if (!strcmp(name, acf->name)) 03509 break; 03510 } 03511 AST_RWLIST_UNLOCK(&acf_root); 03512 03513 return acf; 03514 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3516 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().
03517 { 03518 struct ast_custom_function *cur; 03519 03520 if (!acf) { 03521 return -1; 03522 } 03523 03524 AST_RWLIST_WRLOCK(&acf_root); 03525 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03526 #ifdef AST_XML_DOCS 03527 if (cur->docsrc == AST_XML_DOC) { 03528 ast_string_field_free_memory(acf); 03529 } 03530 #endif 03531 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03532 } 03533 AST_RWLIST_UNLOCK(&acf_root); 03534 03535 return cur ? 0 : -1; 03536 }
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 7840 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().
07841 { 07842 if (i->timezone) { 07843 ast_free(i->timezone); 07844 i->timezone = NULL; 07845 } 07846 return 0; 07847 }
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 4325 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().
04326 { 04327 switch (devstate) { 04328 case AST_DEVICE_ONHOLD: 04329 return AST_EXTENSION_ONHOLD; 04330 case AST_DEVICE_BUSY: 04331 return AST_EXTENSION_BUSY; 04332 case AST_DEVICE_UNKNOWN: 04333 return AST_EXTENSION_NOT_INUSE; 04334 case AST_DEVICE_UNAVAILABLE: 04335 case AST_DEVICE_INVALID: 04336 return AST_EXTENSION_UNAVAILABLE; 04337 case AST_DEVICE_RINGINUSE: 04338 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04339 case AST_DEVICE_RINGING: 04340 return AST_EXTENSION_RINGING; 04341 case AST_DEVICE_INUSE: 04342 return AST_EXTENSION_INUSE; 04343 case AST_DEVICE_NOT_INUSE: 04344 return AST_EXTENSION_NOT_INUSE; 04345 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04346 break; 04347 } 04348 04349 return AST_EXTENSION_NOT_INUSE; 04350 }
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 4877 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_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().
04878 { 04879 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04880 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8152 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().
08153 { 08154 if (!chan) 08155 return -1; 08156 08157 ast_channel_lock(chan); 08158 08159 if (!ast_strlen_zero(context)) 08160 ast_copy_string(chan->context, context, sizeof(chan->context)); 08161 if (!ast_strlen_zero(exten)) 08162 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08163 if (priority > -1) { 08164 chan->priority = priority; 08165 /* see flag description in channel.h for explanation */ 08166 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08167 chan->priority--; 08168 } 08169 08170 ast_channel_unlock(chan); 08171 08172 return 0; 08173 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2650 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().
02651 { 02652 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02653 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02654 return extension_match_core(pattern, data, needmore); 02655 }
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 2452 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02453 { 02454 return ext_cmp(a, b); 02455 }
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 2645 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().
02646 { 02647 return extension_match_core(pattern, data, E_MATCH); 02648 }
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 4395 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().
04396 { 04397 struct ast_exten *e; 04398 04399 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04400 return -1; /* No hint, return -1 */ 04401 } 04402 04403 if (e->exten[0] == '_') { 04404 /* Create this hint on-the-fly */ 04405 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04406 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04407 e->registrar); 04408 if (!(e = ast_hint_extension(c, context, exten))) { 04409 /* Improbable, but not impossible */ 04410 return -1; 04411 } 04412 } 04413 04414 return ast_extension_state2(e); /* Check all devices in the hint */ 04415 }
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 4383 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().
04384 { 04385 int i; 04386 04387 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04388 if (extension_states[i].extension_state == extension_state) 04389 return extension_states[i].text; 04390 } 04391 return "Unknown"; 04392 }
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 4616 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
04618 { 04619 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 04620 }
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 4529 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().
04531 { 04532 struct ast_hint *hint; 04533 struct ast_state_cb *state_cb; 04534 struct ast_exten *e; 04535 int id; 04536 04537 /* If there's no context and extension: add callback to statecbs list */ 04538 if (!context && !exten) { 04539 /* Prevent multiple adds from adding the same change_cb at the same time. */ 04540 ao2_lock(statecbs); 04541 04542 /* Remove any existing change_cb. */ 04543 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 04544 04545 /* Now insert the change_cb */ 04546 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04547 ao2_unlock(statecbs); 04548 return -1; 04549 } 04550 state_cb->id = 0; 04551 state_cb->change_cb = change_cb; 04552 state_cb->destroy_cb = destroy_cb; 04553 state_cb->data = data; 04554 ao2_link(statecbs, state_cb); 04555 04556 ao2_ref(state_cb, -1); 04557 ao2_unlock(statecbs); 04558 return 0; 04559 } 04560 04561 if (!context || !exten) 04562 return -1; 04563 04564 /* This callback type is for only one hint, so get the hint */ 04565 e = ast_hint_extension(NULL, context, exten); 04566 if (!e) { 04567 return -1; 04568 } 04569 04570 /* If this is a pattern, dynamically create a new extension for this 04571 * particular match. Note that this will only happen once for each 04572 * individual extension, because the pattern will no longer match first. 04573 */ 04574 if (e->exten[0] == '_') { 04575 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04576 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04577 e->registrar); 04578 e = ast_hint_extension(NULL, context, exten); 04579 if (!e || e->exten[0] == '_') { 04580 return -1; 04581 } 04582 } 04583 04584 /* Find the hint in the hints container */ 04585 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04586 hint = ao2_find(hints, e, 0); 04587 if (!hint) { 04588 ao2_unlock(hints); 04589 return -1; 04590 } 04591 04592 /* Now insert the callback in the callback list */ 04593 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04594 ao2_ref(hint, -1); 04595 ao2_unlock(hints); 04596 return -1; 04597 } 04598 do { 04599 id = stateid++; /* Unique ID for this callback */ 04600 /* Do not allow id to ever be -1 or 0. */ 04601 } while (id == -1 || id == 0); 04602 state_cb->id = id; 04603 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 04604 state_cb->destroy_cb = destroy_cb; 04605 state_cb->data = data; /* Data for the callback */ 04606 ao2_link(hint->callbacks, state_cb); 04607 04608 ao2_ref(state_cb, -1); 04609 ao2_ref(hint, -1); 04610 ao2_unlock(hints); 04611 04612 return id; 04613 }
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 4638 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().
04639 { 04640 struct ast_state_cb *p_cur; 04641 int ret = -1; 04642 04643 if (!id) { /* id == 0 is a callback without extension */ 04644 if (!change_cb) { 04645 return ret; 04646 } 04647 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 04648 if (p_cur) { 04649 ret = 0; 04650 ao2_ref(p_cur, -1); 04651 } 04652 } else { /* callback with extension, find the callback based on ID */ 04653 struct ast_hint *hint; 04654 04655 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04656 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04657 if (hint) { 04658 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04659 if (p_cur) { 04660 ret = 0; 04661 ao2_ref(p_cur, -1); 04662 } 04663 ao2_ref(hint, -1); 04664 } 04665 ao2_unlock(hints); 04666 } 04667 04668 return ret; 04669 }
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 4882 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().
04883 { 04884 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04885 }
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 4887 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
04888 { 04889 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04890 }
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 3660 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().
03661 { 03662 char *copy = ast_strdupa(function); 03663 char *args = func_args(copy); 03664 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03665 int res; 03666 struct ast_module_user *u = NULL; 03667 03668 if (acfptr == NULL) { 03669 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03670 } else if (!acfptr->read && !acfptr->read2) { 03671 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03672 } else if (acfptr->read) { 03673 if (acfptr->mod) { 03674 u = __ast_module_user_add(acfptr->mod, chan); 03675 } 03676 res = acfptr->read(chan, copy, args, workspace, len); 03677 if (acfptr->mod && u) { 03678 __ast_module_user_remove(acfptr->mod, u); 03679 } 03680 return res; 03681 } else { 03682 struct ast_str *str = ast_str_create(16); 03683 if (acfptr->mod) { 03684 u = __ast_module_user_add(acfptr->mod, chan); 03685 } 03686 res = acfptr->read2(chan, copy, args, &str, 0); 03687 if (acfptr->mod && u) { 03688 __ast_module_user_remove(acfptr->mod, u); 03689 } 03690 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03691 ast_free(str); 03692 return res; 03693 } 03694 return -1; 03695 }
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 3697 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().
03698 { 03699 char *copy = ast_strdupa(function); 03700 char *args = func_args(copy); 03701 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03702 int res; 03703 struct ast_module_user *u = NULL; 03704 03705 if (acfptr == NULL) { 03706 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03707 } else if (!acfptr->read && !acfptr->read2) { 03708 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03709 } else { 03710 if (acfptr->mod) { 03711 u = __ast_module_user_add(acfptr->mod, chan); 03712 } 03713 ast_str_reset(*str); 03714 if (acfptr->read2) { 03715 /* ast_str enabled */ 03716 res = acfptr->read2(chan, copy, args, str, maxlen); 03717 } else { 03718 /* Legacy function pointer, allocate buffer for result */ 03719 int maxsize = ast_str_size(*str); 03720 if (maxlen > -1) { 03721 if (maxlen == 0) { 03722 if (acfptr->read_max) { 03723 maxsize = acfptr->read_max; 03724 } else { 03725 maxsize = VAR_BUF_SIZE; 03726 } 03727 } else { 03728 maxsize = maxlen; 03729 } 03730 ast_str_make_space(str, maxsize); 03731 } 03732 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03733 } 03734 if (acfptr->mod && u) { 03735 __ast_module_user_remove(acfptr->mod, u); 03736 } 03737 return res; 03738 } 03739 return -1; 03740 }
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 3742 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().
03743 { 03744 char *copy = ast_strdupa(function); 03745 char *args = func_args(copy); 03746 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03747 03748 if (acfptr == NULL) 03749 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03750 else if (!acfptr->write) 03751 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03752 else { 03753 int res; 03754 struct ast_module_user *u = NULL; 03755 if (acfptr->mod) 03756 u = __ast_module_user_add(acfptr->mod, chan); 03757 res = acfptr->write(chan, copy, args, value); 03758 if (acfptr->mod && u) 03759 __ast_module_user_remove(acfptr->mod, u); 03760 return res; 03761 } 03762 03763 return -1; 03764 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10382 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().
10383 { 10384 return con ? con->name : NULL; 10385 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10420 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10421 { 10422 return c ? c->registrar : NULL; 10423 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10450 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().
10451 { 10452 return e ? e->app : NULL; 10453 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10455 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().
10456 { 10457 return e ? e->data : NULL; 10458 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10445 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10446 { 10447 return e ? e->cidmatch : NULL; 10448 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 10387 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 10397 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 10440 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10441 { 10442 return e ? e->matchcid : 0; 10443 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10392 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 10412 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 10425 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10426 { 10427 return e ? e->registrar : NULL; 10428 }
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 4839 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().
04840 { 04841 struct ast_exten *e = ast_hint_extension(c, context, exten); 04842 04843 if (e) { 04844 if (hint) 04845 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04846 if (name) { 04847 const char *tmp = ast_get_extension_app_data(e); 04848 if (tmp) 04849 ast_copy_string(name, tmp, namesize); 04850 } 04851 return -1; 04852 } 04853 return 0; 04854 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10407 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().
10408 { 10409 return ip ? ip->pattern : NULL; 10410 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10435 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().
10436 { 10437 return ip ? ip->registrar : NULL; 10438 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 10402 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 10430 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().
10431 { 10432 return i ? i->registrar : NULL; 10433 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10465 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().
10466 { 10467 return sw ? sw->data : NULL; 10468 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10470 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10471 { 10472 return sw->eval; 10473 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10460 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().
10461 { 10462 return sw ? sw->name : NULL; 10463 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10475 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().
10476 { 10477 return sw ? sw->registrar : NULL; 10478 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10570 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10571 { 10572 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10573 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1081 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01082 { 01083 const struct ast_context *ac = ah_a; 01084 const struct ast_context *bc = ah_b; 01085 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01086 return 1; 01087 /* assume context names are registered in a string table! */ 01088 return strcmp(ac->name, bc->name); 01089 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1124 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().
01125 { 01126 const struct ast_context *ac = obj; 01127 return ast_hashtab_hash_string(ac->name); 01128 }
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 8094 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().
08095 { 08096 struct ast_context *con = ast_context_find(context); 08097 08098 if (con) { 08099 struct ast_ignorepat *pat; 08100 08101 for (pat = con->ignorepats; pat; pat = pat->next) { 08102 if (ast_extension_match(pat->pattern, pattern)) 08103 return 1; 08104 } 08105 } 08106 08107 return 0; 08108 }
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 4897 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(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_ss_thread(), readexten_exec(), and skinny_ss().
04898 { 04899 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04900 }
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 7391 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().
07392 { 07393 double ft; 07394 struct ast_context *tmp; 07395 struct ast_context *oldcontextslist; 07396 struct ast_hashtab *oldtable; 07397 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07398 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07399 struct store_hint *saved_hint; 07400 struct ast_hint *hint; 07401 struct ast_exten *exten; 07402 int length; 07403 struct ast_state_cb *thiscb; 07404 struct ast_hashtab_iter *iter; 07405 struct ao2_iterator i; 07406 struct timeval begintime; 07407 struct timeval writelocktime; 07408 struct timeval endlocktime; 07409 struct timeval enddeltime; 07410 07411 /* 07412 * It is very important that this function hold the hints 07413 * container lock _and_ the conlock during its operation; not 07414 * only do we need to ensure that the list of contexts and 07415 * extensions does not change, but also that no hint callbacks 07416 * (watchers) are added or removed during the merge/delete 07417 * process 07418 * 07419 * In addition, the locks _must_ be taken in this order, because 07420 * there are already other code paths that use this order 07421 */ 07422 07423 begintime = ast_tvnow(); 07424 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07425 ast_wrlock_contexts(); 07426 iter = ast_hashtab_start_traversal(contexts_table); 07427 while ((tmp = ast_hashtab_next(iter))) { 07428 context_merge(extcontexts, exttable, tmp, registrar); 07429 } 07430 ast_hashtab_end_traversal(iter); 07431 07432 ao2_lock(hints); 07433 writelocktime = ast_tvnow(); 07434 07435 /* preserve all watchers for hints */ 07436 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07437 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07438 if (ao2_container_count(hint->callbacks)) { 07439 ao2_lock(hint); 07440 if (!hint->exten) { 07441 /* The extension has already been destroyed. (Should never happen here) */ 07442 ao2_unlock(hint); 07443 continue; 07444 } 07445 07446 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07447 + sizeof(*saved_hint); 07448 if (!(saved_hint = ast_calloc(1, length))) { 07449 ao2_unlock(hint); 07450 continue; 07451 } 07452 07453 /* This removes all the callbacks from the hint into saved_hint. */ 07454 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07455 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07456 /* 07457 * We intentionally do not unref thiscb to account for the 07458 * non-ao2 reference in saved_hint->callbacks 07459 */ 07460 } 07461 07462 saved_hint->laststate = hint->laststate; 07463 saved_hint->context = saved_hint->data; 07464 strcpy(saved_hint->data, hint->exten->parent->name); 07465 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07466 strcpy(saved_hint->exten, hint->exten->exten); 07467 ao2_unlock(hint); 07468 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07469 } 07470 } 07471 ao2_iterator_destroy(&i); 07472 07473 /* save the old table and list */ 07474 oldtable = contexts_table; 07475 oldcontextslist = contexts; 07476 07477 /* move in the new table and list */ 07478 contexts_table = exttable; 07479 contexts = *extcontexts; 07480 07481 /* 07482 * Restore the watchers for hints that can be found; notify 07483 * those that cannot be restored. 07484 */ 07485 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07486 struct pbx_find_info q = { .stacklen = 0 }; 07487 07488 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07489 PRIORITY_HINT, NULL, "", E_MATCH); 07490 /* 07491 * If this is a pattern, dynamically create a new extension for this 07492 * particular match. Note that this will only happen once for each 07493 * individual extension, because the pattern will no longer match first. 07494 */ 07495 if (exten && exten->exten[0] == '_') { 07496 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07497 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07498 exten->registrar); 07499 /* rwlocks are not recursive locks */ 07500 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07501 saved_hint->exten); 07502 } 07503 07504 /* Find the hint in the hints container */ 07505 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07506 if (!hint) { 07507 /* 07508 * Notify watchers of this removed hint later when we aren't 07509 * encumberd by so many locks. 07510 */ 07511 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07512 } else { 07513 ao2_lock(hint); 07514 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07515 ao2_link(hint->callbacks, thiscb); 07516 /* Ref that we added when putting into saved_hint->callbacks */ 07517 ao2_ref(thiscb, -1); 07518 } 07519 hint->laststate = saved_hint->laststate; 07520 ao2_unlock(hint); 07521 ao2_ref(hint, -1); 07522 ast_free(saved_hint); 07523 } 07524 } 07525 07526 ao2_unlock(hints); 07527 ast_unlock_contexts(); 07528 07529 /* 07530 * Notify watchers of all removed hints with the same lock 07531 * environment as handle_statechange(). 07532 */ 07533 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 07534 /* this hint has been removed, notify the watchers */ 07535 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07536 thiscb->change_cb(saved_hint->context, saved_hint->exten, 07537 AST_EXTENSION_REMOVED, thiscb->data); 07538 /* Ref that we added when putting into saved_hint->callbacks */ 07539 ao2_ref(thiscb, -1); 07540 } 07541 ast_free(saved_hint); 07542 } 07543 07544 ast_mutex_unlock(&context_merge_lock); 07545 endlocktime = ast_tvnow(); 07546 07547 /* 07548 * The old list and hashtab no longer are relevant, delete them 07549 * while the rest of asterisk is now freely using the new stuff 07550 * instead. 07551 */ 07552 07553 ast_hashtab_destroy(oldtable, NULL); 07554 07555 for (tmp = oldcontextslist; tmp; ) { 07556 struct ast_context *next; /* next starting point */ 07557 07558 next = tmp->next; 07559 __ast_internal_context_destroy(tmp); 07560 tmp = next; 07561 } 07562 enddeltime = ast_tvnow(); 07563 07564 ft = ast_tvdiff_us(writelocktime, begintime); 07565 ft /= 1000000.0; 07566 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07567 07568 ft = ast_tvdiff_us(endlocktime, writelocktime); 07569 ft /= 1000000.0; 07570 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07571 07572 ft = ast_tvdiff_us(enddeltime, endlocktime); 07573 ft /= 1000000.0; 07574 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07575 07576 ft = ast_tvdiff_us(enddeltime, begintime); 07577 ft /= 1000000.0; 07578 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07579 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10635 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().
10636 { 10637 return pbx_parseable_goto(chan, goto_string, 0); 10638 }
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 8971 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().
08972 { 08973 struct ast_channel *chan; 08974 struct app_tmp *tmp; 08975 int res = -1, cdr_res = -1; 08976 struct outgoing_helper oh; 08977 08978 memset(&oh, 0, sizeof(oh)); 08979 oh.vars = vars; 08980 oh.account = account; 08981 08982 if (locked_channel) 08983 *locked_channel = NULL; 08984 if (ast_strlen_zero(app)) { 08985 res = -1; 08986 goto outgoing_app_cleanup; 08987 } 08988 if (synchronous) { 08989 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08990 if (chan) { 08991 ast_set_variables(chan, vars); 08992 if (account) 08993 ast_cdr_setaccount(chan, account); 08994 if (chan->_state == AST_STATE_UP) { 08995 res = 0; 08996 ast_verb(4, "Channel %s was answered.\n", chan->name); 08997 tmp = ast_calloc(1, sizeof(*tmp)); 08998 if (!tmp || ast_string_field_init(tmp, 252)) { 08999 if (tmp) { 09000 ast_free(tmp); 09001 } 09002 res = -1; 09003 } else { 09004 ast_string_field_set(tmp, app, app); 09005 ast_string_field_set(tmp, data, appdata); 09006 tmp->chan = chan; 09007 if (synchronous > 1) { 09008 if (locked_channel) 09009 ast_channel_unlock(chan); 09010 ast_pbx_run_app(tmp); 09011 } else { 09012 if (locked_channel) 09013 ast_channel_lock(chan); 09014 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09015 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09016 ast_string_field_free_memory(tmp); 09017 ast_free(tmp); 09018 if (locked_channel) 09019 ast_channel_unlock(chan); 09020 ast_hangup(chan); 09021 res = -1; 09022 } else { 09023 if (locked_channel) 09024 *locked_channel = chan; 09025 } 09026 } 09027 } 09028 } else { 09029 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09030 if (chan->cdr) { /* update the cdr */ 09031 /* here we update the status of the call, which sould be busy. 09032 * if that fails then we set the status to failed */ 09033 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09034 ast_cdr_failed(chan->cdr); 09035 } 09036 ast_hangup(chan); 09037 } 09038 } 09039 09040 if (res < 0) { /* the call failed for some reason */ 09041 if (*reason == 0) { /* if the call failed (not busy or no answer) 09042 * update the cdr with the failed message */ 09043 cdr_res = ast_pbx_outgoing_cdr_failed(); 09044 if (cdr_res != 0) { 09045 res = cdr_res; 09046 goto outgoing_app_cleanup; 09047 } 09048 } 09049 } 09050 09051 } else { 09052 struct async_stat *as; 09053 if (!(as = ast_calloc(1, sizeof(*as)))) { 09054 res = -1; 09055 goto outgoing_app_cleanup; 09056 } 09057 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09058 if (!chan) { 09059 ast_free(as); 09060 res = -1; 09061 goto outgoing_app_cleanup; 09062 } 09063 as->chan = chan; 09064 ast_copy_string(as->app, app, sizeof(as->app)); 09065 if (appdata) 09066 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09067 as->timeout = timeout; 09068 ast_set_variables(chan, vars); 09069 if (account) 09070 ast_cdr_setaccount(chan, account); 09071 /* Start a new thread, and get something handling this channel. */ 09072 if (locked_channel) 09073 ast_channel_lock(chan); 09074 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09075 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09076 ast_free(as); 09077 if (locked_channel) 09078 ast_channel_unlock(chan); 09079 ast_hangup(chan); 09080 res = -1; 09081 goto outgoing_app_cleanup; 09082 } else { 09083 if (locked_channel) 09084 *locked_channel = chan; 09085 } 09086 res = 0; 09087 } 09088 outgoing_app_cleanup: 09089 ast_variables_destroy(vars); 09090 return res; 09091 }
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 8802 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().
08803 { 08804 struct ast_channel *chan; 08805 struct async_stat *as; 08806 int res = -1, cdr_res = -1; 08807 struct outgoing_helper oh; 08808 08809 if (synchronous) { 08810 oh.context = context; 08811 oh.exten = exten; 08812 oh.priority = priority; 08813 oh.cid_num = cid_num; 08814 oh.cid_name = cid_name; 08815 oh.account = account; 08816 oh.vars = vars; 08817 oh.parent_channel = NULL; 08818 08819 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08820 if (channel) { 08821 *channel = chan; 08822 if (chan) 08823 ast_channel_lock(chan); 08824 } 08825 if (chan) { 08826 if (chan->_state == AST_STATE_UP) { 08827 res = 0; 08828 ast_verb(4, "Channel %s was answered.\n", chan->name); 08829 08830 if (synchronous > 1) { 08831 if (channel) 08832 ast_channel_unlock(chan); 08833 if (ast_pbx_run(chan)) { 08834 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08835 if (channel) 08836 *channel = NULL; 08837 ast_hangup(chan); 08838 chan = NULL; 08839 res = -1; 08840 } 08841 } else { 08842 if (ast_pbx_start(chan)) { 08843 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 08844 if (channel) { 08845 *channel = NULL; 08846 ast_channel_unlock(chan); 08847 } 08848 ast_hangup(chan); 08849 res = -1; 08850 } 08851 chan = NULL; 08852 } 08853 } else { 08854 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08855 08856 if (chan->cdr) { /* update the cdr */ 08857 /* here we update the status of the call, which sould be busy. 08858 * if that fails then we set the status to failed */ 08859 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08860 ast_cdr_failed(chan->cdr); 08861 } 08862 08863 if (channel) { 08864 *channel = NULL; 08865 ast_channel_unlock(chan); 08866 } 08867 ast_hangup(chan); 08868 chan = NULL; 08869 } 08870 } 08871 08872 if (res < 0) { /* the call failed for some reason */ 08873 if (*reason == 0) { /* if the call failed (not busy or no answer) 08874 * update the cdr with the failed message */ 08875 cdr_res = ast_pbx_outgoing_cdr_failed(); 08876 if (cdr_res != 0) { 08877 res = cdr_res; 08878 goto outgoing_exten_cleanup; 08879 } 08880 } 08881 08882 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08883 /* check if "failed" exists */ 08884 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08885 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 08886 if (chan) { 08887 char failed_reason[4] = ""; 08888 if (!ast_strlen_zero(context)) 08889 ast_copy_string(chan->context, context, sizeof(chan->context)); 08890 set_ext_pri(chan, "failed", 1); 08891 ast_set_variables(chan, vars); 08892 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08893 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08894 if (account) 08895 ast_cdr_setaccount(chan, account); 08896 if (ast_pbx_run(chan)) { 08897 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08898 ast_hangup(chan); 08899 } 08900 chan = NULL; 08901 } 08902 } 08903 } 08904 } else { 08905 if (!(as = ast_calloc(1, sizeof(*as)))) { 08906 res = -1; 08907 goto outgoing_exten_cleanup; 08908 } 08909 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 08910 if (channel) { 08911 *channel = chan; 08912 if (chan) 08913 ast_channel_lock(chan); 08914 } 08915 if (!chan) { 08916 ast_free(as); 08917 res = -1; 08918 goto outgoing_exten_cleanup; 08919 } 08920 as->chan = chan; 08921 ast_copy_string(as->context, context, sizeof(as->context)); 08922 set_ext_pri(as->chan, exten, priority); 08923 as->timeout = timeout; 08924 ast_set_variables(chan, vars); 08925 if (account) 08926 ast_cdr_setaccount(chan, account); 08927 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08928 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08929 ast_free(as); 08930 if (channel) { 08931 *channel = NULL; 08932 ast_channel_unlock(chan); 08933 } 08934 ast_hangup(chan); 08935 res = -1; 08936 goto outgoing_exten_cleanup; 08937 } 08938 res = 0; 08939 } 08940 outgoing_exten_cleanup: 08941 ast_variables_destroy(vars); 08942 return res; 08943 }
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 5400 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().
05401 { 05402 return ast_pbx_run_args(c, NULL); 05403 }
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 5380 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().
05381 { 05382 enum ast_pbx_result res = AST_PBX_SUCCESS; 05383 05384 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05385 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05386 return AST_PBX_FAILED; 05387 } 05388 05389 if (increase_call_count(c)) { 05390 return AST_PBX_CALL_LIMIT; 05391 } 05392 05393 res = __ast_pbx_run(c, args); 05394 05395 decrease_call_count(); 05396 05397 return res; 05398 }
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 5353 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), skinny_new(), and unistim_new().
05354 { 05355 pthread_t t; 05356 05357 if (!c) { 05358 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05359 return AST_PBX_FAILED; 05360 } 05361 05362 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05363 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05364 return AST_PBX_FAILED; 05365 } 05366 05367 if (increase_call_count(c)) 05368 return AST_PBX_CALL_LIMIT; 05369 05370 /* Start a new thread, and get something handling this channel. */ 05371 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05372 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05373 decrease_call_count(); 05374 return AST_PBX_FAILED; 05375 } 05376 05377 return AST_PBX_SUCCESS; 05378 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5410 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05411 { 05412 return totalcalls; 05413 }
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 10369 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().
10370 { 10371 return ast_rwlock_rdlock(&con->lock); 10372 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10351 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().
10352 { 10353 return ast_mutex_lock(&conlock); 10354 }
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 5916 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().
05917 { 05918 struct ast_switch *tmp; 05919 05920 AST_RWLIST_WRLOCK(&switches); 05921 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05922 if (!strcasecmp(tmp->name, sw->name)) { 05923 AST_RWLIST_UNLOCK(&switches); 05924 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05925 return -1; 05926 } 05927 } 05928 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05929 AST_RWLIST_UNLOCK(&switches); 05930 05931 return 0; 05932 }
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 4902 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().
04903 { 04904 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04905 }
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 4857 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().
04858 { 04859 struct ast_exten *e = ast_hint_extension(c, context, exten); 04860 04861 if (!e) { 04862 return 0; 04863 } 04864 04865 if (hint) { 04866 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 04867 } 04868 if (name) { 04869 const char *tmp = ast_get_extension_app_data(e); 04870 if (tmp) { 04871 ast_str_set(name, namesize, "%s", tmp); 04872 } 04873 } 04874 return -1; 04875 }
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 3147 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().
03148 { 03149 const char not_found = '\0'; 03150 char *tmpvar; 03151 const char *ret; 03152 const char *s; /* the result */ 03153 int offset, length; 03154 int i, need_substring; 03155 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03156 char workspace[20]; 03157 03158 if (c) { 03159 ast_channel_lock(c); 03160 places[0] = &c->varshead; 03161 } 03162 /* 03163 * Make a copy of var because parse_variable_name() modifies the string. 03164 * Then if called directly, we might need to run substring() on the result; 03165 * remember this for later in 'need_substring', 'offset' and 'length' 03166 */ 03167 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03168 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03169 03170 /* 03171 * Look first into predefined variables, then into variable lists. 03172 * Variable 's' points to the result, according to the following rules: 03173 * s == ¬_found (set at the beginning) means that we did not find a 03174 * matching variable and need to look into more places. 03175 * If s != ¬_found, s is a valid result string as follows: 03176 * s = NULL if the variable does not have a value; 03177 * you typically do this when looking for an unset predefined variable. 03178 * s = workspace if the result has been assembled there; 03179 * typically done when the result is built e.g. with an snprintf(), 03180 * so we don't need to do an additional copy. 03181 * s != workspace in case we have a string, that needs to be copied 03182 * (the ast_copy_string is done once for all at the end). 03183 * Typically done when the result is already available in some string. 03184 */ 03185 s = ¬_found; /* default value */ 03186 if (c) { /* This group requires a valid channel */ 03187 /* Names with common parts are looked up a piece at a time using strncmp. */ 03188 if (!strncmp(var, "CALL", 4)) { 03189 if (!strncmp(var + 4, "ING", 3)) { 03190 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03191 ast_str_set(str, maxlen, "%d", 03192 ast_party_id_presentation(&c->caller.id)); 03193 s = ast_str_buffer(*str); 03194 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03195 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03196 s = ast_str_buffer(*str); 03197 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03198 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03199 s = ast_str_buffer(*str); 03200 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03201 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03202 s = ast_str_buffer(*str); 03203 } 03204 } 03205 } else if (!strcmp(var, "HINT")) { 03206 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03207 } else if (!strcmp(var, "HINTNAME")) { 03208 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03209 } else if (!strcmp(var, "EXTEN")) { 03210 s = c->exten; 03211 } else if (!strcmp(var, "CONTEXT")) { 03212 s = c->context; 03213 } else if (!strcmp(var, "PRIORITY")) { 03214 ast_str_set(str, maxlen, "%d", c->priority); 03215 s = ast_str_buffer(*str); 03216 } else if (!strcmp(var, "CHANNEL")) { 03217 s = c->name; 03218 } else if (!strcmp(var, "UNIQUEID")) { 03219 s = c->uniqueid; 03220 } else if (!strcmp(var, "HANGUPCAUSE")) { 03221 ast_str_set(str, maxlen, "%d", c->hangupcause); 03222 s = ast_str_buffer(*str); 03223 } 03224 } 03225 if (s == ¬_found) { /* look for more */ 03226 if (!strcmp(var, "EPOCH")) { 03227 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03228 s = ast_str_buffer(*str); 03229 } else if (!strcmp(var, "SYSTEMNAME")) { 03230 s = ast_config_AST_SYSTEM_NAME; 03231 } else if (!strcmp(var, "ENTITYID")) { 03232 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03233 s = workspace; 03234 } 03235 } 03236 /* if not found, look into chanvars or global vars */ 03237 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03238 struct ast_var_t *variables; 03239 if (!places[i]) 03240 continue; 03241 if (places[i] == &globals) 03242 ast_rwlock_rdlock(&globalslock); 03243 AST_LIST_TRAVERSE(places[i], variables, entries) { 03244 if (!strcasecmp(ast_var_name(variables), var)) { 03245 s = ast_var_value(variables); 03246 break; 03247 } 03248 } 03249 if (places[i] == &globals) 03250 ast_rwlock_unlock(&globalslock); 03251 } 03252 if (s == ¬_found || s == NULL) { 03253 ast_debug(5, "Result of '%s' is NULL\n", var); 03254 ret = NULL; 03255 } else { 03256 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03257 if (s != ast_str_buffer(*str)) { 03258 ast_str_set(str, maxlen, "%s", s); 03259 } 03260 ret = ast_str_buffer(*str); 03261 if (need_substring) { 03262 ret = ast_str_substring(*str, offset, length); 03263 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03264 } 03265 } 03266 03267 if (c) { 03268 ast_channel_unlock(c); 03269 } 03270 return ret; 03271 }
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 3945 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().
03946 { 03947 size_t used; 03948 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 03949 }
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 3766 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().
03767 { 03768 /* Substitutes variables into buf, based on string templ */ 03769 char *cp4 = NULL; 03770 const char *tmp, *whereweare; 03771 int orig_size = 0; 03772 int offset, offset2, isfunction; 03773 const char *nextvar, *nextexp, *nextthing; 03774 const char *vars, *vare; 03775 char *finalvars; 03776 int pos, brackets, needsub, len; 03777 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03778 03779 ast_str_reset(*buf); 03780 whereweare = tmp = templ; 03781 while (!ast_strlen_zero(whereweare)) { 03782 /* reset our buffer */ 03783 ast_str_reset(substr3); 03784 03785 /* Assume we're copying the whole remaining string */ 03786 pos = strlen(whereweare); 03787 nextvar = NULL; 03788 nextexp = NULL; 03789 nextthing = strchr(whereweare, '$'); 03790 if (nextthing) { 03791 switch (nextthing[1]) { 03792 case '{': 03793 nextvar = nextthing; 03794 pos = nextvar - whereweare; 03795 break; 03796 case '[': 03797 nextexp = nextthing; 03798 pos = nextexp - whereweare; 03799 break; 03800 default: 03801 pos = 1; 03802 } 03803 } 03804 03805 if (pos) { 03806 /* Copy that many bytes */ 03807 ast_str_append_substr(buf, maxlen, whereweare, pos); 03808 03809 templ += pos; 03810 whereweare += pos; 03811 } 03812 03813 if (nextvar) { 03814 /* We have a variable. Find the start and end, and determine 03815 if we are going to have to recursively call ourselves on the 03816 contents */ 03817 vars = vare = nextvar + 2; 03818 brackets = 1; 03819 needsub = 0; 03820 03821 /* Find the end of it */ 03822 while (brackets && *vare) { 03823 if ((vare[0] == '$') && (vare[1] == '{')) { 03824 needsub++; 03825 } else if (vare[0] == '{') { 03826 brackets++; 03827 } else if (vare[0] == '}') { 03828 brackets--; 03829 } else if ((vare[0] == '$') && (vare[1] == '[')) 03830 needsub++; 03831 vare++; 03832 } 03833 if (brackets) 03834 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03835 len = vare - vars - 1; 03836 03837 /* Skip totally over variable string */ 03838 whereweare += (len + 3); 03839 03840 /* Store variable name (and truncate) */ 03841 ast_str_set_substr(&substr1, 0, vars, len); 03842 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03843 03844 /* Substitute if necessary */ 03845 if (needsub) { 03846 size_t used; 03847 if (!substr2) { 03848 substr2 = ast_str_create(16); 03849 } 03850 03851 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03852 finalvars = ast_str_buffer(substr2); 03853 } else { 03854 finalvars = ast_str_buffer(substr1); 03855 } 03856 03857 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03858 if (isfunction) { 03859 /* Evaluate function */ 03860 if (c || !headp) { 03861 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03862 } else { 03863 struct varshead old; 03864 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03865 if (bogus) { 03866 memcpy(&old, &bogus->varshead, sizeof(old)); 03867 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03868 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03869 /* Don't deallocate the varshead that was passed in */ 03870 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03871 ast_channel_unref(bogus); 03872 } else { 03873 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03874 } 03875 } 03876 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03877 } else { 03878 /* Retrieve variable value */ 03879 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 03880 cp4 = ast_str_buffer(substr3); 03881 } 03882 if (cp4) { 03883 ast_str_substring(substr3, offset, offset2); 03884 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03885 } 03886 } else if (nextexp) { 03887 /* We have an expression. Find the start and end, and determine 03888 if we are going to have to recursively call ourselves on the 03889 contents */ 03890 vars = vare = nextexp + 2; 03891 brackets = 1; 03892 needsub = 0; 03893 03894 /* Find the end of it */ 03895 while (brackets && *vare) { 03896 if ((vare[0] == '$') && (vare[1] == '[')) { 03897 needsub++; 03898 brackets++; 03899 vare++; 03900 } else if (vare[0] == '[') { 03901 brackets++; 03902 } else if (vare[0] == ']') { 03903 brackets--; 03904 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03905 needsub++; 03906 vare++; 03907 } 03908 vare++; 03909 } 03910 if (brackets) 03911 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03912 len = vare - vars - 1; 03913 03914 /* Skip totally over expression */ 03915 whereweare += (len + 3); 03916 03917 /* Store variable name (and truncate) */ 03918 ast_str_set_substr(&substr1, 0, vars, len); 03919 03920 /* Substitute if necessary */ 03921 if (needsub) { 03922 size_t used; 03923 if (!substr2) { 03924 substr2 = ast_str_create(16); 03925 } 03926 03927 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03928 finalvars = ast_str_buffer(substr2); 03929 } else { 03930 finalvars = ast_str_buffer(substr1); 03931 } 03932 03933 if (ast_str_expr(&substr3, 0, c, finalvars)) { 03934 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 03935 } 03936 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03937 } 03938 } 03939 *used = ast_str_strlen(*buf) - orig_size; 03940 ast_free(substr1); 03941 ast_free(substr2); 03942 ast_free(substr3); 03943 }
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 3951 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().
03952 { 03953 size_t used; 03954 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 03955 }
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 10374 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().
10375 { 10376 return ast_rwlock_unlock(&con->lock); 10377 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10356 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().
10357 { 10358 return ast_mutex_unlock(&conlock); 10359 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 5934 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().
05935 { 05936 AST_RWLIST_WRLOCK(&switches); 05937 AST_RWLIST_REMOVE(&switches, sw, list); 05938 AST_RWLIST_UNLOCK(&switches); 05939 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) |
Definition at line 10488 of file pbx.c.
References exten, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), context_used(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
10490 { 10491 if (!exten) 10492 return con ? con->root : NULL; 10493 else 10494 return exten->next; 10495 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 10521 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10523 { 10524 if (!ip) 10525 return con ? con->ignorepats : NULL; 10526 else 10527 return ip->next; 10528 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 10512 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), context_used(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
10514 { 10515 if (!inc) 10516 return con ? con->includes : NULL; 10517 else 10518 return inc->next; 10519 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 10497 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(), context_used(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10499 { 10500 if (!sw) 10501 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10502 else 10503 return AST_LIST_NEXT(sw, list); 10504 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 10483 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 10506 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 10364 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().
10365 { 10366 return ast_rwlock_wrlock(&con->lock); 10367 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10346 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().
10347 { 10348 return ast_mutex_lock(&conlock); 10349 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10140 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().
10141 { 10142 struct ast_var_t *vardata; 10143 10144 ast_rwlock_wrlock(&globalslock); 10145 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10146 ast_var_delete(vardata); 10147 ast_rwlock_unlock(&globalslock); 10148 }
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 9902 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_exec(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sig_pri_call(), sig_pri_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().
09903 { 09904 struct ast_var_t *variables; 09905 const char *ret = NULL; 09906 int i; 09907 struct varshead *places[2] = { NULL, &globals }; 09908 09909 if (!name) 09910 return NULL; 09911 09912 if (chan) { 09913 ast_channel_lock(chan); 09914 places[0] = &chan->varshead; 09915 } 09916 09917 for (i = 0; i < 2; i++) { 09918 if (!places[i]) 09919 continue; 09920 if (places[i] == &globals) 09921 ast_rwlock_rdlock(&globalslock); 09922 AST_LIST_TRAVERSE(places[i], variables, entries) { 09923 if (!strcmp(name, ast_var_name(variables))) { 09924 ret = ast_var_value(variables); 09925 break; 09926 } 09927 } 09928 if (places[i] == &globals) 09929 ast_rwlock_unlock(&globalslock); 09930 if (ret) 09931 break; 09932 } 09933 09934 if (chan) 09935 ast_channel_unlock(chan); 09936 09937 return ret; 09938 }
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 9940 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().
09941 { 09942 struct ast_var_t *newvariable; 09943 struct varshead *headp; 09944 09945 if (name[strlen(name)-1] == ')') { 09946 char *function = ast_strdupa(name); 09947 09948 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 09949 ast_func_write(chan, function, value); 09950 return; 09951 } 09952 09953 if (chan) { 09954 ast_channel_lock(chan); 09955 headp = &chan->varshead; 09956 } else { 09957 ast_rwlock_wrlock(&globalslock); 09958 headp = &globals; 09959 } 09960 09961 if (value) { 09962 if (headp == &globals) 09963 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09964 newvariable = ast_var_assign(name, value); 09965 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09966 } 09967 09968 if (chan) 09969 ast_channel_unlock(chan); 09970 else 09971 ast_rwlock_unlock(&globalslock); 09972 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Definition at line 3322 of file pbx.c.
References raise_exception().
03323 { 03324 /* Priority will become 1, next time through the AUTOLOOP */ 03325 return raise_exception(chan, reason, 0); 03326 }
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 9871 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().
09872 { 09873 struct ast_var_t *variables; 09874 const char *var, *val; 09875 int total = 0; 09876 09877 if (!chan) 09878 return 0; 09879 09880 ast_str_reset(*buf); 09881 09882 ast_channel_lock(chan); 09883 09884 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 09885 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 09886 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 09887 ) { 09888 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 09889 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 09890 break; 09891 } else 09892 total++; 09893 } else 09894 break; 09895 } 09896 09897 ast_channel_unlock(chan); 09898 09899 return total; 09900 }
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 10032 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().
10033 { 10034 char *name, *value, *mydata; 10035 10036 if (ast_compat_app_set) { 10037 return pbx_builtin_setvar_multiple(chan, data); 10038 } 10039 10040 if (ast_strlen_zero(data)) { 10041 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10042 return 0; 10043 } 10044 10045 mydata = ast_strdupa(data); 10046 name = strsep(&mydata, "="); 10047 value = mydata; 10048 if (!value) { 10049 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10050 return 0; 10051 } 10052 10053 if (strchr(name, ' ')) { 10054 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10055 } 10056 10057 pbx_builtin_setvar_helper(chan, name, value); 10058 10059 return 0; 10060 }
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 9974 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(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sig_pri_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(), 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().
09975 { 09976 struct ast_var_t *newvariable; 09977 struct varshead *headp; 09978 const char *nametail = name; 09979 09980 if (name[strlen(name) - 1] == ')') { 09981 char *function = ast_strdupa(name); 09982 09983 return ast_func_write(chan, function, value); 09984 } 09985 09986 if (chan) { 09987 ast_channel_lock(chan); 09988 headp = &chan->varshead; 09989 } else { 09990 ast_rwlock_wrlock(&globalslock); 09991 headp = &globals; 09992 } 09993 09994 /* For comparison purposes, we have to strip leading underscores */ 09995 if (*nametail == '_') { 09996 nametail++; 09997 if (*nametail == '_') 09998 nametail++; 09999 } 10000 10001 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10002 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10003 /* there is already such a variable, delete it */ 10004 AST_LIST_REMOVE_CURRENT(entries); 10005 ast_var_delete(newvariable); 10006 break; 10007 } 10008 } 10009 AST_LIST_TRAVERSE_SAFE_END; 10010 10011 if (value) { 10012 if (headp == &globals) 10013 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10014 newvariable = ast_var_assign(name, value); 10015 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10016 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10017 "Channel: %s\r\n" 10018 "Variable: %s\r\n" 10019 "Value: %s\r\n" 10020 "Uniqueid: %s\r\n", 10021 chan ? chan->name : "none", name, value, 10022 chan ? chan->uniqueid : "none"); 10023 } 10024 10025 if (chan) 10026 ast_channel_unlock(chan); 10027 else 10028 ast_rwlock_unlock(&globalslock); 10029 return 0; 10030 }
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 10062 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().
10063 { 10064 char *data; 10065 int x; 10066 AST_DECLARE_APP_ARGS(args, 10067 AST_APP_ARG(pair)[24]; 10068 ); 10069 AST_DECLARE_APP_ARGS(pair, 10070 AST_APP_ARG(name); 10071 AST_APP_ARG(value); 10072 ); 10073 10074 if (ast_strlen_zero(vdata)) { 10075 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10076 return 0; 10077 } 10078 10079 data = ast_strdupa(vdata); 10080 AST_STANDARD_APP_ARGS(args, data); 10081 10082 for (x = 0; x < args.argc; x++) { 10083 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10084 if (pair.argc == 2) { 10085 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10086 if (strchr(pair.name, ' ')) 10087 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); 10088 } else if (!chan) { 10089 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10090 } else { 10091 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10092 } 10093 } 10094 10095 return 0; 10096 }
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 10150 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().
10151 { 10152 int res; 10153 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10154 return 0; 10155 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10156 return res; 10157 } else { /* Strings are true */ 10158 return 1; 10159 } 10160 }
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 1418 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(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
01421 { 01422 int res; 01423 struct ast_module_user *u = NULL; 01424 const char *saved_c_appl; 01425 const char *saved_c_data; 01426 01427 if (c->cdr && !ast_check_hangup(c)) 01428 ast_cdr_setapp(c->cdr, app->name, data); 01429 01430 /* save channel values */ 01431 saved_c_appl= c->appl; 01432 saved_c_data= c->data; 01433 01434 c->appl = app->name; 01435 c->data = data; 01436 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01437 01438 if (app->module) 01439 u = __ast_module_user_add(app->module, c); 01440 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01441 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01442 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01443 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01444 app->name, (char *) data); 01445 } 01446 res = app->execute(c, S_OR(data, "")); 01447 if (app->module && u) 01448 __ast_module_user_remove(app->module, u); 01449 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01450 /* restore channel values */ 01451 c->appl = saved_c_appl; 01452 c->data = saved_c_data; 01453 return res; 01454 }
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 2715 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().
02719 { 02720 int x, res; 02721 struct ast_context *tmp = NULL; 02722 struct ast_exten *e = NULL, *eroot = NULL; 02723 struct ast_include *i = NULL; 02724 struct ast_sw *sw = NULL; 02725 struct ast_exten pattern = {NULL, }; 02726 struct scoreboard score = {0, }; 02727 struct ast_str *tmpdata = NULL; 02728 02729 pattern.label = label; 02730 pattern.priority = priority; 02731 #ifdef NEED_DEBUG_HERE 02732 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02733 #endif 02734 02735 /* Initialize status if appropriate */ 02736 if (q->stacklen == 0) { 02737 q->status = STATUS_NO_CONTEXT; 02738 q->swo = NULL; 02739 q->data = NULL; 02740 q->foundcontext = NULL; 02741 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02742 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02743 return NULL; 02744 } 02745 02746 /* Check first to see if we've already been checked */ 02747 for (x = 0; x < q->stacklen; x++) { 02748 if (!strcasecmp(q->incstack[x], context)) 02749 return NULL; 02750 } 02751 02752 if (bypass) { /* bypass means we only look there */ 02753 tmp = bypass; 02754 } else { /* look in contexts */ 02755 tmp = find_context(context); 02756 if (!tmp) { 02757 return NULL; 02758 } 02759 } 02760 02761 if (q->status < STATUS_NO_EXTENSION) 02762 q->status = STATUS_NO_EXTENSION; 02763 02764 /* Do a search for matching extension */ 02765 02766 eroot = NULL; 02767 score.total_specificity = 0; 02768 score.exten = 0; 02769 score.total_length = 0; 02770 if (!tmp->pattern_tree && tmp->root_table) { 02771 create_match_char_tree(tmp); 02772 #ifdef NEED_DEBUG 02773 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02774 log_match_char_tree(tmp->pattern_tree," "); 02775 #endif 02776 } 02777 #ifdef NEED_DEBUG 02778 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02779 log_match_char_tree(tmp->pattern_tree, ":: "); 02780 #endif 02781 02782 do { 02783 if (!ast_strlen_zero(overrideswitch)) { 02784 char *osw = ast_strdupa(overrideswitch), *name; 02785 struct ast_switch *asw; 02786 ast_switch_f *aswf = NULL; 02787 char *datap; 02788 int eval = 0; 02789 02790 name = strsep(&osw, "/"); 02791 asw = pbx_findswitch(name); 02792 02793 if (!asw) { 02794 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02795 break; 02796 } 02797 02798 if (osw && strchr(osw, '$')) { 02799 eval = 1; 02800 } 02801 02802 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02803 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 02804 break; 02805 } else if (eval) { 02806 /* Substitute variables now */ 02807 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02808 datap = ast_str_buffer(tmpdata); 02809 } else { 02810 datap = osw; 02811 } 02812 02813 /* equivalent of extension_match_core() at the switch level */ 02814 if (action == E_CANMATCH) 02815 aswf = asw->canmatch; 02816 else if (action == E_MATCHMORE) 02817 aswf = asw->matchmore; 02818 else /* action == E_MATCH */ 02819 aswf = asw->exists; 02820 if (!aswf) { 02821 res = 0; 02822 } else { 02823 if (chan) { 02824 ast_autoservice_start(chan); 02825 } 02826 res = aswf(chan, context, exten, priority, callerid, datap); 02827 if (chan) { 02828 ast_autoservice_stop(chan); 02829 } 02830 } 02831 if (res) { /* Got a match */ 02832 q->swo = asw; 02833 q->data = datap; 02834 q->foundcontext = context; 02835 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02836 return NULL; 02837 } 02838 } 02839 } while (0); 02840 02841 if (extenpatternmatchnew) { 02842 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02843 eroot = score.exten; 02844 02845 if (score.last_char == '!' && action == E_MATCHMORE) { 02846 /* We match an extension ending in '!'. 02847 * The decision in this case is final and is NULL (no match). 02848 */ 02849 #ifdef NEED_DEBUG_HERE 02850 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02851 #endif 02852 return NULL; 02853 } 02854 02855 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02856 q->status = STATUS_SUCCESS; 02857 #ifdef NEED_DEBUG_HERE 02858 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02859 #endif 02860 return score.canmatch_exten; 02861 } 02862 02863 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02864 if (score.node) { 02865 struct ast_exten *z = trie_find_next_match(score.node); 02866 if (z) { 02867 #ifdef NEED_DEBUG_HERE 02868 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02869 #endif 02870 } else { 02871 if (score.canmatch_exten) { 02872 #ifdef NEED_DEBUG_HERE 02873 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02874 #endif 02875 return score.canmatch_exten; 02876 } else { 02877 #ifdef NEED_DEBUG_HERE 02878 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02879 #endif 02880 } 02881 } 02882 return z; 02883 } 02884 #ifdef NEED_DEBUG_HERE 02885 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02886 #endif 02887 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02888 } 02889 02890 if (eroot) { 02891 /* found entry, now look for the right priority */ 02892 if (q->status < STATUS_NO_PRIORITY) 02893 q->status = STATUS_NO_PRIORITY; 02894 e = NULL; 02895 if (action == E_FINDLABEL && label ) { 02896 if (q->status < STATUS_NO_LABEL) 02897 q->status = STATUS_NO_LABEL; 02898 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02899 } else { 02900 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02901 } 02902 if (e) { /* found a valid match */ 02903 q->status = STATUS_SUCCESS; 02904 q->foundcontext = context; 02905 #ifdef NEED_DEBUG_HERE 02906 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02907 #endif 02908 return e; 02909 } 02910 } 02911 } else { /* the old/current default exten pattern match algorithm */ 02912 02913 /* scan the list trying to match extension and CID */ 02914 eroot = NULL; 02915 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02916 int match = extension_match_core(eroot->exten, exten, action); 02917 /* 0 on fail, 1 on match, 2 on earlymatch */ 02918 02919 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02920 continue; /* keep trying */ 02921 if (match == 2 && action == E_MATCHMORE) { 02922 /* We match an extension ending in '!'. 02923 * The decision in this case is final and is NULL (no match). 02924 */ 02925 return NULL; 02926 } 02927 /* found entry, now look for the right priority */ 02928 if (q->status < STATUS_NO_PRIORITY) 02929 q->status = STATUS_NO_PRIORITY; 02930 e = NULL; 02931 if (action == E_FINDLABEL && label ) { 02932 if (q->status < STATUS_NO_LABEL) 02933 q->status = STATUS_NO_LABEL; 02934 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02935 } else { 02936 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02937 } 02938 if (e) { /* found a valid match */ 02939 q->status = STATUS_SUCCESS; 02940 q->foundcontext = context; 02941 return e; 02942 } 02943 } 02944 } 02945 02946 /* Check alternative switches */ 02947 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02948 struct ast_switch *asw = pbx_findswitch(sw->name); 02949 ast_switch_f *aswf = NULL; 02950 char *datap; 02951 02952 if (!asw) { 02953 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02954 continue; 02955 } 02956 02957 /* Substitute variables now */ 02958 if (sw->eval) { 02959 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02960 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 02961 continue; 02962 } 02963 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02964 } 02965 02966 /* equivalent of extension_match_core() at the switch level */ 02967 if (action == E_CANMATCH) 02968 aswf = asw->canmatch; 02969 else if (action == E_MATCHMORE) 02970 aswf = asw->matchmore; 02971 else /* action == E_MATCH */ 02972 aswf = asw->exists; 02973 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02974 if (!aswf) 02975 res = 0; 02976 else { 02977 if (chan) 02978 ast_autoservice_start(chan); 02979 res = aswf(chan, context, exten, priority, callerid, datap); 02980 if (chan) 02981 ast_autoservice_stop(chan); 02982 } 02983 if (res) { /* Got a match */ 02984 q->swo = asw; 02985 q->data = datap; 02986 q->foundcontext = context; 02987 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02988 return NULL; 02989 } 02990 } 02991 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02992 /* Now try any includes we have in this context */ 02993 for (i = tmp->includes; i; i = i->next) { 02994 if (include_valid(i)) { 02995 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02996 #ifdef NEED_DEBUG_HERE 02997 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02998 #endif 02999 return e; 03000 } 03001 if (q->swo) 03002 return NULL; 03003 } 03004 } 03005 return NULL; 03006 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 1462 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().
01463 { 01464 struct ast_app *tmp; 01465 01466 AST_RWLIST_RDLOCK(&apps); 01467 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01468 if (!strcasecmp(tmp->name, app)) 01469 break; 01470 } 01471 AST_RWLIST_UNLOCK(&apps); 01472 01473 return tmp; 01474 }
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 3136 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().
03137 { 03138 struct ast_str *str = ast_str_create(16); 03139 const char *cret; 03140 03141 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03142 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03143 *ret = cret ? workspace : NULL; 03144 ast_free(str); 03145 }
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 5415 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05416 { 05417 int oldval = autofallthrough; 05418 autofallthrough = newval; 05419 return oldval; 05420 }
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 5422 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05423 { 05424 int oldval = extenpatternmatchnew; 05425 extenpatternmatchnew = newval; 05426 return oldval; 05427 }
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 5429 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05430 { 05431 if (overrideswitch) { 05432 ast_free(overrideswitch); 05433 } 05434 if (!ast_strlen_zero(newval)) { 05435 overrideswitch = ast_strdup(newval); 05436 } else { 05437 overrideswitch = NULL; 05438 } 05439 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4153 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(), substituted(), and write_cdr().
04154 { 04155 size_t used; 04156 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04157 }
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 3957 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().
03958 { 03959 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03960 char *cp4 = NULL; 03961 const char *tmp, *whereweare, *orig_cp2 = cp2; 03962 int length, offset, offset2, isfunction; 03963 char *workspace = NULL; 03964 char *ltmp = NULL, *var = NULL; 03965 char *nextvar, *nextexp, *nextthing; 03966 char *vars, *vare; 03967 int pos, brackets, needsub, len; 03968 03969 *cp2 = 0; /* just in case nothing ends up there */ 03970 whereweare=tmp=cp1; 03971 while (!ast_strlen_zero(whereweare) && count) { 03972 /* Assume we're copying the whole remaining string */ 03973 pos = strlen(whereweare); 03974 nextvar = NULL; 03975 nextexp = NULL; 03976 nextthing = strchr(whereweare, '$'); 03977 if (nextthing) { 03978 switch (nextthing[1]) { 03979 case '{': 03980 nextvar = nextthing; 03981 pos = nextvar - whereweare; 03982 break; 03983 case '[': 03984 nextexp = nextthing; 03985 pos = nextexp - whereweare; 03986 break; 03987 default: 03988 pos = 1; 03989 } 03990 } 03991 03992 if (pos) { 03993 /* Can't copy more than 'count' bytes */ 03994 if (pos > count) 03995 pos = count; 03996 03997 /* Copy that many bytes */ 03998 memcpy(cp2, whereweare, pos); 03999 04000 count -= pos; 04001 cp2 += pos; 04002 whereweare += pos; 04003 *cp2 = 0; 04004 } 04005 04006 if (nextvar) { 04007 /* We have a variable. Find the start and end, and determine 04008 if we are going to have to recursively call ourselves on the 04009 contents */ 04010 vars = vare = nextvar + 2; 04011 brackets = 1; 04012 needsub = 0; 04013 04014 /* Find the end of it */ 04015 while (brackets && *vare) { 04016 if ((vare[0] == '$') && (vare[1] == '{')) { 04017 needsub++; 04018 } else if (vare[0] == '{') { 04019 brackets++; 04020 } else if (vare[0] == '}') { 04021 brackets--; 04022 } else if ((vare[0] == '$') && (vare[1] == '[')) 04023 needsub++; 04024 vare++; 04025 } 04026 if (brackets) 04027 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04028 len = vare - vars - 1; 04029 04030 /* Skip totally over variable string */ 04031 whereweare += (len + 3); 04032 04033 if (!var) 04034 var = alloca(VAR_BUF_SIZE); 04035 04036 /* Store variable name (and truncate) */ 04037 ast_copy_string(var, vars, len + 1); 04038 04039 /* Substitute if necessary */ 04040 if (needsub) { 04041 size_t used; 04042 if (!ltmp) 04043 ltmp = alloca(VAR_BUF_SIZE); 04044 04045 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04046 vars = ltmp; 04047 } else { 04048 vars = var; 04049 } 04050 04051 if (!workspace) 04052 workspace = alloca(VAR_BUF_SIZE); 04053 04054 workspace[0] = '\0'; 04055 04056 parse_variable_name(vars, &offset, &offset2, &isfunction); 04057 if (isfunction) { 04058 /* Evaluate function */ 04059 if (c || !headp) 04060 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04061 else { 04062 struct varshead old; 04063 struct ast_channel *c = ast_dummy_channel_alloc(); 04064 if (c) { 04065 memcpy(&old, &c->varshead, sizeof(old)); 04066 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04067 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04068 /* Don't deallocate the varshead that was passed in */ 04069 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04070 c = ast_channel_unref(c); 04071 } else { 04072 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04073 } 04074 } 04075 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04076 } else { 04077 /* Retrieve variable value */ 04078 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04079 } 04080 if (cp4) { 04081 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04082 04083 length = strlen(cp4); 04084 if (length > count) 04085 length = count; 04086 memcpy(cp2, cp4, length); 04087 count -= length; 04088 cp2 += length; 04089 *cp2 = 0; 04090 } 04091 } else if (nextexp) { 04092 /* We have an expression. Find the start and end, and determine 04093 if we are going to have to recursively call ourselves on the 04094 contents */ 04095 vars = vare = nextexp + 2; 04096 brackets = 1; 04097 needsub = 0; 04098 04099 /* Find the end of it */ 04100 while (brackets && *vare) { 04101 if ((vare[0] == '$') && (vare[1] == '[')) { 04102 needsub++; 04103 brackets++; 04104 vare++; 04105 } else if (vare[0] == '[') { 04106 brackets++; 04107 } else if (vare[0] == ']') { 04108 brackets--; 04109 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04110 needsub++; 04111 vare++; 04112 } 04113 vare++; 04114 } 04115 if (brackets) 04116 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04117 len = vare - vars - 1; 04118 04119 /* Skip totally over expression */ 04120 whereweare += (len + 3); 04121 04122 if (!var) 04123 var = alloca(VAR_BUF_SIZE); 04124 04125 /* Store variable name (and truncate) */ 04126 ast_copy_string(var, vars, len + 1); 04127 04128 /* Substitute if necessary */ 04129 if (needsub) { 04130 size_t used; 04131 if (!ltmp) 04132 ltmp = alloca(VAR_BUF_SIZE); 04133 04134 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04135 vars = ltmp; 04136 } else { 04137 vars = var; 04138 } 04139 04140 length = ast_expr(vars, cp2, count, c); 04141 04142 if (length) { 04143 ast_debug(1, "Expression result is '%s'\n", cp2); 04144 count -= length; 04145 cp2 += length; 04146 *cp2 = 0; 04147 } 04148 } 04149 } 04150 *used = cp2 - orig_cp2; 04151 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4159 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by dundi_lookup_local(), and loopback_subst().
04160 { 04161 size_t used; 04162 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04163 }