Core PBX routines and definitions. More...
#include "asterisk/sched.h"#include "asterisk/devicestate.h"#include "asterisk/chanvars.h"#include "asterisk/hashtab.h"#include "asterisk/stringfields.h"
Go to the source code of this file.
Data Structures | |
| struct | ast_custom_function |
| Data structure associated with a custom dialplan function. More... | |
| struct | ast_pbx |
| struct | ast_pbx_args |
| Options for ast_pbx_run(). More... | |
| struct | ast_switch |
| struct | ast_timing |
| struct | pbx_find_info |
Defines | |
| #define | ast_custom_function_register(acf) __ast_custom_function_register(acf, ast_module_info->self) |
| Register a custom function. | |
| #define | AST_MAX_APP 32 |
| #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 |
| #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 |
Typedefs | |
| 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_doc_src { AST_XML_DOC, AST_STATIC_DOC } |
From where the documentation come from. More... | |
| enum | ast_extension_states { AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0, AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4 } |
Extension states. More... | |
| enum | ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 } |
The result codes when starting the PBX on a channel with. More... | |
| enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22, E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
| int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
| Register a custom function. | |
| int | ast_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_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| Add an ignorepat. | |
| int | ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
| Add a switch. | |
| int | ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar) |
| Adds a switch (first param is a ast_context). | |
| void | ast_context_destroy (struct ast_context *con, const char *registrar) |
| Destroy a context (matches the specified context (or ANY context if NULL). | |
| struct ast_context * | ast_context_find (const char *name) |
| Find a context. | |
| struct ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
| Register a new context or find an existing one. | |
| int | ast_context_lockmacro (const char *macrocontext) |
| locks the macrolock in the given given context | |
| int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
| Remove a context include. | |
| int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Removes an include by an ast_context structure. | |
| int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
| Remove a switch. | |
| int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
| This function locks given context, removes switch, unlock context and return. | |
| int | ast_context_unlockmacro (const char *macrocontext) |
| Unlocks the macrolock in the given context. | |
| int | ast_context_verify_includes (struct ast_context *con) |
| Verifies includes in an ast_contect structure. | |
| struct ast_custom_function * | ast_custom_function_find (const char *name) |
| int | ast_custom_function_unregister (struct ast_custom_function *acf) |
| Unregister a custom function. | |
| int | ast_destroy_timing (struct ast_timing *i) |
| Deallocates memory structures associated with a timing bitmap. | |
| enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
| Map devstate to an extension state. | |
| int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Determine whether an extension exists. | |
| int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_extension_close (const char *pattern, const char *data, int needmore) |
| int | ast_extension_cmp (const char *a, const char *b) |
| Determine if one extension should match before another. | |
| int | ast_extension_match (const char *pattern, const char *extension) |
| Determine if a given extension matches a given pattern (in NXX format). | |
| int | ast_extension_patmatch (const char *pattern, const char *data) |
| int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
| Uses hint and devicestate callback to get the state of an extension. | |
| const char * | ast_extension_state2str (int extension_state) |
| Return string representation of the state of an extension. | |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
| Registers a state change callback. | |
| int | ast_extension_state_del (int id, ast_state_cb_type callback) |
| 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_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, int 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, int 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_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. | |
| int | ast_wrlock_contexts_version (void) |
| 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, void *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, void *data) |
| Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
| void | 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, void *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, void *data) |
| Execute an application. | |
| struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
| struct ast_app * | pbx_findapp (const char *app) |
| Look up an application. | |
| void | pbx_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) |
| int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
| Simply remove extension from context. | |
| int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked) |
| This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
| int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar) |
| int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked) |
| const char * | ast_get_context_name (struct ast_context *con) |
| struct ast_context * | ast_get_extension_context (struct ast_exten *exten) |
| const char * | ast_get_extension_name (struct ast_exten *exten) |
| const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
| const char * | ast_get_include_name (struct ast_include *include) |
| const char * | ast_get_switch_data (struct ast_sw *sw) |
| int | ast_get_switch_eval (struct ast_sw *sw) |
| const char * | ast_get_switch_name (struct ast_sw *sw) |
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 static string buffers | |
| void | ast_str_substitute_variables (struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *templ) |
| 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) |
Walking functions ... | |
| struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
| struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
| struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| struct ast_context * | ast_walk_contexts (struct ast_context *con) |
| struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
Core PBX routines and definitions.
Definition in file pbx.h.
| #define ast_custom_function_register | ( | acf | ) | __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function.
Definition at line 1028 of file pbx.h.
Referenced by load_module(), and reload().
| #define AST_MAX_APP 32 |
Max length of an application
Definition at line 36 of file pbx.h.
Referenced by destroy_station(), handle_show_function(), print_app_docs(), and sla_build_station().
| #define AST_PBX_ERROR 1 |
| #define AST_PBX_HANGUP -1 |
| #define AST_PBX_INCOMPLETE 12 |
Return to PBX matching, allowing more digits for the extension
Definition at line 46 of file pbx.h.
Referenced by __ast_pbx_run(), dial_exec_full(), pbx_builtin_incomplete(), and retrydial_exec().
| #define PRIORITY_HINT -1 |
Special Priority for a hint
Definition at line 49 of file pbx.h.
Referenced by add_extensions(), add_pri_lockopt(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_station(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), pbx_load_config(), print_ext(), and sla_build_station().
| 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_doc_src |
From where the documentation come from.
| AST_XML_DOC |
From XML documentation |
| AST_STATIC_DOC |
From application/function registration |
Definition at line 77 of file pbx.h.
00077 { 00078 AST_XML_DOC, /*!< From XML documentation */ 00079 AST_STATIC_DOC /*!< From application/function registration */ 00080 };
| enum ast_extension_states |
Extension states.
Definition at line 55 of file pbx.h.
00055 { 00056 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */ 00057 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */ 00058 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */ 00059 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */ 00060 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ 00061 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ 00062 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ 00063 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ 00064 };
| enum ast_pbx_result |
The result codes when starting the PBX on a channel with.
Definition at line 262 of file pbx.h.
00262 { 00263 AST_PBX_SUCCESS = 0, 00264 AST_PBX_FAILED = -1, 00265 AST_PBX_CALL_LIMIT = -2, 00266 };
| enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows. Note that the coding is such that the low 4 bits are the third argument to extension_match_core.
| E_MATCHMORE | |
| E_CANMATCH | |
| E_MATCH | |
| E_MATCH_MASK | |
| E_SPAWN | |
| E_FINDLABEL | |
| E_MATCHMORE | |
| E_CANMATCH | |
| E_MATCH | |
| E_MATCH_MASK | |
| E_SPAWN | |
| E_FINDLABEL |
Definition at line 1081 of file pbx.h.
01081 { 01082 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01083 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01084 E_MATCH = 0x02, /* extension is an exact match */ 01085 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01086 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01087 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01088 };
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 3289 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().
03290 { 03291 struct ast_custom_function *cur; 03292 char tmps[80]; 03293 03294 if (!acf) { 03295 return -1; 03296 } 03297 03298 acf->mod = mod; 03299 acf->docsrc = AST_STATIC_DOC; 03300 03301 if (acf_retrieve_docs(acf)) { 03302 return -1; 03303 } 03304 03305 AST_RWLIST_WRLOCK(&acf_root); 03306 03307 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03308 if (!strcmp(acf->name, cur->name)) { 03309 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03310 AST_RWLIST_UNLOCK(&acf_root); 03311 return -1; 03312 } 03313 } 03314 03315 /* Store in alphabetical order */ 03316 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03317 if (strcasecmp(acf->name, cur->name) < 0) { 03318 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03319 break; 03320 } 03321 } 03322 AST_RWLIST_TRAVERSE_SAFE_END; 03323 03324 if (!cur) { 03325 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03326 } 03327 03328 AST_RWLIST_UNLOCK(&acf_root); 03329 03330 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03331 03332 return 0; 03333 }
| int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 4601 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
04602 { 04603 return countcalls; 04604 }
| 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 7305 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state_add(), handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().
07308 { 07309 int ret = -1; 07310 struct ast_context *c = find_context_locked(context); 07311 07312 if (c) { 07313 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 07314 application, data, datad, registrar); 07315 ast_unlock_contexts(); 07316 } 07317 07318 return ret; 07319 }
| int ast_add_extension2 | ( | struct ast_context * | con, | |
| int | replace, | |||
| const char * | extension, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| const char * | application, | |||
| void * | data, | |||
| void(*)(void *) | datad, | |||
| const char * | registrar | |||
| ) |
Add an extension to an extension context, this time with an ast_context *.
Add an extension to an extension context, this time with an ast_context *.
We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.
The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.
EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set
Definition at line 7624 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), build_parkinglot(), context_merge(), load_config(), load_module(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
07628 { 07629 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 07630 }
| 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 7344 of file pbx.c.
References ast_channel::_state, ast_channel::accountcode, 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_channel::cdr, ast_channel::context, ast_channel::exten, 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_dtmfup(), handle_request_bye(), handle_request_refer(), pbx_parseable_goto(), process_ast_dsp(), sip_read(), and socket_process().
07345 { 07346 int res = 0; 07347 07348 ast_channel_lock(chan); 07349 07350 if (chan->pbx) { /* This channel is currently in the PBX */ 07351 ast_explicit_goto(chan, context, exten, priority + 1); 07352 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 07353 } else { 07354 /* In order to do it when the channel doesn't really exist within 07355 the PBX, we have to make a new channel, masquerade, and start the PBX 07356 at the new location */ 07357 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 07358 if (!tmpchan) { 07359 res = -1; 07360 } else { 07361 if (chan->cdr) { 07362 ast_cdr_discard(tmpchan->cdr); 07363 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 07364 } 07365 /* Make formats okay */ 07366 tmpchan->readformat = chan->readformat; 07367 tmpchan->writeformat = chan->writeformat; 07368 /* Setup proper location */ 07369 ast_explicit_goto(tmpchan, 07370 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 07371 07372 /* Masquerade into temp channel */ 07373 if (ast_channel_masquerade(tmpchan, chan)) { 07374 /* Failed to set up the masquerade. It's probably chan_local 07375 * in the middle of optimizing itself out. Sad. :( */ 07376 ast_hangup(tmpchan); 07377 tmpchan = NULL; 07378 res = -1; 07379 } else { 07380 /* Grab the locks and get going */ 07381 ast_channel_lock(tmpchan); 07382 ast_do_masquerade(tmpchan); 07383 ast_channel_unlock(tmpchan); 07384 /* Start the PBX going on our stolen channel */ 07385 if (ast_pbx_start(tmpchan)) { 07386 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 07387 ast_hangup(tmpchan); 07388 res = -1; 07389 } 07390 } 07391 } 07392 } 07393 ast_channel_unlock(chan); 07394 return res; 07395 }
| 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 7397 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
07398 { 07399 struct ast_channel *chan; 07400 int res = -1; 07401 07402 chan = ast_get_channel_by_name_locked(channame); 07403 if (chan) { 07404 res = ast_async_goto(chan, context, exten, priority); 07405 ast_channel_unlock(chan); 07406 } 07407 return res; 07408 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 9575 of file pbx.c.
References __ast_goto_if_exists().
09576 { 09577 return __ast_goto_if_exists(chan, context, exten, priority, 1); 09578 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9638 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
09639 { 09640 return pbx_parseable_goto(chan, goto_string, 1); 09641 }
| 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 6939 of file pbx.c.
References ast_strdup, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
06940 { 06941 char *info_save, *info; 06942 int j, num_fields, last_sep = -1; 06943 06944 /* Check for empty just in case */ 06945 if (ast_strlen_zero(info_in)) { 06946 return 0; 06947 } 06948 06949 /* make a copy just in case we were passed a static string */ 06950 info_save = info = ast_strdupa(info_in); 06951 06952 /* count the number of fields in the timespec */ 06953 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 06954 if (info[j] == ',') { 06955 last_sep = j; 06956 num_fields++; 06957 } 06958 } 06959 06960 /* save the timezone, if it is specified */ 06961 if (num_fields == 5) { 06962 i->timezone = ast_strdup(info + last_sep + 1); 06963 } else { 06964 i->timezone = NULL; 06965 } 06966 06967 /* Assume everything except time */ 06968 i->monthmask = 0xfff; /* 12 bits */ 06969 i->daymask = 0x7fffffffU; /* 31 bits */ 06970 i->dowmask = 0x7f; /* 7 bits */ 06971 /* on each call, use strsep() to move info to the next argument */ 06972 get_timerange(i, strsep(&info, "|,")); 06973 if (info) 06974 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 06975 if (info) 06976 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 06977 if (info) 06978 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 06979 return 1; 06980 }
| 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 4158 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), pri_dchannel(), skinny_ss(), ss_thread(), and valid_exit().
04159 { 04160 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04161 }
| 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 6982 of file pbx.c.
References ast_localtime(), ast_log(), ast_tvnow(), 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 iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
06983 { 06984 struct ast_tm tm; 06985 struct timeval now = ast_tvnow(); 06986 06987 ast_localtime(&now, &tm, i->timezone); 06988 06989 /* If it's not the right month, return */ 06990 if (!(i->monthmask & (1 << tm.tm_mon))) 06991 return 0; 06992 06993 /* If it's not that time of the month.... */ 06994 /* Warning, tm_mday has range 1..31! */ 06995 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 06996 return 0; 06997 06998 /* If it's not the right day of the week */ 06999 if (!(i->dowmask & (1 << tm.tm_wday))) 07000 return 0; 07001 07002 /* Sanity check the hour just to be safe */ 07003 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07004 ast_log(LOG_WARNING, "Insane time...\n"); 07005 return 0; 07006 } 07007 07008 /* Now the tough part, we calculate if it fits 07009 in the right time based on min/hour */ 07010 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)))) 07011 return 0; 07012 07013 /* If we got this far, then we're good */ 07014 return 1; 07015 }
| int ast_context_add_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Add an ignorepat.
| context | which context to add the ignorpattern to | |
| ignorepat | ignorepattern to set up for the extension | |
| registrar | registrar of the ignore pattern |
Adds an ignore pattern to a particular context.
| 0 | on success | |
| -1 | on failure |
Definition at line 7217 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
07218 { 07219 int ret = -1; 07220 struct ast_context *c = find_context_locked(context); 07221 07222 if (c) { 07223 ret = ast_context_add_ignorepat2(c, value, registrar); 07224 ast_unlock_contexts(); 07225 } 07226 return ret; 07227 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 7229 of file pbx.c.
References ast_calloc, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
07230 { 07231 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 07232 int length; 07233 char *pattern; 07234 length = sizeof(struct ast_ignorepat); 07235 length += strlen(value) + 1; 07236 if (!(ignorepat = ast_calloc(1, length))) 07237 return -1; 07238 /* The cast to char * is because we need to write the initial value. 07239 * The field is not supposed to be modified otherwise. Also, gcc 4.2 07240 * sees the cast as dereferencing a type-punned pointer and warns about 07241 * it. This is the workaround (we're telling gcc, yes, that's really 07242 * what we wanted to do). 07243 */ 07244 pattern = (char *) ignorepat->pattern; 07245 strcpy(pattern, value); 07246 ignorepat->next = NULL; 07247 ignorepat->registrar = registrar; 07248 ast_wrlock_context(con); 07249 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 07250 ignorepatl = ignorepatc; 07251 if (!strcasecmp(ignorepatc->pattern, value)) { 07252 /* Already there */ 07253 ast_unlock_context(con); 07254 errno = EEXIST; 07255 return -1; 07256 } 07257 } 07258 if (ignorepatl) 07259 ignorepatl->next = ignorepat; 07260 else 07261 con->ignorepats = ignorepat; 07262 ast_unlock_context(con); 07263 return 0; 07264 07265 }
| int ast_context_add_include | ( | const char * | context, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| context | context to add include to | |
| include | new include to add | |
| registrar | who's registering it |
Adds an include taking a char * string as the context parameter
| 0 | on success | |
| -1 | on error |
Definition at line 6768 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
06769 { 06770 int ret = -1; 06771 struct ast_context *c = find_context_locked(context); 06772 06773 if (c) { 06774 ret = ast_context_add_include2(c, include, registrar); 06775 ast_unlock_contexts(); 06776 } 06777 return ret; 06778 }
| int ast_context_add_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| con | context to add the include to | |
| include | include to add | |
| registrar | who registered the context |
Adds an include taking a struct ast_context as the first parameter
| 0 | on success | |
| -1 | on failure |
Definition at line 7032 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.
Referenced by ast_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
07034 { 07035 struct ast_include *new_include; 07036 char *c; 07037 struct ast_include *i, *il = NULL; /* include, include_last */ 07038 int length; 07039 char *p; 07040 07041 length = sizeof(struct ast_include); 07042 length += 2 * (strlen(value) + 1); 07043 07044 /* allocate new include structure ... */ 07045 if (!(new_include = ast_calloc(1, length))) 07046 return -1; 07047 /* Fill in this structure. Use 'p' for assignments, as the fields 07048 * in the structure are 'const char *' 07049 */ 07050 p = new_include->stuff; 07051 new_include->name = p; 07052 strcpy(p, value); 07053 p += strlen(value) + 1; 07054 new_include->rname = p; 07055 strcpy(p, value); 07056 /* Strip off timing info, and process if it is there */ 07057 if ( (c = strchr(p, ',')) ) { 07058 *c++ = '\0'; 07059 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07060 } 07061 new_include->next = NULL; 07062 new_include->registrar = registrar; 07063 07064 ast_wrlock_context(con); 07065 07066 /* ... go to last include and check if context is already included too... */ 07067 for (i = con->includes; i; i = i->next) { 07068 if (!strcasecmp(i->name, new_include->name)) { 07069 ast_destroy_timing(&(new_include->timing)); 07070 ast_free(new_include); 07071 ast_unlock_context(con); 07072 errno = EEXIST; 07073 return -1; 07074 } 07075 il = i; 07076 } 07077 07078 /* ... include new context into context list, unlock, return */ 07079 if (il) 07080 il->next = new_include; 07081 else 07082 con->includes = new_include; 07083 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07084 07085 ast_unlock_context(con); 07086 07087 return 0; 07088 }
| int ast_context_add_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| int | eval, | |||
| const char * | registrar | |||
| ) |
Add a switch.
| context | context to which to add the switch | |
| sw | switch to add | |
| data | data to pass to switch | |
| eval | whether to evaluate variables when running switch | |
| registrar | whoever registered the switch |
This function registers a switch with the asterisk switch architecture
| 0 | on success | |
| -1 | on failure |
Definition at line 7095 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07096 { 07097 int ret = -1; 07098 struct ast_context *c = find_context_locked(context); 07099 07100 if (c) { /* found, add switch to this context */ 07101 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07102 ast_unlock_contexts(); 07103 } 07104 return ret; 07105 }
| 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 7114 of file pbx.c.
References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_compile_ael2(), ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
07116 { 07117 struct ast_sw *new_sw; 07118 struct ast_sw *i; 07119 int length; 07120 char *p; 07121 07122 length = sizeof(struct ast_sw); 07123 length += strlen(value) + 1; 07124 if (data) 07125 length += strlen(data); 07126 length++; 07127 07128 /* allocate new sw structure ... */ 07129 if (!(new_sw = ast_calloc(1, length))) 07130 return -1; 07131 /* ... fill in this structure ... */ 07132 p = new_sw->stuff; 07133 new_sw->name = p; 07134 strcpy(new_sw->name, value); 07135 p += strlen(value) + 1; 07136 new_sw->data = p; 07137 if (data) { 07138 strcpy(new_sw->data, data); 07139 p += strlen(data) + 1; 07140 } else { 07141 strcpy(new_sw->data, ""); 07142 p++; 07143 } 07144 new_sw->eval = eval; 07145 new_sw->registrar = registrar; 07146 07147 /* ... try to lock this context ... */ 07148 ast_wrlock_context(con); 07149 07150 /* ... go to last sw and check if context is already swd too... */ 07151 AST_LIST_TRAVERSE(&con->alts, i, list) { 07152 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07153 ast_free(new_sw); 07154 ast_unlock_context(con); 07155 errno = EEXIST; 07156 return -1; 07157 } 07158 } 07159 07160 /* ... sw new context into context list, unlock, return */ 07161 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07162 07163 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07164 07165 ast_unlock_context(con); 07166 07167 return 0; 07168 }
| void ast_context_destroy | ( | struct ast_context * | con, | |
| const char * | registrar | |||
| ) |
Destroy a context (matches the specified context (or ANY context if NULL).
| con | context to destroy | |
| registrar | who registered it |
You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.
Definition at line 8415 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), sla_destroy(), and unload_module().
08416 { 08417 ast_wrlock_contexts(); 08418 __ast_context_destroy(contexts, contexts_table, con,registrar); 08419 ast_unlock_contexts(); 08420 }
| struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
| name | name of the context to find |
Will search for the context with the given name.
Definition at line 2430 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), load_config(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
02431 { 02432 struct ast_context *tmp = NULL; 02433 struct fake_context item; 02434 02435 ast_copy_string(item.name, name, sizeof(item.name)); 02436 02437 ast_rdlock_contexts(); 02438 if( contexts_table ) { 02439 tmp = ast_hashtab_lookup(contexts_table,&item); 02440 } else { 02441 while ( (tmp = ast_walk_contexts(tmp)) ) { 02442 if (!name || !strcasecmp(name, tmp->name)) { 02443 break; 02444 } 02445 } 02446 } 02447 ast_unlock_contexts(); 02448 return tmp; 02449 }
| struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| const char * | name, | |||
| const char * | registrar | |||
| ) | [read] |
Register a new context or find an existing one.
| extcontexts | pointer to the ast_context structure pointer | |
| exttable | pointer to the hashtable that contains all the elements in extcontexts | |
| name | name of the new context | |
| registrar | registrar of the context |
This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.
Definition at line 6424 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init(), ast_rdlock_contexts(), ast_rwlock_init(), ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), build_parkinglot(), config_parse_variables(), context_merge(), load_config(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
06425 { 06426 struct ast_context *tmp, **local_contexts; 06427 struct fake_context search; 06428 int length = sizeof(struct ast_context) + strlen(name) + 1; 06429 06430 if (!contexts_table) { 06431 contexts_table = ast_hashtab_create(17, 06432 ast_hashtab_compare_contexts, 06433 ast_hashtab_resize_java, 06434 ast_hashtab_newsize_java, 06435 ast_hashtab_hash_contexts, 06436 0); 06437 } 06438 06439 ast_copy_string(search.name, name, sizeof(search.name)); 06440 if (!extcontexts) { 06441 ast_rdlock_contexts(); 06442 local_contexts = &contexts; 06443 tmp = ast_hashtab_lookup(contexts_table, &search); 06444 ast_unlock_contexts(); 06445 if (tmp) { 06446 tmp->refcount++; 06447 return tmp; 06448 } 06449 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 06450 local_contexts = extcontexts; 06451 tmp = ast_hashtab_lookup(exttable, &search); 06452 if (tmp) { 06453 tmp->refcount++; 06454 return tmp; 06455 } 06456 } 06457 06458 if ((tmp = ast_calloc(1, length))) { 06459 ast_rwlock_init(&tmp->lock); 06460 ast_mutex_init(&tmp->macrolock); 06461 strcpy(tmp->name, name); 06462 tmp->root = NULL; 06463 tmp->root_table = NULL; 06464 tmp->registrar = ast_strdup(registrar); 06465 tmp->includes = NULL; 06466 tmp->ignorepats = NULL; 06467 tmp->refcount = 1; 06468 } else { 06469 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 06470 return NULL; 06471 } 06472 06473 if (!extcontexts) { 06474 ast_wrlock_contexts(); 06475 tmp->next = *local_contexts; 06476 *local_contexts = tmp; 06477 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 06478 ast_unlock_contexts(); 06479 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06480 ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06481 } else { 06482 tmp->next = *local_contexts; 06483 if (exttable) 06484 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 06485 06486 *local_contexts = tmp; 06487 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06488 ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06489 } 06490 return tmp; 06491 }
| int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
| macrocontext | name of the macro-context to lock |
Locks the given macro-context to ensure only one thread (call) can execute it at a time
| 0 | on success | |
| -1 | on failure |
Definition at line 4988 of file pbx.c.
References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
04989 { 04990 struct ast_context *c = NULL; 04991 int ret = -1; 04992 struct fake_context item; 04993 04994 ast_rdlock_contexts(); 04995 04996 ast_copy_string(item.name, context, sizeof(item.name)); 04997 04998 c = ast_hashtab_lookup(contexts_table,&item); 04999 if (c) 05000 ret = 0; 05001 05002 05003 #ifdef NOTNOW 05004 05005 while ((c = ast_walk_contexts(c))) { 05006 if (!strcmp(ast_get_context_name(c), context)) { 05007 ret = 0; 05008 break; 05009 } 05010 } 05011 05012 #endif 05013 ast_unlock_contexts(); 05014 05015 /* if we found context, lock macrolock */ 05016 if (ret == 0) { 05017 ret = ast_mutex_lock(&c->macrolock); 05018 } 05019 05020 return ret; 05021 }
| int ast_context_remove_extension | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar | |||
| ) |
Simply remove extension from context.
| context | context to remove extension from | |
| extension | which extension to remove | |
| priority | priority of extension to remove (0 to remove all) | |
| callerid | NULL to remove all; non-NULL to match a single record per priority | |
| matchcid | non-zero to match callerid element (if non-NULL); 0 to match default case | |
| registrar | registrar of the extension |
This function removes an extension from a given context.
| 0 | on success | |
| -1 | on failure |
Definition at line 4796 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
04797 { 04798 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 04799 }
| 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 4823 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by load_config(), manage_parkinglot(), park_exec_full(), and unload_module().
04824 { 04825 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 04826 }
| 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 4801 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().
04802 { 04803 int ret = -1; /* default error return */ 04804 struct ast_context *c = find_context_locked(context); 04805 04806 if (c) { /* ... remove extension ... */ 04807 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 04808 ast_unlock_contexts(); 04809 } 04810 return ret; 04811 }
| 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 4828 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
04829 { 04830 struct ast_exten *exten, *prev_exten = NULL; 04831 struct ast_exten *peer; 04832 struct ast_exten ex, *exten2, *exten3; 04833 char dummy_name[1024]; 04834 struct ast_exten *previous_peer = NULL; 04835 struct ast_exten *next_peer = NULL; 04836 int found = 0; 04837 04838 if (!already_locked) 04839 ast_wrlock_context(con); 04840 04841 /* Handle this is in the new world */ 04842 04843 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 04844 * peers, not just those matching the callerid. */ 04845 #ifdef NEED_DEBUG 04846 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 04847 #endif 04848 #ifdef CONTEXT_DEBUG 04849 check_contexts(__FILE__, __LINE__); 04850 #endif 04851 /* find this particular extension */ 04852 ex.exten = dummy_name; 04853 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 04854 ex.cidmatch = callerid; 04855 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 04856 exten = ast_hashtab_lookup(con->root_table, &ex); 04857 if (exten) { 04858 if (priority == 0) { 04859 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04860 if (!exten2) 04861 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); 04862 if (con->pattern_tree) { 04863 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04864 04865 if (x->exten) { /* this test for safety purposes */ 04866 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04867 x->exten = 0; /* get rid of what will become a bad pointer */ 04868 } else { 04869 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 04870 } 04871 } 04872 } else { 04873 ex.priority = priority; 04874 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 04875 if (exten2) { 04876 04877 if (exten2->label) { /* if this exten has a label, remove that, too */ 04878 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 04879 if (!exten3) 04880 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); 04881 } 04882 04883 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 04884 if (!exten3) 04885 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); 04886 if (exten2 == exten && exten2->peer) { 04887 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04888 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 04889 } 04890 if (ast_hashtab_size(exten->peer_table) == 0) { 04891 /* well, if the last priority of an exten is to be removed, 04892 then, the extension is removed, too! */ 04893 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 04894 if (!exten3) 04895 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 04896 if (con->pattern_tree) { 04897 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04898 if (x->exten) { /* this test for safety purposes */ 04899 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04900 x->exten = 0; /* get rid of what will become a bad pointer */ 04901 } 04902 } 04903 } 04904 } else { 04905 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 04906 priority, exten->exten, con->name); 04907 } 04908 } 04909 } else { 04910 /* hmmm? this exten is not in this pattern tree? */ 04911 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 04912 extension, con->name); 04913 } 04914 #ifdef NEED_DEBUG 04915 if (con->pattern_tree) { 04916 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 04917 log_match_char_tree(con->pattern_tree, " "); 04918 } 04919 #endif 04920 04921 /* scan the extension list to find first matching extension-registrar */ 04922 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 04923 if (!strcmp(exten->exten, extension) && 04924 (!registrar || !strcmp(exten->registrar, registrar)) && 04925 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 04926 break; 04927 } 04928 if (!exten) { 04929 /* we can't find right extension */ 04930 if (!already_locked) 04931 ast_unlock_context(con); 04932 return -1; 04933 } 04934 04935 /* scan the priority list to remove extension with exten->priority == priority */ 04936 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 04937 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))); 04938 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 04939 if ((priority == 0 || peer->priority == priority) && 04940 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 04941 (!registrar || !strcmp(peer->registrar, registrar) )) { 04942 found = 1; 04943 04944 /* we are first priority extension? */ 04945 if (!previous_peer) { 04946 /* 04947 * We are first in the priority chain, so must update the extension chain. 04948 * The next node is either the next priority or the next extension 04949 */ 04950 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 04951 if (peer->peer) { 04952 /* move the peer_table and peer_label_table down to the next peer, if 04953 it is there */ 04954 peer->peer->peer_table = peer->peer_table; 04955 peer->peer->peer_label_table = peer->peer_label_table; 04956 peer->peer_table = NULL; 04957 peer->peer_label_table = NULL; 04958 } 04959 if (!prev_exten) { /* change the root... */ 04960 con->root = next_node; 04961 } else { 04962 prev_exten->next = next_node; /* unlink */ 04963 } 04964 if (peer->peer) { /* update the new head of the pri list */ 04965 peer->peer->next = peer->next; 04966 } 04967 } else { /* easy, we are not first priority in extension */ 04968 previous_peer->peer = peer->peer; 04969 } 04970 04971 /* now, free whole priority extension */ 04972 destroy_exten(peer); 04973 } else { 04974 previous_peer = peer; 04975 } 04976 } 04977 if (!already_locked) 04978 ast_unlock_context(con); 04979 return found ? 0 : -1; 04980 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 7174 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07175 { 07176 int ret = -1; 07177 struct ast_context *c = find_context_locked(context); 07178 07179 if (c) { 07180 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 07181 ast_unlock_contexts(); 07182 } 07183 return ret; 07184 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 7186 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().
07187 { 07188 struct ast_ignorepat *ip, *ipl = NULL; 07189 07190 ast_wrlock_context(con); 07191 07192 for (ip = con->ignorepats; ip; ip = ip->next) { 07193 if (!strcmp(ip->pattern, ignorepat) && 07194 (!registrar || (registrar == ip->registrar))) { 07195 if (ipl) { 07196 ipl->next = ip->next; 07197 ast_free(ip); 07198 } else { 07199 con->ignorepats = ip->next; 07200 ast_free(ip); 07201 } 07202 ast_unlock_context(con); 07203 return 0; 07204 } 07205 ipl = ip; 07206 } 07207 07208 ast_unlock_context(con); 07209 errno = EINVAL; 07210 return -1; 07211 }
| 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 4687 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
04688 { 04689 int ret = -1; 04690 struct ast_context *c = find_context_locked(context); 04691 04692 if (c) { 04693 /* found, remove include from this context ... */ 04694 ret = ast_context_remove_include2(c, include, registrar); 04695 ast_unlock_contexts(); 04696 } 04697 return ret; 04698 }
| int ast_context_remove_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Removes an include by an ast_context structure.
| 0 | on success | |
| -1 | on success |
Removes an include by an ast_context structure.
| 0 | on success. | |
| -1 | on failure. |
Definition at line 4709 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().
04710 { 04711 struct ast_include *i, *pi = NULL; 04712 int ret = -1; 04713 04714 ast_wrlock_context(con); 04715 04716 /* find our include */ 04717 for (i = con->includes; i; pi = i, i = i->next) { 04718 if (!strcmp(i->name, include) && 04719 (!registrar || !strcmp(i->registrar, registrar))) { 04720 /* remove from list */ 04721 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 04722 if (pi) 04723 pi->next = i->next; 04724 else 04725 con->includes = i->next; 04726 /* free include and return */ 04727 ast_destroy_timing(&(i->timing)); 04728 ast_free(i); 04729 ret = 0; 04730 break; 04731 } 04732 } 04733 04734 ast_unlock_context(con); 04735 04736 return ret; 04737 }
| int ast_context_remove_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
Remove a switch.
Removes a switch with the given parameters
| 0 | on success | |
| -1 | on failure |
Definition at line 4744 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
04745 { 04746 int ret = -1; /* default error return */ 04747 struct ast_context *c = find_context_locked(context); 04748 04749 if (c) { 04750 /* remove switch from this context ... */ 04751 ret = ast_context_remove_switch2(c, sw, data, registrar); 04752 ast_unlock_contexts(); 04753 } 04754 return ret; 04755 }
| 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 4765 of file pbx.c.
References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
04766 { 04767 struct ast_sw *i; 04768 int ret = -1; 04769 04770 ast_wrlock_context(con); 04771 04772 /* walk switches */ 04773 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 04774 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 04775 (!registrar || !strcmp(i->registrar, registrar))) { 04776 /* found, remove from list */ 04777 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 04778 AST_LIST_REMOVE_CURRENT(list); 04779 ast_free(i); /* free switch and return */ 04780 ret = 0; 04781 break; 04782 } 04783 } 04784 AST_LIST_TRAVERSE_SAFE_END; 04785 04786 ast_unlock_context(con); 04787 04788 return ret; 04789 }
| int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
| macrocontext | name of the macro-context to unlock |
Unlocks the given macro-context so that another thread (call) can execute it
| 0 | on success | |
| -1 | on failure |
Definition at line 5028 of file pbx.c.
References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
05029 { 05030 struct ast_context *c = NULL; 05031 int ret = -1; 05032 struct fake_context item; 05033 05034 ast_rdlock_contexts(); 05035 05036 ast_copy_string(item.name, context, sizeof(item.name)); 05037 05038 c = ast_hashtab_lookup(contexts_table,&item); 05039 if (c) 05040 ret = 0; 05041 #ifdef NOTNOW 05042 05043 while ((c = ast_walk_contexts(c))) { 05044 if (!strcmp(ast_get_context_name(c), context)) { 05045 ret = 0; 05046 break; 05047 } 05048 } 05049 05050 #endif 05051 ast_unlock_contexts(); 05052 05053 /* if we found context, unlock macrolock */ 05054 if (ret == 0) { 05055 ret = ast_mutex_unlock(&c->macrolock); 05056 } 05057 05058 return ret; 05059 }
| 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 9532 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().
09533 { 09534 struct ast_include *inc = NULL; 09535 int res = 0; 09536 09537 while ( (inc = ast_walk_context_includes(con, inc)) ) { 09538 if (ast_context_find(inc->rname)) 09539 continue; 09540 09541 res = -1; 09542 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 09543 ast_get_context_name(con), inc->rname); 09544 break; 09545 } 09546 09547 return res; 09548 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3202 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_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03203 { 03204 struct ast_custom_function *acf = NULL; 03205 03206 AST_RWLIST_RDLOCK(&acf_root); 03207 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03208 if (!strcmp(name, acf->name)) 03209 break; 03210 } 03211 AST_RWLIST_UNLOCK(&acf_root); 03212 03213 return acf; 03214 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3216 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 load_module(), reload(), and unload_module().
03217 { 03218 struct ast_custom_function *cur; 03219 03220 if (!acf) { 03221 return -1; 03222 } 03223 03224 AST_RWLIST_WRLOCK(&acf_root); 03225 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03226 if (cur->docsrc == AST_XML_DOC) { 03227 ast_string_field_free_memory(acf); 03228 } 03229 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03230 } 03231 AST_RWLIST_UNLOCK(&acf_root); 03232 03233 return cur ? 0 : -1; 03234 }
| 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 7017 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
| enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
| [in] | device | state |
Definition at line 3770 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_state2().
03771 { 03772 switch (devstate) { 03773 case AST_DEVICE_ONHOLD: 03774 return AST_EXTENSION_ONHOLD; 03775 case AST_DEVICE_BUSY: 03776 return AST_EXTENSION_BUSY; 03777 case AST_DEVICE_UNAVAILABLE: 03778 case AST_DEVICE_UNKNOWN: 03779 case AST_DEVICE_INVALID: 03780 return AST_EXTENSION_UNAVAILABLE; 03781 case AST_DEVICE_RINGINUSE: 03782 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 03783 case AST_DEVICE_RINGING: 03784 return AST_EXTENSION_RINGING; 03785 case AST_DEVICE_INUSE: 03786 return AST_EXTENSION_INUSE; 03787 case AST_DEVICE_NOT_INUSE: 03788 return AST_EXTENSION_NOT_INUSE; 03789 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 03790 break; 03791 } 03792 03793 return AST_EXTENSION_NOT_INUSE; 03794 }
| 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 4143 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), privacy_exec(), process_ast_dsp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_read(), skinny_ss(), socket_process(), ss7_linkset(), ss_thread(), and waitstream_core().
04144 { 04145 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04146 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 7321 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
07322 { 07323 if (!chan) 07324 return -1; 07325 07326 ast_channel_lock(chan); 07327 07328 if (!ast_strlen_zero(context)) 07329 ast_copy_string(chan->context, context, sizeof(chan->context)); 07330 if (!ast_strlen_zero(exten)) 07331 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07332 if (priority > -1) { 07333 chan->priority = priority; 07334 /* see flag description in channel.h for explanation */ 07335 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 07336 chan->priority--; 07337 } 07338 07339 ast_channel_unlock(chan); 07340 07341 return 0; 07342 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 2407 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().
02408 { 02409 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02410 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02411 return extension_match_core(pattern, data, needmore); 02412 }
| 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 |
Checks whether or extension a should match before extension b
| 0 | if the two extensions have equal matching priority | |
| 1 | on a > b | |
| -1 | on a < b |
Definition at line 2209 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02210 { 02211 return ext_cmp(a, b); 02212 }
| 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. |
Checks whether or not the given extension matches the given pattern.
| 1 | on match | |
| 0 | on failure |
Definition at line 2402 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().
02403 { 02404 return extension_match_core(pattern, data, E_MATCH); 02405 }
| 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 3832 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().
03833 { 03834 struct ast_exten *e; 03835 03836 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 03837 return -1; /* No hint, return -1 */ 03838 } 03839 03840 return ast_extension_state2(e); /* Check all devices in the hint */ 03841 }
| 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 3820 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(), and show_channels_cb().
03821 { 03822 int i; 03823 03824 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 03825 if (extension_states[i].extension_state == extension_state) 03826 return extension_states[i].text; 03827 } 03828 return "Unknown"; 03829 }
| int ast_extension_state_add | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | callback, | |||
| void * | data | |||
| ) |
Registers a state change callback.
| context | which context to look in | |
| exten | which extension to get state | |
| callback | callback to call if state changed | |
| data | to pass to callback |
The callback is called if the state of an extension is changed.
| -1 | on failure | |
| ID | on success |
Definition at line 3896 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr(), ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_state_cb::callback, ast_hint::callbacks, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_hint::exten, ast_exten::exten, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, and stateid.
Referenced by __init_manager(), handle_request_subscribe(), and skinny_register().
03898 { 03899 struct ast_hint *hint; 03900 struct ast_state_cb *cblist; 03901 struct ast_exten *e; 03902 03903 /* If there's no context and extension: add callback to statecbs list */ 03904 if (!context && !exten) { 03905 AST_RWLIST_WRLOCK(&hints); 03906 03907 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03908 if (cblist->callback == callback) { 03909 cblist->data = data; 03910 AST_RWLIST_UNLOCK(&hints); 03911 return 0; 03912 } 03913 } 03914 03915 /* Now insert the callback */ 03916 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03917 AST_RWLIST_UNLOCK(&hints); 03918 return -1; 03919 } 03920 cblist->id = 0; 03921 cblist->callback = callback; 03922 cblist->data = data; 03923 03924 AST_LIST_INSERT_HEAD(&statecbs, cblist, entry); 03925 03926 AST_RWLIST_UNLOCK(&hints); 03927 03928 return 0; 03929 } 03930 03931 if (!context || !exten) 03932 return -1; 03933 03934 /* This callback type is for only one hint, so get the hint */ 03935 e = ast_hint_extension(NULL, context, exten); 03936 if (!e) { 03937 return -1; 03938 } 03939 03940 /* If this is a pattern, dynamically create a new extension for this 03941 * particular match. Note that this will only happen once for each 03942 * individual extension, because the pattern will no longer match first. 03943 */ 03944 if (e->exten[0] == '_') { 03945 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 03946 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 03947 e->registrar); 03948 e = ast_hint_extension(NULL, context, exten); 03949 if (!e || e->exten[0] == '_') { 03950 return -1; 03951 } 03952 } 03953 03954 /* Find the hint in the list of hints */ 03955 AST_RWLIST_WRLOCK(&hints); 03956 03957 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03958 if (hint->exten == e) 03959 break; 03960 } 03961 03962 if (!hint) { 03963 /* We have no hint, sorry */ 03964 AST_RWLIST_UNLOCK(&hints); 03965 return -1; 03966 } 03967 03968 /* Now insert the callback in the callback list */ 03969 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03970 AST_RWLIST_UNLOCK(&hints); 03971 return -1; 03972 } 03973 03974 cblist->id = stateid++; /* Unique ID for this callback */ 03975 cblist->callback = callback; /* Pointer to callback routine */ 03976 cblist->data = data; /* Data for the callback */ 03977 03978 AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry); 03979 03980 AST_RWLIST_UNLOCK(&hints); 03981 03982 return cblist->id; 03983 }
| int ast_extension_state_del | ( | int | id, | |
| ast_state_cb_type | callback | |||
| ) |
Deletes a registered state change callback by ID.
| id | of the callback to delete | |
| callback | callback |
Removes the callback from list of callbacks
| 0 | success | |
| -1 | failure |
Definition at line 3986 of file pbx.c.
References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, ast_hint::callbacks, and ast_state_cb::id.
Referenced by dialog_unlink_all(), handle_request_subscribe(), and skinny_unregister().
03987 { 03988 struct ast_state_cb *p_cur = NULL; 03989 int ret = -1; 03990 03991 if (!id && !callback) 03992 return -1; 03993 03994 AST_RWLIST_WRLOCK(&hints); 03995 03996 if (!id) { /* id == 0 is a callback without extension */ 03997 AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) { 03998 if (p_cur->callback == callback) { 03999 AST_LIST_REMOVE_CURRENT(entry); 04000 break; 04001 } 04002 } 04003 AST_LIST_TRAVERSE_SAFE_END; 04004 } else { /* callback with extension, find the callback based on ID */ 04005 struct ast_hint *hint; 04006 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04007 AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) { 04008 if (p_cur->id == id) { 04009 AST_LIST_REMOVE_CURRENT(entry); 04010 break; 04011 } 04012 } 04013 AST_LIST_TRAVERSE_SAFE_END; 04014 04015 if (p_cur) 04016 break; 04017 } 04018 } 04019 04020 if (p_cur) { 04021 ast_free(p_cur); 04022 } 04023 04024 AST_RWLIST_UNLOCK(&hints); 04025 04026 return ret; 04027 }
| 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 4148 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().
04149 { 04150 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04151 }
| int ast_findlabel_extension2 | ( | struct ast_channel * | c, | |
| struct ast_context * | con, | |||
| const char * | exten, | |||
| const char * | label, | |||
| const char * | callerid | |||
| ) |
Find the priority of an extension that has the specified label.
Definition at line 4153 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
04154 { 04155 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04156 }
| int ast_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | workspace, | |||
| size_t | len | |||
| ) |
executes a read operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| workspace | A pointer to safe memory to use for a return value | |
| len | the number of bytes in workspace |
This application executes a function in read mode on a given channel.
| 0 | success | |
| non-zero | failure |
Definition at line 3356 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::read.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03357 { 03358 char *copy = ast_strdupa(function); 03359 char *args = func_args(copy); 03360 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03361 03362 if (acfptr == NULL) 03363 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03364 else if (!acfptr->read) 03365 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03366 else { 03367 int res; 03368 struct ast_module_user *u = NULL; 03369 if (acfptr->mod) 03370 u = __ast_module_user_add(acfptr->mod, chan); 03371 res = acfptr->read(chan, copy, args, workspace, len); 03372 if (acfptr->mod && u) 03373 __ast_module_user_remove(acfptr->mod, u); 03374 return res; 03375 } 03376 return -1; 03377 }
| int ast_func_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| const char * | value | |||
| ) |
executes a write operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| value | A value parameter to pass for writing |
This application executes a function in write mode on a given channel.
| 0 | success | |
| non-zero | failure |
Definition at line 3379 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by action_setvar(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03380 { 03381 char *copy = ast_strdupa(function); 03382 char *args = func_args(copy); 03383 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03384 03385 if (acfptr == NULL) 03386 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03387 else if (!acfptr->write) 03388 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03389 else { 03390 int res; 03391 struct ast_module_user *u = NULL; 03392 if (acfptr->mod) 03393 u = __ast_module_user_add(acfptr->mod, chan); 03394 res = acfptr->write(chan, copy, args, value); 03395 if (acfptr->mod && u) 03396 __ast_module_user_remove(acfptr->mod, u); 03397 return res; 03398 } 03399 03400 return -1; 03401 }
| const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 9384 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_lockmacro(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_unlockmacro(), ast_context_verify_includes(), 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(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09385 { 09386 return con ? con->name : NULL; 09387 }
| const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 9422 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
09423 { 09424 return c ? c->registrar : NULL; 09425 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 9452 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint_nolock(), ast_extension_state2(), ast_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), manager_show_dialplan_helper(), and print_ext().
09453 { 09454 return e ? e->app : NULL; 09455 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 9457 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
09458 { 09459 return e ? e->data : NULL; 09460 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 9447 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09448 { 09449 return e ? e->cidmatch : NULL; 09450 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 9389 of file pbx.c.
References ast_exten::parent.
Referenced by handle_show_hint(), and handle_show_hints().
09390 { 09391 return exten ? exten->parent : NULL; 09392 }
| const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 9399 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
| int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 9442 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09443 { 09444 return e ? e->matchcid : 0; 09445 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 9394 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint_nolock(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().
09395 { 09396 return exten ? exten->exten : NULL; 09397 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 9414 of file pbx.c.
References ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
09415 { 09416 return exten ? exten->priority : -1; 09417 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 9427 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09428 { 09429 return e ? e->registrar : NULL; 09430 }
| 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 4126 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(), pbx_retrieve_variable(), skinny_extensionstate_cb(), and transmit_state_notify().
04127 { 04128 struct ast_exten *e = ast_hint_extension(c, context, exten); 04129 04130 if (e) { 04131 if (hint) 04132 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04133 if (name) { 04134 const char *tmp = ast_get_extension_app_data(e); 04135 if (tmp) 04136 ast_copy_string(name, tmp, namesize); 04137 } 04138 return -1; 04139 } 04140 return 0; 04141 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9409 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().
09410 { 09411 return ip ? ip->pattern : NULL; 09412 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9437 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().
09438 { 09439 return ip ? ip->registrar : NULL; 09440 }
| const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 9404 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 9432 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().
09433 { 09434 return i ? i->registrar : NULL; 09435 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 9467 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().
09468 { 09469 return sw ? sw->data : NULL; 09470 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 9472 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
09473 { 09474 return sw->eval; 09475 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 9462 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().
09463 { 09464 return sw ? sw->name : NULL; 09465 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 9477 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().
09478 { 09479 return sw ? sw->registrar : NULL; 09480 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 9570 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), and valid_exit().
09571 { 09572 return __ast_goto_if_exists(chan, context, exten, priority, 0); 09573 }
| int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) |
hashtable functions for contexts
Definition at line 994 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
00995 { 00996 const struct ast_context *ac = ah_a; 00997 const struct ast_context *bc = ah_b; 00998 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 00999 return 1; 01000 /* assume context names are registered in a string table! */ 01001 return strcmp(ac->name, bc->name); 01002 }
| unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1037 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().
01038 { 01039 const struct ast_context *ac = obj; 01040 return ast_hashtab_hash_string(ac->name); 01041 }
| int ast_ignore_pattern | ( | const char * | context, | |
| const char * | pattern | |||
| ) |
Checks to see if a number should be ignored.
| context | context to search within | |
| pattern | to check whether it should be ignored or not |
Check if a number should be ignored with respect to dialtone cancellation.
| 0 | if the pattern should not be ignored | |
| non-zero | if the pattern should be ignored |
Definition at line 7267 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().
07268 { 07269 struct ast_context *con = ast_context_find(context); 07270 if (con) { 07271 struct ast_ignorepat *pat; 07272 for (pat = con->ignorepats; pat; pat = pat->next) { 07273 if (ast_extension_match(pat->pattern, pattern)) 07274 return 1; 07275 } 07276 } 07277 07278 return 0; 07279 }
| 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 4163 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __ast_pbx_run(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_dchannel(), readexten_exec(), skinny_ss(), and ss_thread().
04164 { 04165 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04166 }
| 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 6623 of file pbx.c.
References __ast_internal_context_destroy(), ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, ast_exten::data, E_MATCH, ast_exten::exten, ast_hint::exten, ast_hint::laststate, LOG_WARNING, ast_context::name, ast_context::next, ast_sw::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
06624 { 06625 double ft; 06626 struct ast_context *tmp, *oldcontextslist; 06627 struct ast_hashtab *oldtable; 06628 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 06629 struct store_hint *this; 06630 struct ast_hint *hint; 06631 struct ast_exten *exten; 06632 int length; 06633 struct ast_state_cb *thiscb; 06634 struct ast_hashtab_iter *iter; 06635 06636 /* it is very important that this function hold the hint list lock _and_ the conlock 06637 during its operation; not only do we need to ensure that the list of contexts 06638 and extensions does not change, but also that no hint callbacks (watchers) are 06639 added or removed during the merge/delete process 06640 06641 in addition, the locks _must_ be taken in this order, because there are already 06642 other code paths that use this order 06643 */ 06644 06645 struct timeval begintime, writelocktime, endlocktime, enddeltime; 06646 int wrlock_ver; 06647 06648 begintime = ast_tvnow(); 06649 ast_rdlock_contexts(); 06650 iter = ast_hashtab_start_traversal(contexts_table); 06651 while ((tmp = ast_hashtab_next(iter))) { 06652 context_merge(extcontexts, exttable, tmp, registrar); 06653 } 06654 ast_hashtab_end_traversal(iter); 06655 wrlock_ver = ast_wrlock_contexts_version(); 06656 06657 ast_unlock_contexts(); /* this feels real retarded, but you must do 06658 what you must do If this isn't done, the following 06659 wrlock is a guraranteed deadlock */ 06660 ast_wrlock_contexts(); 06661 if (ast_wrlock_contexts_version() > wrlock_ver+1) { 06662 ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); 06663 } 06664 06665 AST_RWLIST_WRLOCK(&hints); 06666 writelocktime = ast_tvnow(); 06667 06668 /* preserve all watchers for hints */ 06669 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06670 if (!AST_LIST_EMPTY(&hint->callbacks)) { 06671 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 06672 if (!(this = ast_calloc(1, length))) 06673 continue; 06674 /* this removes all the callbacks from the hint into this. */ 06675 AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry); 06676 this->laststate = hint->laststate; 06677 this->context = this->data; 06678 strcpy(this->data, hint->exten->parent->name); 06679 this->exten = this->data + strlen(this->context) + 1; 06680 strcpy(this->exten, hint->exten->exten); 06681 AST_LIST_INSERT_HEAD(&store, this, list); 06682 } 06683 } 06684 06685 /* save the old table and list */ 06686 oldtable = contexts_table; 06687 oldcontextslist = contexts; 06688 06689 /* move in the new table and list */ 06690 contexts_table = exttable; 06691 contexts = *extcontexts; 06692 06693 /* restore the watchers for hints that can be found; notify those that 06694 cannot be restored 06695 */ 06696 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 06697 struct pbx_find_info q = { .stacklen = 0 }; 06698 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 06699 /* If this is a pattern, dynamically create a new extension for this 06700 * particular match. Note that this will only happen once for each 06701 * individual extension, because the pattern will no longer match first. 06702 */ 06703 if (exten && exten->exten[0] == '_') { 06704 ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL, 06705 0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar); 06706 /* rwlocks are not recursive locks */ 06707 exten = ast_hint_extension_nolock(NULL, this->context, this->exten); 06708 } 06709 06710 /* Find the hint in the list of hints */ 06711 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06712 if (hint->exten == exten) 06713 break; 06714 } 06715 if (!exten || !hint) { 06716 /* this hint has been removed, notify the watchers */ 06717 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 06718 thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data); 06719 ast_free(thiscb); 06720 } 06721 } else { 06722 AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry); 06723 hint->laststate = this->laststate; 06724 } 06725 ast_free(this); 06726 } 06727 06728 AST_RWLIST_UNLOCK(&hints); 06729 ast_unlock_contexts(); 06730 endlocktime = ast_tvnow(); 06731 06732 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 06733 is now freely using the new stuff instead */ 06734 06735 ast_hashtab_destroy(oldtable, NULL); 06736 06737 for (tmp = oldcontextslist; tmp; ) { 06738 struct ast_context *next; /* next starting point */ 06739 next = tmp->next; 06740 __ast_internal_context_destroy(tmp); 06741 tmp = next; 06742 } 06743 enddeltime = ast_tvnow(); 06744 06745 ft = ast_tvdiff_us(writelocktime, begintime); 06746 ft /= 1000000.0; 06747 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 06748 06749 ft = ast_tvdiff_us(endlocktime, writelocktime); 06750 ft /= 1000000.0; 06751 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 06752 06753 ft = ast_tvdiff_us(enddeltime, endlocktime); 06754 ft /= 1000000.0; 06755 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 06756 06757 ft = ast_tvdiff_us(enddeltime, begintime); 06758 ft /= 1000000.0; 06759 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 06760 return; 06761 }
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9633 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().
09634 { 09635 return pbx_parseable_goto(chan, goto_string, 0); 09636 }
| int ast_pbx_outgoing_app | ( | const char * | type, | |
| int | 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 8106 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, app_tmp::data, errno, ast_channel::hangupcause, LOG_WARNING, ast_channel::name, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
08107 { 08108 struct ast_channel *chan; 08109 struct app_tmp *tmp; 08110 int res = -1, cdr_res = -1; 08111 struct outgoing_helper oh; 08112 08113 memset(&oh, 0, sizeof(oh)); 08114 oh.vars = vars; 08115 oh.account = account; 08116 08117 if (locked_channel) 08118 *locked_channel = NULL; 08119 if (ast_strlen_zero(app)) { 08120 res = -1; 08121 goto outgoing_app_cleanup; 08122 } 08123 if (synchronous) { 08124 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 08125 if (chan) { 08126 ast_set_variables(chan, vars); 08127 if (account) 08128 ast_cdr_setaccount(chan, account); 08129 if (chan->_state == AST_STATE_UP) { 08130 res = 0; 08131 ast_verb(4, "Channel %s was answered.\n", chan->name); 08132 tmp = ast_calloc(1, sizeof(*tmp)); 08133 if (!tmp) 08134 res = -1; 08135 else { 08136 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 08137 if (appdata) 08138 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 08139 tmp->chan = chan; 08140 if (synchronous > 1) { 08141 if (locked_channel) 08142 ast_channel_unlock(chan); 08143 ast_pbx_run_app(tmp); 08144 } else { 08145 if (locked_channel) 08146 ast_channel_lock(chan); 08147 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 08148 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 08149 ast_free(tmp); 08150 if (locked_channel) 08151 ast_channel_unlock(chan); 08152 ast_hangup(chan); 08153 res = -1; 08154 } else { 08155 if (locked_channel) 08156 *locked_channel = chan; 08157 } 08158 } 08159 } 08160 } else { 08161 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08162 if (chan->cdr) { /* update the cdr */ 08163 /* here we update the status of the call, which sould be busy. 08164 * if that fails then we set the status to failed */ 08165 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08166 ast_cdr_failed(chan->cdr); 08167 } 08168 ast_hangup(chan); 08169 } 08170 } 08171 08172 if (res < 0) { /* the call failed for some reason */ 08173 if (*reason == 0) { /* if the call failed (not busy or no answer) 08174 * update the cdr with the failed message */ 08175 cdr_res = ast_pbx_outgoing_cdr_failed(); 08176 if (cdr_res != 0) { 08177 res = cdr_res; 08178 goto outgoing_app_cleanup; 08179 } 08180 } 08181 } 08182 08183 } else { 08184 struct async_stat *as; 08185 if (!(as = ast_calloc(1, sizeof(*as)))) { 08186 res = -1; 08187 goto outgoing_app_cleanup; 08188 } 08189 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 08190 if (!chan) { 08191 ast_free(as); 08192 res = -1; 08193 goto outgoing_app_cleanup; 08194 } 08195 as->chan = chan; 08196 ast_copy_string(as->app, app, sizeof(as->app)); 08197 if (appdata) 08198 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 08199 as->timeout = timeout; 08200 ast_set_variables(chan, vars); 08201 if (account) 08202 ast_cdr_setaccount(chan, account); 08203 /* Start a new thread, and get something handling this channel. */ 08204 if (locked_channel) 08205 ast_channel_lock(chan); 08206 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08207 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08208 ast_free(as); 08209 if (locked_channel) 08210 ast_channel_unlock(chan); 08211 ast_hangup(chan); 08212 res = -1; 08213 goto outgoing_app_cleanup; 08214 } else { 08215 if (locked_channel) 08216 *locked_channel = chan; 08217 } 08218 res = 0; 08219 } 08220 outgoing_app_cleanup: 08221 ast_variables_destroy(vars); 08222 return res; 08223 }
| int ast_pbx_outgoing_exten | ( | const char * | type, | |
| int | 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 7940 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
07941 { 07942 struct ast_channel *chan; 07943 struct async_stat *as; 07944 int res = -1, cdr_res = -1; 07945 struct outgoing_helper oh; 07946 07947 if (synchronous) { 07948 oh.context = context; 07949 oh.exten = exten; 07950 oh.priority = priority; 07951 oh.cid_num = cid_num; 07952 oh.cid_name = cid_name; 07953 oh.account = account; 07954 oh.vars = vars; 07955 oh.parent_channel = NULL; 07956 07957 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07958 if (channel) { 07959 *channel = chan; 07960 if (chan) 07961 ast_channel_lock(chan); 07962 } 07963 if (chan) { 07964 if (chan->_state == AST_STATE_UP) { 07965 res = 0; 07966 ast_verb(4, "Channel %s was answered.\n", chan->name); 07967 07968 if (synchronous > 1) { 07969 if (channel) 07970 ast_channel_unlock(chan); 07971 if (ast_pbx_run(chan)) { 07972 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07973 if (channel) 07974 *channel = NULL; 07975 ast_hangup(chan); 07976 chan = NULL; 07977 res = -1; 07978 } 07979 } else { 07980 if (ast_pbx_start(chan)) { 07981 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 07982 if (channel) { 07983 *channel = NULL; 07984 ast_channel_unlock(chan); 07985 } 07986 ast_hangup(chan); 07987 res = -1; 07988 } 07989 chan = NULL; 07990 } 07991 } else { 07992 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07993 07994 if (chan->cdr) { /* update the cdr */ 07995 /* here we update the status of the call, which sould be busy. 07996 * if that fails then we set the status to failed */ 07997 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07998 ast_cdr_failed(chan->cdr); 07999 } 08000 08001 if (channel) { 08002 *channel = NULL; 08003 ast_channel_unlock(chan); 08004 } 08005 ast_hangup(chan); 08006 chan = NULL; 08007 } 08008 } 08009 08010 if (res < 0) { /* the call failed for some reason */ 08011 if (*reason == 0) { /* if the call failed (not busy or no answer) 08012 * update the cdr with the failed message */ 08013 cdr_res = ast_pbx_outgoing_cdr_failed(); 08014 if (cdr_res != 0) { 08015 res = cdr_res; 08016 goto outgoing_exten_cleanup; 08017 } 08018 } 08019 08020 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08021 /* check if "failed" exists */ 08022 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08023 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 08024 if (chan) { 08025 char failed_reason[4] = ""; 08026 if (!ast_strlen_zero(context)) 08027 ast_copy_string(chan->context, context, sizeof(chan->context)); 08028 set_ext_pri(chan, "failed", 1); 08029 ast_set_variables(chan, vars); 08030 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08031 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08032 if (account) 08033 ast_cdr_setaccount(chan, account); 08034 if (ast_pbx_run(chan)) { 08035 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08036 ast_hangup(chan); 08037 } 08038 chan = NULL; 08039 } 08040 } 08041 } 08042 } else { 08043 if (!(as = ast_calloc(1, sizeof(*as)))) { 08044 res = -1; 08045 goto outgoing_exten_cleanup; 08046 } 08047 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 08048 if (channel) { 08049 *channel = chan; 08050 if (chan) 08051 ast_channel_lock(chan); 08052 } 08053 if (!chan) { 08054 ast_free(as); 08055 res = -1; 08056 goto outgoing_exten_cleanup; 08057 } 08058 as->chan = chan; 08059 ast_copy_string(as->context, context, sizeof(as->context)); 08060 set_ext_pri(as->chan, exten, priority); 08061 as->timeout = timeout; 08062 ast_set_variables(chan, vars); 08063 if (account) 08064 ast_cdr_setaccount(chan, account); 08065 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08066 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08067 ast_free(as); 08068 if (channel) { 08069 *channel = NULL; 08070 ast_channel_unlock(chan); 08071 } 08072 ast_hangup(chan); 08073 res = -1; 08074 goto outgoing_exten_cleanup; 08075 } 08076 res = 0; 08077 } 08078 outgoing_exten_cleanup: 08079 ast_variables_destroy(vars); 08080 return res; 08081 }
| enum ast_pbx_result ast_pbx_run | ( | struct ast_channel * | c | ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
| Zero | on success | |
| non-zero | on failure |
Definition at line 4596 of file pbx.c.
References ast_pbx_run_args().
Referenced by ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), mgcp_ss(), skinny_newcall(), ss_thread(), and unistim_ss().
04597 { 04598 return ast_pbx_run_args(c, NULL); 04599 }
| enum ast_pbx_result ast_pbx_run_args | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on | |
| args | options for the pbx |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
| Zero | on success | |
| non-zero | on failure |
Definition at line 4581 of file pbx.c.
References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
04582 { 04583 enum ast_pbx_result res = AST_PBX_SUCCESS; 04584 04585 if (increase_call_count(c)) { 04586 return AST_PBX_CALL_LIMIT; 04587 } 04588 04589 res = __ast_pbx_run(c, args); 04590 04591 decrease_call_count(); 04592 04593 return res; 04594 }
| 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 4559 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, 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(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parkinglot(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), pri_dchannel(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().
04560 { 04561 pthread_t t; 04562 04563 if (!c) { 04564 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 04565 return AST_PBX_FAILED; 04566 } 04567 04568 if (increase_call_count(c)) 04569 return AST_PBX_CALL_LIMIT; 04570 04571 /* Start a new thread, and get something handling this channel. */ 04572 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 04573 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 04574 decrease_call_count(); 04575 return AST_PBX_FAILED; 04576 } 04577 04578 return AST_PBX_SUCCESS; 04579 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 4606 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
04607 { 04608 return totalcalls; 04609 }
| 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 9371 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().
09372 { 09373 return ast_rwlock_rdlock(&con->lock); 09374 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 9353 of file pbx.c.
References ast_rwlock_rdlock(), and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09354 { 09355 return ast_rwlock_rdlock(&conlock); 09356 }
| int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
| sw | switch to register |
This function registers a populated ast_switch structure with the asterisk switching architecture.
| 0 | success | |
| non-zero | failure |
Definition at line 5157 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
05158 { 05159 struct ast_switch *tmp; 05160 05161 AST_RWLIST_WRLOCK(&switches); 05162 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05163 if (!strcasecmp(tmp->name, sw->name)) { 05164 AST_RWLIST_UNLOCK(&switches); 05165 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05166 return -1; 05167 } 05168 } 05169 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05170 AST_RWLIST_UNLOCK(&switches); 05171 05172 return 0; 05173 }
| 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 4168 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().
04169 { 04170 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04171 }
| void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
| size_t | maxlen, | |||
| struct ast_channel * | chan, | |||
| const char * | templ | |||
| ) |
Definition at line 114 of file strings.c.
References ast_str_make_space(), first, and pbx_substitute_variables_helper_full().
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), and cli_odbc_write().
00115 { 00116 int first = 1; 00117 do { 00118 ast_str_make_space(buf, maxlen ? maxlen : 00119 (first ? strlen(template) * 2 : (*buf)->__AST_STR_LEN * 2)); 00120 pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->__AST_STR_STR, (*buf)->__AST_STR_LEN - 1, &((*buf)->__AST_STR_USED)); 00121 first = 0; 00122 } while (maxlen == 0 && (*buf)->__AST_STR_LEN - 5 < (*buf)->__AST_STR_USED); 00123 }
| 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 9376 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().
09377 { 09378 return ast_rwlock_unlock(&con->lock); 09379 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 9358 of file pbx.c.
References ast_rwlock_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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09359 { 09360 return ast_rwlock_unlock(&conlock); 09361 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 5175 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
05176 { 05177 AST_RWLIST_WRLOCK(&switches); 05178 AST_RWLIST_REMOVE(&switches, sw, list); 05179 AST_RWLIST_UNLOCK(&switches); 05180 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 9490 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
| struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
| struct ast_ignorepat * | ip | |||
| ) | [read] |
Definition at line 9523 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
09525 { 09526 if (!ip) 09527 return con ? con->ignorepats : NULL; 09528 else 09529 return ip->next; 09530 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 9514 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
| struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
| struct ast_sw * | sw | |||
| ) | [read] |
Definition at line 9499 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09501 { 09502 if (!sw) 09503 return con ? AST_LIST_FIRST(&con->alts) : NULL; 09504 else 09505 return AST_LIST_NEXT(sw, list); 09506 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 9485 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), 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(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
| struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 9508 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
09510 { 09511 return priority ? priority->peer : exten; 09512 }
| 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 9366 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().
09367 { 09368 return ast_rwlock_wrlock(&con->lock); 09369 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 9345 of file pbx.c.
References ast_atomic_fetchadd_int(), ast_rwlock_wrlock(), conlock, and conlock_wrlock_version.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
09346 { 09347 int res = ast_rwlock_wrlock(&conlock); 09348 if (!res) 09349 ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); 09350 return res; 09351 }
| int ast_wrlock_contexts_version | ( | void | ) |
Definition at line 9337 of file pbx.c.
References conlock_wrlock_version.
Referenced by ast_merge_contexts_and_delete().
09338 { 09339 return conlock_wrlock_version; 09340 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 9182 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().
09183 { 09184 struct ast_var_t *vardata; 09185 09186 ast_rwlock_wrlock(&globalslock); 09187 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 09188 ast_var_delete(vardata); 09189 ast_rwlock_unlock(&globalslock); 09190 }
| const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name | |||
| ) |
Return a pointer to the value of the corresponding channel variable.
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 8951 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_call_forward(), ast_eivr_getvariable(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), confbridge_exec(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), listfilter(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
08952 { 08953 struct ast_var_t *variables; 08954 const char *ret = NULL; 08955 int i; 08956 struct varshead *places[2] = { NULL, &globals }; 08957 08958 if (!name) 08959 return NULL; 08960 08961 if (chan) { 08962 ast_channel_lock(chan); 08963 places[0] = &chan->varshead; 08964 } 08965 08966 for (i = 0; i < 2; i++) { 08967 if (!places[i]) 08968 continue; 08969 if (places[i] == &globals) 08970 ast_rwlock_rdlock(&globalslock); 08971 AST_LIST_TRAVERSE(places[i], variables, entries) { 08972 if (!strcmp(name, ast_var_name(variables))) { 08973 ret = ast_var_value(variables); 08974 break; 08975 } 08976 } 08977 if (places[i] == &globals) 08978 ast_rwlock_unlock(&globalslock); 08979 if (ret) 08980 break; 08981 } 08982 08983 if (chan) 08984 ast_channel_unlock(chan); 08985 08986 return ret; 08987 }
| 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 8989 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_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
08990 { 08991 struct ast_var_t *newvariable; 08992 struct varshead *headp; 08993 08994 if (name[strlen(name)-1] == ')') { 08995 char *function = ast_strdupa(name); 08996 08997 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 08998 ast_func_write(chan, function, value); 08999 return; 09000 } 09001 09002 if (chan) { 09003 ast_channel_lock(chan); 09004 headp = &chan->varshead; 09005 } else { 09006 ast_rwlock_wrlock(&globalslock); 09007 headp = &globals; 09008 } 09009 09010 if (value) { 09011 if (headp == &globals) 09012 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09013 newvariable = ast_var_assign(name, value); 09014 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09015 } 09016 09017 if (chan) 09018 ast_channel_unlock(chan); 09019 else 09020 ast_rwlock_unlock(&globalslock); 09021 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) |
Definition at line 2995 of file pbx.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_free, ast_string_field_init, ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run().
02996 { 02997 const char *reason = vreason; 02998 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02999 struct pbx_exception *exception = NULL; 03000 03001 if (!ds) { 03002 ds = ast_datastore_alloc(&exception_store_info, NULL); 03003 if (!ds) 03004 return -1; 03005 exception = ast_calloc(1, sizeof(struct pbx_exception)); 03006 if (!exception) { 03007 ast_datastore_free(ds); 03008 return -1; 03009 } 03010 if (ast_string_field_init(exception, 128)) { 03011 ast_free(exception); 03012 ast_datastore_free(ds); 03013 return -1; 03014 } 03015 ds->data = exception; 03016 ast_channel_datastore_add(chan, ds); 03017 } else 03018 exception = ds->data; 03019 03020 ast_string_field_set(exception, reason, reason); 03021 ast_string_field_set(exception, context, chan->context); 03022 ast_string_field_set(exception, exten, chan->exten); 03023 exception->priority = chan->priority; 03024 set_ext_pri(chan, "e", 0); 03025 return 0; 03026 }
| 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 |
Definition at line 8920 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().
08921 { 08922 struct ast_var_t *variables; 08923 const char *var, *val; 08924 int total = 0; 08925 08926 if (!chan) 08927 return 0; 08928 08929 ast_str_reset(*buf); 08930 08931 ast_channel_lock(chan); 08932 08933 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 08934 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 08935 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 08936 ) { 08937 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 08938 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 08939 break; 08940 } else 08941 total++; 08942 } else 08943 break; 08944 } 08945 08946 ast_channel_unlock(chan); 08947 08948 return total; 08949 }
| int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 9081 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and pbx_builtin_setvar_multiple().
Referenced by ast_compile_ael2(), and rpt_exec().
09082 { 09083 char *name, *value, *mydata; 09084 09085 if (ast_compat_app_set) { 09086 return pbx_builtin_setvar_multiple(chan, data); 09087 } 09088 09089 if (ast_strlen_zero(data)) { 09090 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 09091 return 0; 09092 } 09093 09094 mydata = ast_strdupa(data); 09095 name = strsep(&mydata, "="); 09096 value = mydata; 09097 if (strchr(name, ' ')) 09098 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 09099 09100 pbx_builtin_setvar_helper(chan, name, value); 09101 return(0); 09102 }
| void 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 9023 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_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, ast_channel::name, ast_channel::uniqueid, and ast_channel::varshead.
Referenced by __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_exec(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), aqm_exec(), array(), ast_bridge_call(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_rtp_set_vars(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_request_and_dial(), frame_set_var(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), 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(), pri_dchannel(), privacy_exec(), process_ast_dsp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), record_exec(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss7_start_call(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), transmit(), tryexec_exec(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
09024 { 09025 struct ast_var_t *newvariable; 09026 struct varshead *headp; 09027 const char *nametail = name; 09028 09029 if (name[strlen(name) - 1] == ')') { 09030 char *function = ast_strdupa(name); 09031 09032 ast_func_write(chan, function, value); 09033 return; 09034 } 09035 09036 if (chan) { 09037 ast_channel_lock(chan); 09038 headp = &chan->varshead; 09039 } else { 09040 ast_rwlock_wrlock(&globalslock); 09041 headp = &globals; 09042 } 09043 09044 /* For comparison purposes, we have to strip leading underscores */ 09045 if (*nametail == '_') { 09046 nametail++; 09047 if (*nametail == '_') 09048 nametail++; 09049 } 09050 09051 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 09052 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 09053 /* there is already such a variable, delete it */ 09054 AST_LIST_REMOVE_CURRENT(entries); 09055 ast_var_delete(newvariable); 09056 break; 09057 } 09058 } 09059 AST_LIST_TRAVERSE_SAFE_END; 09060 09061 if (value) { 09062 if (headp == &globals) 09063 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09064 newvariable = ast_var_assign(name, value); 09065 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09066 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 09067 "Channel: %s\r\n" 09068 "Variable: %s\r\n" 09069 "Value: %s\r\n" 09070 "Uniqueid: %s\r\n", 09071 chan ? chan->name : "none", name, value, 09072 chan ? chan->uniqueid : "none"); 09073 } 09074 09075 if (chan) 09076 ast_channel_unlock(chan); 09077 else 09078 ast_rwlock_unlock(&globalslock); 09079 }
| int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
| void * | 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 9104 of file pbx.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), and ast_channel::priority.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
09105 { 09106 char *data; 09107 int x; 09108 AST_DECLARE_APP_ARGS(args, 09109 AST_APP_ARG(pair)[24]; 09110 ); 09111 AST_DECLARE_APP_ARGS(pair, 09112 AST_APP_ARG(name); 09113 AST_APP_ARG(value); 09114 ); 09115 09116 if (ast_strlen_zero(vdata)) { 09117 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 09118 return 0; 09119 } 09120 09121 data = ast_strdupa(vdata); 09122 AST_STANDARD_APP_ARGS(args, data); 09123 09124 for (x = 0; x < args.argc; x++) { 09125 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 09126 if (pair.argc == 2) { 09127 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 09128 if (strchr(pair.name, ' ')) 09129 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); 09130 } else if (!chan) { 09131 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 09132 } else { 09133 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 09134 } 09135 } 09136 09137 return 0; 09138 }
| 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 9192 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().
09193 { 09194 int res; 09195 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 09196 return 0; 09197 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 09198 return res; 09199 } else { /* Strings are true */ 09200 return 1; 09201 } 09202 }
| int pbx_exec | ( | struct ast_channel * | c, | |
| struct ast_app * | app, | |||
| void * | data | |||
| ) |
Execute an application.
| c | channel to execute on | |
| app | which app to execute | |
| data | the data passed into the app |
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.
| 0 | success | |
| -1 | failure |
| c | Channel | |
| app | Application | |
| data | Data for execution |
Definition at line 1322 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01325 { 01326 int res; 01327 struct ast_module_user *u = NULL; 01328 const char *saved_c_appl; 01329 const char *saved_c_data; 01330 01331 if (c->cdr && !ast_check_hangup(c)) 01332 ast_cdr_setapp(c->cdr, app->name, data); 01333 01334 /* save channel values */ 01335 saved_c_appl= c->appl; 01336 saved_c_data= c->data; 01337 01338 c->appl = app->name; 01339 c->data = data; 01340 if (app->module) 01341 u = __ast_module_user_add(app->module, c); 01342 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01343 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01344 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01345 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01346 app->name, (char *) data); 01347 } 01348 res = app->execute(c, S_OR((char *) data, "")); 01349 if (app->module && u) 01350 __ast_module_user_remove(app->module, u); 01351 /* restore channel values */ 01352 c->appl = saved_c_appl; 01353 c->data = saved_c_data; 01354 return res; 01355 }
| struct ast_exten* pbx_find_extension | ( | struct ast_channel * | chan, | |
| struct ast_context * | bypass, | |||
| struct pbx_find_info * | q, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| enum ext_match_t | action | |||
| ) | [read] |
Definition at line 2469 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strlen_zero(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_switch::canmatch, scoreboard::canmatch_exten, contexts_table, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_sw::name, ast_context::name, fake_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, 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(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().
02473 { 02474 int x, res; 02475 struct ast_context *tmp = NULL; 02476 struct ast_exten *e = NULL, *eroot = NULL; 02477 struct ast_include *i = NULL; 02478 struct ast_sw *sw = NULL; 02479 struct ast_exten pattern = {NULL, }; 02480 struct scoreboard score = {0, }; 02481 struct ast_str *tmpdata = NULL; 02482 02483 pattern.label = label; 02484 pattern.priority = priority; 02485 #ifdef NEED_DEBUG_HERE 02486 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02487 #endif 02488 02489 /* Initialize status if appropriate */ 02490 if (q->stacklen == 0) { 02491 q->status = STATUS_NO_CONTEXT; 02492 q->swo = NULL; 02493 q->data = NULL; 02494 q->foundcontext = NULL; 02495 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02496 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02497 return NULL; 02498 } 02499 02500 /* Check first to see if we've already been checked */ 02501 for (x = 0; x < q->stacklen; x++) { 02502 if (!strcasecmp(q->incstack[x], context)) 02503 return NULL; 02504 } 02505 02506 if (bypass) { /* bypass means we only look there */ 02507 tmp = bypass; 02508 } else { /* look in contexts */ 02509 struct fake_context item; 02510 02511 ast_copy_string(item.name, context, sizeof(item.name)); 02512 02513 tmp = ast_hashtab_lookup(contexts_table, &item); 02514 #ifdef NOTNOW 02515 tmp = NULL; 02516 while ((tmp = ast_walk_contexts(tmp)) ) { 02517 if (!strcmp(tmp->name, context)) { 02518 break; 02519 } 02520 } 02521 #endif 02522 if (!tmp) { 02523 return NULL; 02524 } 02525 } 02526 02527 if (q->status < STATUS_NO_EXTENSION) 02528 q->status = STATUS_NO_EXTENSION; 02529 02530 /* Do a search for matching extension */ 02531 02532 eroot = NULL; 02533 score.total_specificity = 0; 02534 score.exten = 0; 02535 score.total_length = 0; 02536 if (!tmp->pattern_tree && tmp->root_table) { 02537 create_match_char_tree(tmp); 02538 #ifdef NEED_DEBUG 02539 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02540 log_match_char_tree(tmp->pattern_tree," "); 02541 #endif 02542 } 02543 #ifdef NEED_DEBUG 02544 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02545 log_match_char_tree(tmp->pattern_tree, ":: "); 02546 #endif 02547 02548 do { 02549 if (!ast_strlen_zero(overrideswitch)) { 02550 char *osw = ast_strdupa(overrideswitch), *name; 02551 struct ast_switch *asw; 02552 ast_switch_f *aswf = NULL; 02553 char *datap; 02554 int eval = 0; 02555 02556 name = strsep(&osw, "/"); 02557 asw = pbx_findswitch(name); 02558 02559 if (!asw) { 02560 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02561 break; 02562 } 02563 02564 if (osw && strchr(osw, '$')) { 02565 eval = 1; 02566 } 02567 02568 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02569 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02570 break; 02571 } else if (eval) { 02572 /* Substitute variables now */ 02573 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02574 datap = ast_str_buffer(tmpdata); 02575 } else { 02576 datap = osw; 02577 } 02578 02579 /* equivalent of extension_match_core() at the switch level */ 02580 if (action == E_CANMATCH) 02581 aswf = asw->canmatch; 02582 else if (action == E_MATCHMORE) 02583 aswf = asw->matchmore; 02584 else /* action == E_MATCH */ 02585 aswf = asw->exists; 02586 if (!aswf) { 02587 res = 0; 02588 } else { 02589 if (chan) { 02590 ast_autoservice_start(chan); 02591 } 02592 res = aswf(chan, context, exten, priority, callerid, datap); 02593 if (chan) { 02594 ast_autoservice_stop(chan); 02595 } 02596 } 02597 if (res) { /* Got a match */ 02598 q->swo = asw; 02599 q->data = datap; 02600 q->foundcontext = context; 02601 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02602 return NULL; 02603 } 02604 } 02605 } while (0); 02606 02607 if (extenpatternmatchnew) { 02608 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02609 eroot = score.exten; 02610 02611 if (score.last_char == '!' && action == E_MATCHMORE) { 02612 /* We match an extension ending in '!'. 02613 * The decision in this case is final and is NULL (no match). 02614 */ 02615 #ifdef NEED_DEBUG_HERE 02616 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02617 #endif 02618 return NULL; 02619 } 02620 02621 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02622 q->status = STATUS_SUCCESS; 02623 #ifdef NEED_DEBUG_HERE 02624 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02625 #endif 02626 return score.canmatch_exten; 02627 } 02628 02629 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02630 if (score.node) { 02631 struct ast_exten *z = trie_find_next_match(score.node); 02632 if (z) { 02633 #ifdef NEED_DEBUG_HERE 02634 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02635 #endif 02636 } else { 02637 if (score.canmatch_exten) { 02638 #ifdef NEED_DEBUG_HERE 02639 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02640 #endif 02641 return score.canmatch_exten; 02642 } else { 02643 #ifdef NEED_DEBUG_HERE 02644 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02645 #endif 02646 } 02647 } 02648 return z; 02649 } 02650 #ifdef NEED_DEBUG_HERE 02651 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02652 #endif 02653 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02654 } 02655 02656 if (eroot) { 02657 /* found entry, now look for the right priority */ 02658 if (q->status < STATUS_NO_PRIORITY) 02659 q->status = STATUS_NO_PRIORITY; 02660 e = NULL; 02661 if (action == E_FINDLABEL && label ) { 02662 if (q->status < STATUS_NO_LABEL) 02663 q->status = STATUS_NO_LABEL; 02664 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02665 } else { 02666 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02667 } 02668 if (e) { /* found a valid match */ 02669 q->status = STATUS_SUCCESS; 02670 q->foundcontext = context; 02671 #ifdef NEED_DEBUG_HERE 02672 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02673 #endif 02674 return e; 02675 } 02676 } 02677 } else { /* the old/current default exten pattern match algorithm */ 02678 02679 /* scan the list trying to match extension and CID */ 02680 eroot = NULL; 02681 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02682 int match = extension_match_core(eroot->exten, exten, action); 02683 /* 0 on fail, 1 on match, 2 on earlymatch */ 02684 02685 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02686 continue; /* keep trying */ 02687 if (match == 2 && action == E_MATCHMORE) { 02688 /* We match an extension ending in '!'. 02689 * The decision in this case is final and is NULL (no match). 02690 */ 02691 return NULL; 02692 } 02693 /* found entry, now look for the right priority */ 02694 if (q->status < STATUS_NO_PRIORITY) 02695 q->status = STATUS_NO_PRIORITY; 02696 e = NULL; 02697 if (action == E_FINDLABEL && label ) { 02698 if (q->status < STATUS_NO_LABEL) 02699 q->status = STATUS_NO_LABEL; 02700 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02701 } else { 02702 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02703 } 02704 #ifdef NOTNOW 02705 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 02706 /* Match label or priority */ 02707 if (action == E_FINDLABEL) { 02708 if (q->status < STATUS_NO_LABEL) 02709 q->status = STATUS_NO_LABEL; 02710 if (label && e->label && !strcmp(label, e->label)) 02711 break; /* found it */ 02712 } else if (e->priority == priority) { 02713 break; /* found it */ 02714 } /* else keep searching */ 02715 } 02716 #endif 02717 if (e) { /* found a valid match */ 02718 q->status = STATUS_SUCCESS; 02719 q->foundcontext = context; 02720 return e; 02721 } 02722 } 02723 } 02724 02725 /* Check alternative switches */ 02726 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02727 struct ast_switch *asw = pbx_findswitch(sw->name); 02728 ast_switch_f *aswf = NULL; 02729 char *datap; 02730 02731 if (!asw) { 02732 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02733 continue; 02734 } 02735 02736 /* Substitute variables now */ 02737 if (sw->eval) { 02738 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02739 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02740 continue; 02741 } 02742 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02743 } 02744 02745 /* equivalent of extension_match_core() at the switch level */ 02746 if (action == E_CANMATCH) 02747 aswf = asw->canmatch; 02748 else if (action == E_MATCHMORE) 02749 aswf = asw->matchmore; 02750 else /* action == E_MATCH */ 02751 aswf = asw->exists; 02752 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02753 if (!aswf) 02754 res = 0; 02755 else { 02756 if (chan) 02757 ast_autoservice_start(chan); 02758 res = aswf(chan, context, exten, priority, callerid, datap); 02759 if (chan) 02760 ast_autoservice_stop(chan); 02761 } 02762 if (res) { /* Got a match */ 02763 q->swo = asw; 02764 q->data = datap; 02765 q->foundcontext = context; 02766 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02767 return NULL; 02768 } 02769 } 02770 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02771 /* Now try any includes we have in this context */ 02772 for (i = tmp->includes; i; i = i->next) { 02773 if (include_valid(i)) { 02774 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02775 #ifdef NEED_DEBUG_HERE 02776 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02777 #endif 02778 return e; 02779 } 02780 if (q->swo) 02781 return NULL; 02782 } 02783 } 02784 return NULL; 02785 }
| struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Look up an application.
| app | name of the app |
This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in.
Definition at line 1363 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01364 { 01365 struct ast_app *tmp; 01366 01367 AST_RWLIST_RDLOCK(&apps); 01368 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01369 if (!strcasecmp(tmp->name, app)) 01370 break; 01371 } 01372 AST_RWLIST_UNLOCK(&apps); 01373 01374 return tmp; 01375 }
| void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
| const char * | var, | |||
| char ** | ret, | |||
| char * | workspace, | |||
| int | workspacelen, | |||
| struct varshead * | headp | |||
| ) |
Retrieve the value of a builtin variable or variable from the channel variable stack.
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 2867 of file pbx.c.
References ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_eid_default, ast_eid_to_str(), ast_get_hint(), AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_channel::name, parse_variable_name(), ast_channel::priority, s, substring(), ast_channel::uniqueid, and ast_channel::varshead.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02868 { 02869 const char not_found = '\0'; 02870 char *tmpvar; 02871 const char *s; /* the result */ 02872 int offset, length; 02873 int i, need_substring; 02874 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02875 02876 if (c) { 02877 ast_channel_lock(c); 02878 places[0] = &c->varshead; 02879 } 02880 /* 02881 * Make a copy of var because parse_variable_name() modifies the string. 02882 * Then if called directly, we might need to run substring() on the result; 02883 * remember this for later in 'need_substring', 'offset' and 'length' 02884 */ 02885 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 02886 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 02887 02888 /* 02889 * Look first into predefined variables, then into variable lists. 02890 * Variable 's' points to the result, according to the following rules: 02891 * s == ¬_found (set at the beginning) means that we did not find a 02892 * matching variable and need to look into more places. 02893 * If s != ¬_found, s is a valid result string as follows: 02894 * s = NULL if the variable does not have a value; 02895 * you typically do this when looking for an unset predefined variable. 02896 * s = workspace if the result has been assembled there; 02897 * typically done when the result is built e.g. with an snprintf(), 02898 * so we don't need to do an additional copy. 02899 * s != workspace in case we have a string, that needs to be copied 02900 * (the ast_copy_string is done once for all at the end). 02901 * Typically done when the result is already available in some string. 02902 */ 02903 s = ¬_found; /* default value */ 02904 if (c) { /* This group requires a valid channel */ 02905 /* Names with common parts are looked up a piece at a time using strncmp. */ 02906 if (!strncmp(var, "CALL", 4)) { 02907 if (!strncmp(var + 4, "ING", 3)) { 02908 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 02909 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 02910 s = workspace; 02911 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 02912 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 02913 s = workspace; 02914 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 02915 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 02916 s = workspace; 02917 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 02918 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 02919 s = workspace; 02920 } 02921 } 02922 } else if (!strcmp(var, "HINT")) { 02923 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 02924 } else if (!strcmp(var, "HINTNAME")) { 02925 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 02926 } else if (!strcmp(var, "EXTEN")) { 02927 s = c->exten; 02928 } else if (!strcmp(var, "CONTEXT")) { 02929 s = c->context; 02930 } else if (!strcmp(var, "PRIORITY")) { 02931 snprintf(workspace, workspacelen, "%d", c->priority); 02932 s = workspace; 02933 } else if (!strcmp(var, "CHANNEL")) { 02934 s = c->name; 02935 } else if (!strcmp(var, "UNIQUEID")) { 02936 s = c->uniqueid; 02937 } else if (!strcmp(var, "HANGUPCAUSE")) { 02938 snprintf(workspace, workspacelen, "%d", c->hangupcause); 02939 s = workspace; 02940 } 02941 } 02942 if (s == ¬_found) { /* look for more */ 02943 if (!strcmp(var, "EPOCH")) { 02944 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 02945 s = workspace; 02946 } else if (!strcmp(var, "SYSTEMNAME")) { 02947 s = ast_config_AST_SYSTEM_NAME; 02948 } else if (!strcmp(var, "ENTITYID")) { 02949 ast_eid_to_str(workspace, workspacelen, &ast_eid_default); 02950 s = workspace; 02951 } 02952 } 02953 /* if not found, look into chanvars or global vars */ 02954 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 02955 struct ast_var_t *variables; 02956 if (!places[i]) 02957 continue; 02958 if (places[i] == &globals) 02959 ast_rwlock_rdlock(&globalslock); 02960 AST_LIST_TRAVERSE(places[i], variables, entries) { 02961 if (!strcasecmp(ast_var_name(variables), var)) { 02962 s = ast_var_value(variables); 02963 break; 02964 } 02965 } 02966 if (places[i] == &globals) 02967 ast_rwlock_unlock(&globalslock); 02968 } 02969 if (s == ¬_found || s == NULL) 02970 *ret = NULL; 02971 else { 02972 if (s != workspace) 02973 ast_copy_string(workspace, s, workspacelen); 02974 *ret = workspace; 02975 if (need_substring) 02976 *ret = substring(*ret, offset, length, workspace, workspacelen); 02977 } 02978 02979 if (c) 02980 ast_channel_unlock(c); 02981 }
| 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 4611 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
04612 { 04613 int oldval = autofallthrough; 04614 autofallthrough = newval; 04615 return oldval; 04616 }
| 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 4618 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
04619 { 04620 int oldval = extenpatternmatchnew; 04621 extenpatternmatchnew = newval; 04622 return oldval; 04623 }
| 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 4625 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
04626 { 04627 if (overrideswitch) { 04628 ast_free(overrideswitch); 04629 } 04630 if (!ast_strlen_zero(newval)) { 04631 overrideswitch = ast_strdup(newval); 04632 } else { 04633 overrideswitch = NULL; 04634 } 04635 }
| void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3598 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by _macro_exec(), acf_import(), add_extensions(), ast_add_extension2_lockopt(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), function_eval(), function_fieldqty(), get_mapping_weight(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_curl(), realtime_exec(), realtime_multi_curl(), require_curl(), rotate_file(), rpt_do_lstats(), rpt_exec(), sendmail(), sendpage(), sqlite3_log(), store_curl(), substituted(), try_calling(), tryexec_exec(), update2_curl(), and update_curl().
03599 { 03600 size_t used; 03601 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 03602 }
| 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 3403 of file pbx.c.
References ast_channel_alloc, ast_channel_free(), ast_copy_string(), ast_debug, 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 ast_str_substitute_variables(), pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
03404 { 03405 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03406 char *cp4; 03407 const char *tmp, *whereweare, *orig_cp2 = cp2; 03408 int length, offset, offset2, isfunction; 03409 char *workspace = NULL; 03410 char *ltmp = NULL, *var = NULL; 03411 char *nextvar, *nextexp, *nextthing; 03412 char *vars, *vare; 03413 int pos, brackets, needsub, len; 03414 03415 *cp2 = 0; /* just in case nothing ends up there */ 03416 whereweare=tmp=cp1; 03417 while (!ast_strlen_zero(whereweare) && count) { 03418 /* Assume we're copying the whole remaining string */ 03419 pos = strlen(whereweare); 03420 nextvar = NULL; 03421 nextexp = NULL; 03422 nextthing = strchr(whereweare, '$'); 03423 if (nextthing) { 03424 switch (nextthing[1]) { 03425 case '{': 03426 nextvar = nextthing; 03427 pos = nextvar - whereweare; 03428 break; 03429 case '[': 03430 nextexp = nextthing; 03431 pos = nextexp - whereweare; 03432 break; 03433 default: 03434 pos = 1; 03435 } 03436 } 03437 03438 if (pos) { 03439 /* Can't copy more than 'count' bytes */ 03440 if (pos > count) 03441 pos = count; 03442 03443 /* Copy that many bytes */ 03444 memcpy(cp2, whereweare, pos); 03445 03446 count -= pos; 03447 cp2 += pos; 03448 whereweare += pos; 03449 *cp2 = 0; 03450 } 03451 03452 if (nextvar) { 03453 /* We have a variable. Find the start and end, and determine 03454 if we are going to have to recursively call ourselves on the 03455 contents */ 03456 vars = vare = nextvar + 2; 03457 brackets = 1; 03458 needsub = 0; 03459 03460 /* Find the end of it */ 03461 while (brackets && *vare) { 03462 if ((vare[0] == '$') && (vare[1] == '{')) { 03463 needsub++; 03464 } else if (vare[0] == '{') { 03465 brackets++; 03466 } else if (vare[0] == '}') { 03467 brackets--; 03468 } else if ((vare[0] == '$') && (vare[1] == '[')) 03469 needsub++; 03470 vare++; 03471 } 03472 if (brackets) 03473 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03474 len = vare - vars - 1; 03475 03476 /* Skip totally over variable string */ 03477 whereweare += (len + 3); 03478 03479 if (!var) 03480 var = alloca(VAR_BUF_SIZE); 03481 03482 /* Store variable name (and truncate) */ 03483 ast_copy_string(var, vars, len + 1); 03484 03485 /* Substitute if necessary */ 03486 if (needsub) { 03487 size_t used; 03488 if (!ltmp) 03489 ltmp = alloca(VAR_BUF_SIZE); 03490 03491 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03492 vars = ltmp; 03493 } else { 03494 vars = var; 03495 } 03496 03497 if (!workspace) 03498 workspace = alloca(VAR_BUF_SIZE); 03499 03500 workspace[0] = '\0'; 03501 03502 parse_variable_name(vars, &offset, &offset2, &isfunction); 03503 if (isfunction) { 03504 /* Evaluate function */ 03505 if (c || !headp) 03506 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03507 else { 03508 struct varshead old; 03509 struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 03510 if (bogus) { 03511 memcpy(&old, &bogus->varshead, sizeof(old)); 03512 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03513 cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03514 /* Don't deallocate the varshead that was passed in */ 03515 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03516 ast_channel_free(bogus); 03517 } else 03518 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03519 } 03520 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03521 } else { 03522 /* Retrieve variable value */ 03523 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03524 } 03525 if (cp4) { 03526 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03527 03528 length = strlen(cp4); 03529 if (length > count) 03530 length = count; 03531 memcpy(cp2, cp4, length); 03532 count -= length; 03533 cp2 += length; 03534 *cp2 = 0; 03535 } 03536 } else if (nextexp) { 03537 /* We have an expression. Find the start and end, and determine 03538 if we are going to have to recursively call ourselves on the 03539 contents */ 03540 vars = vare = nextexp + 2; 03541 brackets = 1; 03542 needsub = 0; 03543 03544 /* Find the end of it */ 03545 while (brackets && *vare) { 03546 if ((vare[0] == '$') && (vare[1] == '[')) { 03547 needsub++; 03548 brackets++; 03549 vare++; 03550 } else if (vare[0] == '[') { 03551 brackets++; 03552 } else if (vare[0] == ']') { 03553 brackets--; 03554 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03555 needsub++; 03556 vare++; 03557 } 03558 vare++; 03559 } 03560 if (brackets) 03561 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03562 len = vare - vars - 1; 03563 03564 /* Skip totally over expression */ 03565 whereweare += (len + 3); 03566 03567 if (!var) 03568 var = alloca(VAR_BUF_SIZE); 03569 03570 /* Store variable name (and truncate) */ 03571 ast_copy_string(var, vars, len + 1); 03572 03573 /* Substitute if necessary */ 03574 if (needsub) { 03575 size_t used; 03576 if (!ltmp) 03577 ltmp = alloca(VAR_BUF_SIZE); 03578 03579 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03580 vars = ltmp; 03581 } else { 03582 vars = var; 03583 } 03584 03585 length = ast_expr(vars, cp2, count, c); 03586 03587 if (length) { 03588 ast_debug(1, "Expression result is '%s'\n", cp2); 03589 count -= length; 03590 cp2 += length; 03591 *cp2 = 0; 03592 } 03593 } 03594 } 03595 *used = cp2 - orig_cp2; 03596 }
| void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3604 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by add_user_extension(), build_user_routes(), do_say(), dundi_lookup_local(), loopback_subst(), phoneprov_callback(), pp_each_extension_exec(), and pp_each_user_exec().
03605 { 03606 size_t used; 03607 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 03608 }
1.6.2