#include "asterisk/channel.h"
#include "asterisk/sched.h"
#include "asterisk/devicestate.h"
#include "asterisk/chanvars.h"
#include "asterisk/hashtab.h"
#include "asterisk/stringfields.h"
#include "asterisk/xmldoc.h"
#include "asterisk/format.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_GOTO_FAILED -3 |
| #define | AST_PBX_KEEP 0 |
| #define | AST_PBX_MAX_STACK 128 |
| #define | AST_PBX_REPLACE 1 |
| #define | PRIORITY_HINT -1 |
| #define | STATUS_NO_CONTEXT 1 |
| #define | STATUS_NO_EXTENSION 2 |
| #define | STATUS_NO_LABEL 4 |
| #define | STATUS_NO_PRIORITY 3 |
| #define | STATUS_SUCCESS 5 |
| #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 void(* | ast_state_cb_destroy_type )(int id, void *data) |
| Typedef for devicestate and hint callback removal indication callback. | |
| typedef int(* | ast_state_cb_type )(const char *context, const char *exten, enum ast_extension_states state, void *data) |
| Typedef for devicestate and hint callbacks. | |
| typedef int( | ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| All switch functions have the same interface, so define a type for them. | |
Enumerations | |
| enum | ast_extension_states { AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0, AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4 } |
| Extension states. More... | |
| enum | ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 } |
| The result codes when starting the PBX on a channel with ast_pbx_start. More... | |
| enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22, E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
| int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
| Register a custom function. | |
| int | ast_active_calls (void) |
| Retrieve the number of active calls. | |
| int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add and extension to an extension context. | |
| int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add an extension to an extension context, this time with an ast_context *. | |
| int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| Set the channel to next execute the specified dialplan location. | |
| int | ast_async_goto_by_name (const char *chan, const char *context, const char *exten, int priority) |
| Set the channel to next execute the specified dialplan location. | |
| int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_build_timing (struct ast_timing *i, const char *info) |
| Construct a timing bitmap, for use in time-based conditionals. | |
| int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks for a valid matching extension. | |
| int | ast_check_timing (const struct ast_timing *i) |
| Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified. | |
| int | ast_check_timing2 (const struct ast_timing *i, const struct timeval tv) |
| Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified. | |
| char * | ast_complete_applications (const char *line, const char *word, int state) |
| Command completion for the list of installed applications. | |
| int | ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| Add an ignorepat. | |
| int | ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
| Add a switch. | |
| int | ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar) |
| Adds a switch (first param is a ast_context). | |
| void | ast_context_destroy (struct ast_context *con, const char *registrar) |
| Destroy a context (matches the specified context (or ANY context if NULL). | |
| struct ast_context * | ast_context_find (const char *name) |
| Find a context. | |
| struct ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
| Register a new context or find an existing one. | |
| int | ast_context_lockmacro (const char *macrocontext) |
| locks the macrolock in the given given context | |
| int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
| Remove a context include. | |
| int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Removes an include by an ast_context structure. | |
| int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
| Remove a switch. | |
| int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
| This function locks given context, removes switch, unlock context and return. | |
| int | ast_context_unlockmacro (const char *macrocontext) |
| Unlocks the macrolock in the given context. | |
| int | ast_context_verify_includes (struct ast_context *con) |
| Verifies includes in an ast_contect structure. | |
| struct ast_custom_function * | ast_custom_function_find (const char *name) |
| int | ast_custom_function_unregister (struct ast_custom_function *acf) |
| Unregister a custom function. | |
| int | ast_destroy_timing (struct ast_timing *i) |
| Deallocates memory structures associated with a timing bitmap. | |
| enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
| Map devstate to an extension state. | |
| int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Determine whether an extension exists. | |
| int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_extension_close (const char *pattern, const char *data, int needmore) |
| int | ast_extension_cmp (const char *a, const char *b) |
| Determine if one extension should match before another. | |
| int | ast_extension_match (const char *pattern, const char *extension) |
| Determine if a given extension matches a given pattern (in NXX format). | |
| int | ast_extension_patmatch (const char *pattern, const char *data) |
| int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
| Uses hint and devicestate callback to get the state of an extension. | |
| const char * | ast_extension_state2str (int extension_state) |
| Return string representation of the state of an extension. | |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data) |
| Registers a state change callback. | |
| int | ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data) |
| Registers a state change callback with destructor. | |
| int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
| Deletes a registered state change callback by ID. | |
| int | ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
| executes a read operation on a function | |
| int | ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen) |
| executes a read operation on a function | |
| int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
| executes a write operation on a function | |
| int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
| If an extension hint exists, return non-zero. | |
| int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_ignore_pattern (const char *context, const char *pattern) |
| Checks to see if a number should be ignored. | |
| int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
| void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
| Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
| int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_pbx_outgoing_app (const char *type, struct ast_format_cap *cap, const char *addr, 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, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
| enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
| Execute the PBX in the current thread. | |
| enum ast_pbx_result | ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args) |
| Execute the PBX in the current thread. | |
| enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
| Create a new thread and start the PBX. | |
| int | ast_processed_calls (void) |
| Retrieve the total number of calls processed through the PBX since last restart. | |
| int | ast_rdlock_context (struct ast_context *con) |
| Read locks a given context. | |
| int | ast_rdlock_contexts (void) |
| Read locks the context list. | |
| int | ast_register_switch (struct ast_switch *sw) |
| Register an alternative dialplan switch. | |
| int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn) |
| Launch a new extension (i.e. new stack). | |
| int | ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten) |
| If an extension hint exists, return non-zero. | |
| int | ast_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts (void) |
| Unlocks contexts. | |
| void | ast_unregister_switch (struct ast_switch *sw) |
| Unregister an alternative switch. | |
| int | ast_wrlock_context (struct ast_context *con) |
| Write locks a given context. | |
| int | ast_wrlock_contexts (void) |
| Write locks the context list. | |
| void | pbx_builtin_clear_globals (void) |
| const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
| Return a pointer to the value of the corresponding channel variable. | |
| void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, without removing any previously set value. | |
| int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *data) |
| int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
| Create a human-readable string, specifying all variables and their corresponding values. | |
| int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
| Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
| int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
| int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *data) |
| Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
| int | pbx_checkcondition (const char *condition) |
| Evaluate a condition. | |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
| Execute an application. | |
| 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 dynamic string buffers | |
| const char * | ast_str_retrieve_variable (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var) |
| void | ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ) |
| void | ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used) |
| void | ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ) |
Walking functions ... | |
| struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
| struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
| struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| struct ast_context * | ast_walk_contexts (struct ast_context *con) |
| struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
Substitution routines, using static string buffers | |
| void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
| void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used) |
| void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
Definition in file pbx.h.
| #define ast_custom_function_register | ( | acf | ) | __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function.
Definition at line 1144 of file pbx.h.
Referenced by load_module(), and reload().
| #define AST_MAX_APP 32 |
Max length of an application
Definition at line 39 of file pbx.h.
Referenced by destroy_station(), handle_show_function(), print_app_docs(), and sla_build_station().
| #define AST_PBX_ERROR 1 |
| #define AST_PBX_GOTO_FAILED -3 |
| #define AST_PBX_HANGUP -1 |
| #define AST_PBX_INCOMPLETE 12 |
Return to PBX matching, allowing more digits for the extension
Definition at line 50 of file pbx.h.
Referenced by __ast_pbx_run(), dial_exec_full(), pbx_builtin_incomplete(), and retrydial_exec().
| #define PRIORITY_HINT -1 |
Special Priority for a hint
Definition at line 53 of file pbx.h.
Referenced by add_extensions(), add_priority(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_space(), destroy_station(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), lua_register_hints(), manager_show_dialplan_helper(), park_add_hints(), pbx_load_config(), print_ext(), and sla_build_station().
| typedef void(* ast_state_cb_destroy_type)(int id, void *data) |
| typedef int(* ast_state_cb_type)(const char *context, const char *exten, enum ast_extension_states state, void *data) |
| typedef int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| enum ast_extension_states |
Extension states.
| AST_EXTENSION_REMOVED | Extension removed |
| AST_EXTENSION_DEACTIVATED | Extension hint removed |
| AST_EXTENSION_NOT_INUSE | No device INUSE or BUSY |
| AST_EXTENSION_INUSE | One or more devices INUSE |
| AST_EXTENSION_BUSY | All devices BUSY |
| AST_EXTENSION_UNAVAILABLE | All devices UNAVAILABLE/UNREGISTERED |
| AST_EXTENSION_RINGING | All devices RINGING |
| AST_EXTENSION_ONHOLD | All devices ONHOLD |
Definition at line 60 of file pbx.h.
00060 { 00061 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */ 00062 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */ 00063 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */ 00064 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */ 00065 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ 00066 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ 00067 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ 00068 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ 00069 };
| enum ast_pbx_result |
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition at line 289 of file pbx.h.
00289 { 00290 AST_PBX_SUCCESS = 0, 00291 AST_PBX_FAILED = -1, 00292 AST_PBX_CALL_LIMIT = -2, 00293 };
| enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows.
| 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 1213 of file pbx.h.
01213 { 01214 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01215 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01216 E_MATCH = 0x02, /* extension is an exact match */ 01217 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01218 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01219 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01220 };
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 3715 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by ast_msg_init(), and load_pbx().
03716 { 03717 struct ast_custom_function *cur; 03718 char tmps[80]; 03719 03720 if (!acf) { 03721 return -1; 03722 } 03723 03724 acf->mod = mod; 03725 #ifdef AST_XML_DOCS 03726 acf->docsrc = AST_STATIC_DOC; 03727 #endif 03728 03729 if (acf_retrieve_docs(acf)) { 03730 return -1; 03731 } 03732 03733 AST_RWLIST_WRLOCK(&acf_root); 03734 03735 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03736 if (!strcmp(acf->name, cur->name)) { 03737 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03738 AST_RWLIST_UNLOCK(&acf_root); 03739 return -1; 03740 } 03741 } 03742 03743 /* Store in alphabetical order */ 03744 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03745 if (strcasecmp(acf->name, cur->name) < 0) { 03746 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03747 break; 03748 } 03749 } 03750 AST_RWLIST_TRAVERSE_SAFE_END; 03751 03752 if (!cur) { 03753 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03754 } 03755 03756 AST_RWLIST_UNLOCK(&acf_root); 03757 03758 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03759 03760 return 0; 03761 }
| int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5546 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05547 { 05548 return countcalls; 05549 }
| 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 8271 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().
08274 { 08275 int ret = -1; 08276 struct ast_context *c; 08277 08278 c = find_context_locked(context); 08279 if (c) { 08280 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08281 application, data, datad, registrar); 08282 ast_unlock_contexts(); 08283 } 08284 08285 return ret; 08286 }
| int ast_add_extension2 | ( | struct ast_context * | con, | |
| int | replace, | |||
| const char * | extension, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| const char * | application, | |||
| void * | data, | |||
| void(*)(void *) | datad, | |||
| const char * | registrar | |||
| ) |
Add an extension to an extension context, this time with an ast_context *.
We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.
The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.
EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set
Definition at line 8617 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), lua_register_hints(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
08621 { 08622 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08623 application, data, datad, registrar, 1); 08624 }
| 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 8311 of file pbx.c.
References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_accountcode(), ast_channel_alloc, ast_channel_linkedid(), ast_channel_lock, ast_channel_masquerade(), ast_channel_name(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_format_copy(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmf(), fax_detect_framehook(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().
08312 { 08313 int res = 0; 08314 struct ast_channel *tmpchan; 08315 struct { 08316 char *accountcode; 08317 char *exten; 08318 char *context; 08319 char *linkedid; 08320 char *name; 08321 struct ast_cdr *cdr; 08322 int amaflags; 08323 int state; 08324 struct ast_format readformat; 08325 struct ast_format writeformat; 08326 } tmpvars = { 0, }; 08327 08328 ast_channel_lock(chan); 08329 if (chan->pbx) { /* This channel is currently in the PBX */ 08330 ast_explicit_goto(chan, context, exten, priority + 1); 08331 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08332 ast_channel_unlock(chan); 08333 return res; 08334 } 08335 08336 /* In order to do it when the channel doesn't really exist within 08337 * the PBX, we have to make a new channel, masquerade, and start the PBX 08338 * at the new location */ 08339 tmpvars.accountcode = ast_strdupa(ast_channel_accountcode(chan)); 08340 tmpvars.exten = ast_strdupa(chan->exten); 08341 tmpvars.context = ast_strdupa(chan->context); 08342 tmpvars.linkedid = ast_strdupa(ast_channel_linkedid(chan)); 08343 tmpvars.name = ast_strdupa(ast_channel_name(chan)); 08344 tmpvars.amaflags = chan->amaflags; 08345 tmpvars.state = chan->_state; 08346 ast_format_copy(&tmpvars.writeformat, &chan->writeformat); 08347 ast_format_copy(&tmpvars.readformat, &chan->readformat); 08348 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08349 08350 ast_channel_unlock(chan); 08351 08352 /* Do not hold any channel locks while calling channel_alloc() since the function 08353 * locks the channel container when linking the new channel in. */ 08354 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08355 ast_cdr_discard(tmpvars.cdr); 08356 return -1; 08357 } 08358 08359 /* copy the cdr info over */ 08360 if (tmpvars.cdr) { 08361 ast_cdr_discard(tmpchan->cdr); 08362 tmpchan->cdr = tmpvars.cdr; 08363 tmpvars.cdr = NULL; 08364 } 08365 08366 /* Make formats okay */ 08367 ast_format_copy(&tmpchan->readformat, &tmpvars.readformat); 08368 ast_format_copy(&tmpchan->writeformat, &tmpvars.writeformat); 08369 08370 /* Setup proper location. Never hold another channel lock while calling this function. */ 08371 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08372 08373 /* Masquerade into tmp channel */ 08374 if (ast_channel_masquerade(tmpchan, chan)) { 08375 /* Failed to set up the masquerade. It's probably chan_local 08376 * in the middle of optimizing itself out. Sad. :( */ 08377 ast_hangup(tmpchan); 08378 tmpchan = NULL; 08379 res = -1; 08380 } else { 08381 ast_do_masquerade(tmpchan); 08382 /* Start the PBX going on our stolen channel */ 08383 if (ast_pbx_start(tmpchan)) { 08384 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmpchan)); 08385 ast_hangup(tmpchan); 08386 res = -1; 08387 } 08388 } 08389 08390 return res; 08391 }
| 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 8393 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08394 { 08395 struct ast_channel *chan; 08396 int res = -1; 08397 08398 if ((chan = ast_channel_get_by_name(channame))) { 08399 res = ast_async_goto(chan, context, exten, priority); 08400 chan = ast_channel_unref(chan); 08401 } 08402 08403 return res; 08404 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 10708 of file pbx.c.
References __ast_goto_if_exists().
10709 { 10710 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10711 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 10773 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10774 { 10775 return pbx_parseable_goto(chan, goto_string, 1); 10776 }
| 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 7895 of file pbx.c.
References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, strsep(), and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07896 { 07897 char *info; 07898 int j, num_fields, last_sep = -1; 07899 07900 /* Check for empty just in case */ 07901 if (ast_strlen_zero(info_in)) { 07902 return 0; 07903 } 07904 07905 /* make a copy just in case we were passed a static string */ 07906 info = ast_strdupa(info_in); 07907 07908 /* count the number of fields in the timespec */ 07909 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07910 if (info[j] == ',') { 07911 last_sep = j; 07912 num_fields++; 07913 } 07914 } 07915 07916 /* save the timezone, if it is specified */ 07917 if (num_fields == 5) { 07918 i->timezone = ast_strdup(info + last_sep + 1); 07919 } else { 07920 i->timezone = NULL; 07921 } 07922 07923 /* Assume everything except time */ 07924 i->monthmask = 0xfff; /* 12 bits */ 07925 i->daymask = 0x7fffffffU; /* 31 bits */ 07926 i->dowmask = 0x7f; /* 7 bits */ 07927 /* on each call, use strsep() to move info to the next argument */ 07928 get_timerange(i, strsep(&info, "|,")); 07929 if (info) 07930 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07931 if (info) 07932 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07933 if (info) 07934 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07935 return 1; 07936 }
| 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 5041 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
05042 { 05043 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05044 }
| 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 7938 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07939 { 07940 return ast_check_timing2(i, ast_tvnow()); 07941 }
| int ast_check_timing2 | ( | const struct ast_timing * | i, | |
| const struct timeval | tv | |||
| ) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
| i | Pointer to an ast_timing structure. | |
| tv | Specified time |
| Returns | 1, if the time matches or 0, if the time falls outside of the specified range. |
Definition at line 7943 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by ast_check_timing(), and pbx_builtin_gotoiftime().
07944 { 07945 struct ast_tm tm; 07946 07947 ast_localtime(&tv, &tm, i->timezone); 07948 07949 /* If it's not the right month, return */ 07950 if (!(i->monthmask & (1 << tm.tm_mon))) 07951 return 0; 07952 07953 /* If it's not that time of the month.... */ 07954 /* Warning, tm_mday has range 1..31! */ 07955 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07956 return 0; 07957 07958 /* If it's not the right day of the week */ 07959 if (!(i->dowmask & (1 << tm.tm_wday))) 07960 return 0; 07961 07962 /* Sanity check the hour just to be safe */ 07963 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07964 ast_log(LOG_WARNING, "Insane time...\n"); 07965 return 0; 07966 } 07967 07968 /* Now the tough part, we calculate if it fits 07969 in the right time based on min/hour */ 07970 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)))) 07971 return 0; 07972 07973 /* If we got this far, then we're good */ 07974 return 1; 07975 }
| char* ast_complete_applications | ( | const char * | line, | |
| const char * | word, | |||
| int | state | |||
| ) |
Command completion for the list of installed applications.
This can be called from a CLI command completion function that wants to complete from the list of available applications.
Definition at line 10778 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::name.
Referenced by handle_orig(), and handle_show_application().
10779 { 10780 struct ast_app *app = NULL; 10781 int which = 0; 10782 char *ret = NULL; 10783 size_t wordlen = strlen(word); 10784 10785 AST_RWLIST_RDLOCK(&apps); 10786 AST_RWLIST_TRAVERSE(&apps, app, list) { 10787 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10788 ret = ast_strdup(app->name); 10789 break; 10790 } 10791 } 10792 AST_RWLIST_UNLOCK(&apps); 10793 10794 return ret; 10795 }
| int ast_context_add_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Add an ignorepat.
| context | which context to add the ignorpattern to | |
| ignorepat | ignorepattern to set up for the extension | |
| registrar | registrar of the ignore pattern |
| 0 | on success | |
| -1 | on failure |
Definition at line 8179 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08180 { 08181 int ret = -1; 08182 struct ast_context *c; 08183 08184 c = find_context_locked(context); 08185 if (c) { 08186 ret = ast_context_add_ignorepat2(c, value, registrar); 08187 ast_unlock_contexts(); 08188 } 08189 return ret; 08190 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8192 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().
08193 { 08194 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08195 int length; 08196 char *pattern; 08197 length = sizeof(struct ast_ignorepat); 08198 length += strlen(value) + 1; 08199 if (!(ignorepat = ast_calloc(1, length))) 08200 return -1; 08201 /* The cast to char * is because we need to write the initial value. 08202 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08203 * sees the cast as dereferencing a type-punned pointer and warns about 08204 * it. This is the workaround (we're telling gcc, yes, that's really 08205 * what we wanted to do). 08206 */ 08207 pattern = (char *) ignorepat->pattern; 08208 strcpy(pattern, value); 08209 ignorepat->next = NULL; 08210 ignorepat->registrar = registrar; 08211 ast_wrlock_context(con); 08212 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08213 ignorepatl = ignorepatc; 08214 if (!strcasecmp(ignorepatc->pattern, value)) { 08215 /* Already there */ 08216 ast_unlock_context(con); 08217 errno = EEXIST; 08218 return -1; 08219 } 08220 } 08221 if (ignorepatl) 08222 ignorepatl->next = ignorepat; 08223 else 08224 con->ignorepats = ignorepat; 08225 ast_unlock_context(con); 08226 return 0; 08227 08228 }
| int ast_context_add_include | ( | const char * | context, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| context | context to add include to | |
| include | new include to add | |
| registrar | who's registering it |
| 0 | on success | |
| -1 | on error |
Definition at line 7723 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07724 { 07725 int ret = -1; 07726 struct ast_context *c; 07727 07728 c = find_context_locked(context); 07729 if (c) { 07730 ret = ast_context_add_include2(c, include, registrar); 07731 ast_unlock_contexts(); 07732 } 07733 return ret; 07734 }
| int ast_context_add_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| con | context to add the include to | |
| include | include to add | |
| registrar | who registered the context |
| 0 | on success | |
| -1 | on failure |
Definition at line 7992 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().
07994 { 07995 struct ast_include *new_include; 07996 char *c; 07997 struct ast_include *i, *il = NULL; /* include, include_last */ 07998 int length; 07999 char *p; 08000 08001 length = sizeof(struct ast_include); 08002 length += 2 * (strlen(value) + 1); 08003 08004 /* allocate new include structure ... */ 08005 if (!(new_include = ast_calloc(1, length))) 08006 return -1; 08007 /* Fill in this structure. Use 'p' for assignments, as the fields 08008 * in the structure are 'const char *' 08009 */ 08010 p = new_include->stuff; 08011 new_include->name = p; 08012 strcpy(p, value); 08013 p += strlen(value) + 1; 08014 new_include->rname = p; 08015 strcpy(p, value); 08016 /* Strip off timing info, and process if it is there */ 08017 if ( (c = strchr(p, ',')) ) { 08018 *c++ = '\0'; 08019 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08020 } 08021 new_include->next = NULL; 08022 new_include->registrar = registrar; 08023 08024 ast_wrlock_context(con); 08025 08026 /* ... go to last include and check if context is already included too... */ 08027 for (i = con->includes; i; i = i->next) { 08028 if (!strcasecmp(i->name, new_include->name)) { 08029 ast_destroy_timing(&(new_include->timing)); 08030 ast_free(new_include); 08031 ast_unlock_context(con); 08032 errno = EEXIST; 08033 return -1; 08034 } 08035 il = i; 08036 } 08037 08038 /* ... include new context into context list, unlock, return */ 08039 if (il) 08040 il->next = new_include; 08041 else 08042 con->includes = new_include; 08043 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08044 08045 ast_unlock_context(con); 08046 08047 return 0; 08048 }
| int ast_context_add_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| int | eval, | |||
| const char * | registrar | |||
| ) |
Add a switch.
| context | context to which to add the switch | |
| sw | switch to add | |
| data | data to pass to switch | |
| eval | whether to evaluate variables when running switch | |
| registrar | whoever registered the switch |
| 0 | on success | |
| -1 | on failure |
Definition at line 8055 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08056 { 08057 int ret = -1; 08058 struct ast_context *c; 08059 08060 c = find_context_locked(context); 08061 if (c) { /* found, add switch to this context */ 08062 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08063 ast_unlock_contexts(); 08064 } 08065 return ret; 08066 }
| 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 8075 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().
08077 { 08078 struct ast_sw *new_sw; 08079 struct ast_sw *i; 08080 int length; 08081 char *p; 08082 08083 length = sizeof(struct ast_sw); 08084 length += strlen(value) + 1; 08085 if (data) 08086 length += strlen(data); 08087 length++; 08088 08089 /* allocate new sw structure ... */ 08090 if (!(new_sw = ast_calloc(1, length))) 08091 return -1; 08092 /* ... fill in this structure ... */ 08093 p = new_sw->stuff; 08094 new_sw->name = p; 08095 strcpy(new_sw->name, value); 08096 p += strlen(value) + 1; 08097 new_sw->data = p; 08098 if (data) { 08099 strcpy(new_sw->data, data); 08100 p += strlen(data) + 1; 08101 } else { 08102 strcpy(new_sw->data, ""); 08103 p++; 08104 } 08105 new_sw->eval = eval; 08106 new_sw->registrar = registrar; 08107 08108 /* ... try to lock this context ... */ 08109 ast_wrlock_context(con); 08110 08111 /* ... go to last sw and check if context is already swd too... */ 08112 AST_LIST_TRAVERSE(&con->alts, i, list) { 08113 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08114 ast_free(new_sw); 08115 ast_unlock_context(con); 08116 errno = EEXIST; 08117 return -1; 08118 } 08119 } 08120 08121 /* ... sw new context into context list, unlock, return */ 08122 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08123 08124 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08125 08126 ast_unlock_context(con); 08127 08128 return 0; 08129 }
| void ast_context_destroy | ( | struct ast_context * | con, | |
| const char * | registrar | |||
| ) |
Destroy a context (matches the specified context (or ANY context if NULL).
| con | context to destroy | |
| registrar | who registered it |
Definition at line 9438 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09439 { 09440 ast_wrlock_contexts(); 09441 __ast_context_destroy(contexts, contexts_table, con,registrar); 09442 ast_unlock_contexts(); 09443 }
| struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
| name | name of the context to find |
Definition at line 2777 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), handle_cli_dialplan_add_extension(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().
02778 { 02779 struct ast_context *tmp; 02780 struct fake_context item; 02781 02782 if (!name) { 02783 return NULL; 02784 } 02785 ast_rdlock_contexts(); 02786 if (contexts_table) { 02787 ast_copy_string(item.name, name, sizeof(item.name)); 02788 tmp = ast_hashtab_lookup(contexts_table, &item); 02789 } else { 02790 tmp = NULL; 02791 while ((tmp = ast_walk_contexts(tmp))) { 02792 if (!strcasecmp(name, tmp->name)) { 02793 break; 02794 } 02795 } 02796 } 02797 ast_unlock_contexts(); 02798 return tmp; 02799 }
| 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 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 7324 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), handle_cli_dialplan_add_extension(), load_module(), lua_register_hints(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
07325 { 07326 struct ast_context *tmp, **local_contexts; 07327 struct fake_context search; 07328 int length = sizeof(struct ast_context) + strlen(name) + 1; 07329 07330 if (!contexts_table) { 07331 /* Protect creation of contexts_table from reentrancy. */ 07332 ast_wrlock_contexts(); 07333 if (!contexts_table) { 07334 contexts_table = ast_hashtab_create(17, 07335 ast_hashtab_compare_contexts, 07336 ast_hashtab_resize_java, 07337 ast_hashtab_newsize_java, 07338 ast_hashtab_hash_contexts, 07339 0); 07340 } 07341 ast_unlock_contexts(); 07342 } 07343 07344 ast_copy_string(search.name, name, sizeof(search.name)); 07345 if (!extcontexts) { 07346 ast_rdlock_contexts(); 07347 local_contexts = &contexts; 07348 tmp = ast_hashtab_lookup(contexts_table, &search); 07349 ast_unlock_contexts(); 07350 if (tmp) { 07351 tmp->refcount++; 07352 return tmp; 07353 } 07354 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07355 local_contexts = extcontexts; 07356 tmp = ast_hashtab_lookup(exttable, &search); 07357 if (tmp) { 07358 tmp->refcount++; 07359 return tmp; 07360 } 07361 } 07362 07363 if ((tmp = ast_calloc(1, length))) { 07364 ast_rwlock_init(&tmp->lock); 07365 ast_mutex_init(&tmp->macrolock); 07366 strcpy(tmp->name, name); 07367 tmp->root = NULL; 07368 tmp->root_table = NULL; 07369 tmp->registrar = ast_strdup(registrar); 07370 tmp->includes = NULL; 07371 tmp->ignorepats = NULL; 07372 tmp->refcount = 1; 07373 } else { 07374 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07375 return NULL; 07376 } 07377 07378 if (!extcontexts) { 07379 ast_wrlock_contexts(); 07380 tmp->next = *local_contexts; 07381 *local_contexts = tmp; 07382 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07383 ast_unlock_contexts(); 07384 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07385 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07386 } else { 07387 tmp->next = *local_contexts; 07388 if (exttable) 07389 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07390 07391 *local_contexts = tmp; 07392 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07393 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07394 } 07395 return tmp; 07396 }
| int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
| macrocontext | name of the macro-context to lock |
| 0 | on success | |
| -1 | on failure |
Definition at line 5924 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05925 { 05926 struct ast_context *c; 05927 int ret = -1; 05928 05929 c = find_context_locked(context); 05930 if (c) { 05931 ast_unlock_contexts(); 05932 05933 /* if we found context, lock macrolock */ 05934 ret = ast_mutex_lock(&c->macrolock); 05935 } 05936 05937 return ret; 05938 }
| int ast_context_remove_extension | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar | |||
| ) |
Simply remove extension from context.
| context | context to remove extension from | |
| extension | which extension to remove | |
| priority | priority of extension to remove (0 to remove all) | |
| registrar | registrar of the extension |
| 0 | on success | |
| -1 | on failure |
Definition at line 5729 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), remove_exten_if_exist(), unregister_exten(), and UnregisterExtension().
05730 { 05731 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05732 }
| 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 5759 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
05760 { 05761 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05762 }
| 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 5734 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().
05735 { 05736 int ret = -1; /* default error return */ 05737 struct ast_context *c; 05738 05739 c = find_context_locked(context); 05740 if (c) { /* ... remove extension ... */ 05741 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 05742 matchcallerid, registrar, 0); 05743 ast_unlock_contexts(); 05744 } 05745 05746 return ret; 05747 }
| 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 5764 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
05765 { 05766 struct ast_exten *exten, *prev_exten = NULL; 05767 struct ast_exten *peer; 05768 struct ast_exten ex, *exten2, *exten3; 05769 char dummy_name[1024]; 05770 struct ast_exten *previous_peer = NULL; 05771 struct ast_exten *next_peer = NULL; 05772 int found = 0; 05773 05774 if (!already_locked) 05775 ast_wrlock_context(con); 05776 05777 /* Handle this is in the new world */ 05778 05779 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05780 * peers, not just those matching the callerid. */ 05781 #ifdef NEED_DEBUG 05782 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05783 #endif 05784 #ifdef CONTEXT_DEBUG 05785 check_contexts(__FILE__, __LINE__); 05786 #endif 05787 /* find this particular extension */ 05788 ex.exten = dummy_name; 05789 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05790 ex.cidmatch = callerid; 05791 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05792 exten = ast_hashtab_lookup(con->root_table, &ex); 05793 if (exten) { 05794 if (priority == 0) { 05795 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05796 if (!exten2) 05797 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); 05798 if (con->pattern_tree) { 05799 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05800 05801 if (x->exten) { /* this test for safety purposes */ 05802 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05803 x->exten = 0; /* get rid of what will become a bad pointer */ 05804 } else { 05805 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05806 } 05807 } 05808 } else { 05809 ex.priority = priority; 05810 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05811 if (exten2) { 05812 05813 if (exten2->label) { /* if this exten has a label, remove that, too */ 05814 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05815 if (!exten3) 05816 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); 05817 } 05818 05819 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05820 if (!exten3) 05821 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); 05822 if (exten2 == exten && exten2->peer) { 05823 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05824 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05825 } 05826 if (ast_hashtab_size(exten->peer_table) == 0) { 05827 /* well, if the last priority of an exten is to be removed, 05828 then, the extension is removed, too! */ 05829 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05830 if (!exten3) 05831 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05832 if (con->pattern_tree) { 05833 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05834 if (x->exten) { /* this test for safety purposes */ 05835 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05836 x->exten = 0; /* get rid of what will become a bad pointer */ 05837 } 05838 } 05839 } 05840 } else { 05841 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05842 priority, exten->exten, con->name); 05843 } 05844 } 05845 } else { 05846 /* hmmm? this exten is not in this pattern tree? */ 05847 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05848 extension, con->name); 05849 } 05850 #ifdef NEED_DEBUG 05851 if (con->pattern_tree) { 05852 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05853 log_match_char_tree(con->pattern_tree, " "); 05854 } 05855 #endif 05856 05857 /* scan the extension list to find first matching extension-registrar */ 05858 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05859 if (!strcmp(exten->exten, extension) && 05860 (!registrar || !strcmp(exten->registrar, registrar)) && 05861 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05862 break; 05863 } 05864 if (!exten) { 05865 /* we can't find right extension */ 05866 if (!already_locked) 05867 ast_unlock_context(con); 05868 return -1; 05869 } 05870 05871 /* scan the priority list to remove extension with exten->priority == priority */ 05872 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05873 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))); 05874 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05875 if ((priority == 0 || peer->priority == priority) && 05876 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05877 (!registrar || !strcmp(peer->registrar, registrar) )) { 05878 found = 1; 05879 05880 /* we are first priority extension? */ 05881 if (!previous_peer) { 05882 /* 05883 * We are first in the priority chain, so must update the extension chain. 05884 * The next node is either the next priority or the next extension 05885 */ 05886 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05887 if (peer->peer) { 05888 /* move the peer_table and peer_label_table down to the next peer, if 05889 it is there */ 05890 peer->peer->peer_table = peer->peer_table; 05891 peer->peer->peer_label_table = peer->peer_label_table; 05892 peer->peer_table = NULL; 05893 peer->peer_label_table = NULL; 05894 } 05895 if (!prev_exten) { /* change the root... */ 05896 con->root = next_node; 05897 } else { 05898 prev_exten->next = next_node; /* unlink */ 05899 } 05900 if (peer->peer) { /* update the new head of the pri list */ 05901 peer->peer->next = peer->next; 05902 } 05903 } else { /* easy, we are not first priority in extension */ 05904 previous_peer->peer = peer->peer; 05905 } 05906 05907 /* now, free whole priority extension */ 05908 destroy_exten(peer); 05909 } else { 05910 previous_peer = peer; 05911 } 05912 } 05913 if (!already_locked) 05914 ast_unlock_context(con); 05915 return found ? 0 : -1; 05916 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8135 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08136 { 08137 int ret = -1; 08138 struct ast_context *c; 08139 08140 c = find_context_locked(context); 08141 if (c) { 08142 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08143 ast_unlock_contexts(); 08144 } 08145 return ret; 08146 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8148 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().
08149 { 08150 struct ast_ignorepat *ip, *ipl = NULL; 08151 08152 ast_wrlock_context(con); 08153 08154 for (ip = con->ignorepats; ip; ip = ip->next) { 08155 if (!strcmp(ip->pattern, ignorepat) && 08156 (!registrar || (registrar == ip->registrar))) { 08157 if (ipl) { 08158 ipl->next = ip->next; 08159 ast_free(ip); 08160 } else { 08161 con->ignorepats = ip->next; 08162 ast_free(ip); 08163 } 08164 ast_unlock_context(con); 08165 return 0; 08166 } 08167 ipl = ip; 08168 } 08169 08170 ast_unlock_context(con); 08171 errno = EINVAL; 08172 return -1; 08173 }
| 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 5622 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05623 { 05624 int ret = -1; 05625 struct ast_context *c; 05626 05627 c = find_context_locked(context); 05628 if (c) { 05629 /* found, remove include from this context ... */ 05630 ret = ast_context_remove_include2(c, include, registrar); 05631 ast_unlock_contexts(); 05632 } 05633 return ret; 05634 }
| 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 |
| 0 | on success. | |
| -1 | on failure. |
Definition at line 5645 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().
05646 { 05647 struct ast_include *i, *pi = NULL; 05648 int ret = -1; 05649 05650 ast_wrlock_context(con); 05651 05652 /* find our include */ 05653 for (i = con->includes; i; pi = i, i = i->next) { 05654 if (!strcmp(i->name, include) && 05655 (!registrar || !strcmp(i->registrar, registrar))) { 05656 /* remove from list */ 05657 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05658 if (pi) 05659 pi->next = i->next; 05660 else 05661 con->includes = i->next; 05662 /* free include and return */ 05663 ast_destroy_timing(&(i->timing)); 05664 ast_free(i); 05665 ret = 0; 05666 break; 05667 } 05668 } 05669 05670 ast_unlock_context(con); 05671 05672 return ret; 05673 }
| 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 5680 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05681 { 05682 int ret = -1; /* default error return */ 05683 struct ast_context *c; 05684 05685 c = find_context_locked(context); 05686 if (c) { 05687 /* remove switch from this context ... */ 05688 ret = ast_context_remove_switch2(c, sw, data, registrar); 05689 ast_unlock_contexts(); 05690 } 05691 return ret; 05692 }
| 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 5702 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().
05703 { 05704 struct ast_sw *i; 05705 int ret = -1; 05706 05707 ast_wrlock_context(con); 05708 05709 /* walk switches */ 05710 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05711 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05712 (!registrar || !strcmp(i->registrar, registrar))) { 05713 /* found, remove from list */ 05714 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05715 AST_LIST_REMOVE_CURRENT(list); 05716 ast_free(i); /* free switch and return */ 05717 ret = 0; 05718 break; 05719 } 05720 } 05721 AST_LIST_TRAVERSE_SAFE_END; 05722 05723 ast_unlock_context(con); 05724 05725 return ret; 05726 }
| int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
| macrocontext | name of the macro-context to unlock |
| 0 | on success | |
| -1 | on failure |
Definition at line 5945 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05946 { 05947 struct ast_context *c; 05948 int ret = -1; 05949 05950 c = find_context_locked(context); 05951 if (c) { 05952 ast_unlock_contexts(); 05953 05954 /* if we found context, unlock macrolock */ 05955 ret = ast_mutex_unlock(&c->macrolock); 05956 } 05957 05958 return ret; 05959 }
| 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 10663 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().
10664 { 10665 struct ast_include *inc = NULL; 10666 int res = 0; 10667 10668 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10669 if (ast_context_find(inc->rname)) 10670 continue; 10671 10672 res = -1; 10673 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10674 ast_get_context_name(con), inc->rname); 10675 break; 10676 } 10677 10678 return res; 10679 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3626 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03627 { 03628 struct ast_custom_function *acf = NULL; 03629 03630 AST_RWLIST_RDLOCK(&acf_root); 03631 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03632 if (!strcmp(name, acf->name)) 03633 break; 03634 } 03635 AST_RWLIST_UNLOCK(&acf_root); 03636 03637 return acf; 03638 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3640 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by _unload_module(), load_module(), reload(), and unload_module().
03641 { 03642 struct ast_custom_function *cur; 03643 03644 if (!acf) { 03645 return -1; 03646 } 03647 03648 AST_RWLIST_WRLOCK(&acf_root); 03649 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03650 #ifdef AST_XML_DOCS 03651 if (cur->docsrc == AST_XML_DOC) { 03652 ast_string_field_free_memory(acf); 03653 } 03654 #endif 03655 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03656 } 03657 AST_RWLIST_UNLOCK(&acf_root); 03658 03659 return cur ? 0 : -1; 03660 }
| 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 7977 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().
07978 { 07979 if (i->timezone) { 07980 ast_free(i->timezone); 07981 i->timezone = NULL; 07982 } 07983 return 0; 07984 }
| enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
| [in] | devstate | device state |
Definition at line 4449 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.
Referenced by ast_extension_state3().
04450 { 04451 switch (devstate) { 04452 case AST_DEVICE_ONHOLD: 04453 return AST_EXTENSION_ONHOLD; 04454 case AST_DEVICE_BUSY: 04455 return AST_EXTENSION_BUSY; 04456 case AST_DEVICE_UNKNOWN: 04457 return AST_EXTENSION_NOT_INUSE; 04458 case AST_DEVICE_UNAVAILABLE: 04459 case AST_DEVICE_INVALID: 04460 return AST_EXTENSION_UNAVAILABLE; 04461 case AST_DEVICE_RINGINUSE: 04462 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04463 case AST_DEVICE_RINGING: 04464 return AST_EXTENSION_RINGING; 04465 case AST_DEVICE_INUSE: 04466 return AST_EXTENSION_INUSE; 04467 case AST_DEVICE_NOT_INUSE: 04468 return AST_EXTENSION_NOT_INUSE; 04469 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04470 break; 04471 } 04472 04473 return AST_EXTENSION_NOT_INUSE; 04474 }
| 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 5026 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), action_originate(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), fax_detect_framehook(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), setsubstate(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().
05027 { 05028 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05029 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 8288 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(), msg_route(), pbx_parseable_goto(), and return_exec().
08289 { 08290 if (!chan) 08291 return -1; 08292 08293 ast_channel_lock(chan); 08294 08295 if (!ast_strlen_zero(context)) 08296 ast_copy_string(chan->context, context, sizeof(chan->context)); 08297 if (!ast_strlen_zero(exten)) 08298 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08299 if (priority > -1) { 08300 chan->priority = priority; 08301 /* see flag description in channel.h for explanation */ 08302 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08303 chan->priority--; 08304 } 08305 08306 ast_channel_unlock(chan); 08307 08308 return 0; 08309 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 2754 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().
02755 { 02756 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02757 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02758 return extension_match_core(pattern, data, needmore); 02759 }
| int ast_extension_cmp | ( | const char * | a, | |
| const char * | b | |||
| ) |
Determine if one extension should match before another.
Checks whether or extension a should match before extension b
| 0 | if the two extensions have equal matching priority | |
| 1 | on a > b | |
| -1 | on a < b |
Definition at line 2556 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02557 { 02558 return ext_cmp(a, b); 02559 }
| int ast_extension_match | ( | const char * | pattern, | |
| const char * | extension | |||
| ) |
Determine if a given extension matches a given pattern (in NXX format).
Checks whether or not the given extension matches the given pattern.
| 1 | on match | |
| 0 | on failure |
Definition at line 2749 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().
02750 { 02751 return extension_match_core(pattern, data, E_MATCH); 02752 }
| 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 4519 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.
Referenced by action_extensionstate(), extstate_read(), get_queue_member_status(), and handle_request_subscribe().
04520 { 04521 struct ast_exten *e; 04522 04523 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04524 return -1; /* No hint, return -1 */ 04525 } 04526 04527 if (e->exten[0] == '_') { 04528 /* Create this hint on-the-fly */ 04529 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04530 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04531 e->registrar); 04532 if (!(e = ast_hint_extension(c, context, exten))) { 04533 /* Improbable, but not impossible */ 04534 return -1; 04535 } 04536 } 04537 04538 return ast_extension_state2(e); /* Check all devices in the hint */ 04539 }
| 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 4507 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), show_channels_cb(), and skinny_extensionstate_cb().
04508 { 04509 int i; 04510 04511 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04512 if (extension_states[i].extension_state == extension_state) 04513 return extension_states[i].text; 04514 } 04515 return "Unknown"; 04516 }
| int ast_extension_state_add | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | change_cb, | |||
| void * | data | |||
| ) |
Registers a state change callback.
| context | which context to look in | |
| exten | which extension to get state | |
| change_cb | callback to call if state changed | |
| data | to pass to callback |
| -1 | on failure | |
| ID | on success |
Definition at line 4752 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
04754 { 04755 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 04756 }
| int ast_extension_state_add_destroy | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | change_cb, | |||
| ast_state_cb_destroy_type | destroy_cb, | |||
| void * | data | |||
| ) |
Registers a state change callback with destructor.
10.1.0
| context | which context to look in | |
| exten | which extension to get state | |
| change_cb | callback to call if state changed | |
| destroy_cb | callback to call when registration destroyed. | |
| data | to pass to callback |
The destroy_cb is called when the registration is deleted so the registerer can release any associated resources.
| -1 | on failure | |
| ID | on success |
Definition at line 4665 of file pbx.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, hints, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.
Referenced by ast_extension_state_add(), and handle_request_subscribe().
04667 { 04668 struct ast_hint *hint; 04669 struct ast_state_cb *state_cb; 04670 struct ast_exten *e; 04671 int id; 04672 04673 /* If there's no context and extension: add callback to statecbs list */ 04674 if (!context && !exten) { 04675 /* Prevent multiple adds from adding the same change_cb at the same time. */ 04676 ao2_lock(statecbs); 04677 04678 /* Remove any existing change_cb. */ 04679 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 04680 04681 /* Now insert the change_cb */ 04682 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04683 ao2_unlock(statecbs); 04684 return -1; 04685 } 04686 state_cb->id = 0; 04687 state_cb->change_cb = change_cb; 04688 state_cb->destroy_cb = destroy_cb; 04689 state_cb->data = data; 04690 ao2_link(statecbs, state_cb); 04691 04692 ao2_ref(state_cb, -1); 04693 ao2_unlock(statecbs); 04694 return 0; 04695 } 04696 04697 if (!context || !exten) 04698 return -1; 04699 04700 /* This callback type is for only one hint, so get the hint */ 04701 e = ast_hint_extension(NULL, context, exten); 04702 if (!e) { 04703 return -1; 04704 } 04705 04706 /* If this is a pattern, dynamically create a new extension for this 04707 * particular match. Note that this will only happen once for each 04708 * individual extension, because the pattern will no longer match first. 04709 */ 04710 if (e->exten[0] == '_') { 04711 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04712 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04713 e->registrar); 04714 e = ast_hint_extension(NULL, context, exten); 04715 if (!e || e->exten[0] == '_') { 04716 return -1; 04717 } 04718 } 04719 04720 /* Find the hint in the hints container */ 04721 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04722 hint = ao2_find(hints, e, 0); 04723 if (!hint) { 04724 ao2_unlock(hints); 04725 return -1; 04726 } 04727 04728 /* Now insert the callback in the callback list */ 04729 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04730 ao2_ref(hint, -1); 04731 ao2_unlock(hints); 04732 return -1; 04733 } 04734 do { 04735 id = stateid++; /* Unique ID for this callback */ 04736 /* Do not allow id to ever be -1 or 0. */ 04737 } while (id == -1 || id == 0); 04738 state_cb->id = id; 04739 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 04740 state_cb->destroy_cb = destroy_cb; 04741 state_cb->data = data; /* Data for the callback */ 04742 ao2_link(hint->callbacks, state_cb); 04743 04744 ao2_ref(state_cb, -1); 04745 ao2_ref(hint, -1); 04746 ao2_unlock(hints); 04747 04748 return id; 04749 }
| int ast_extension_state_del | ( | int | id, | |
| ast_state_cb_type | change_cb | |||
| ) |
Deletes a registered state change callback by ID.
| id | of the registered state callback to delete | |
| change_cb | callback to call if state changed (Used if id == 0 (global)) |
| 0 | success | |
| -1 | failure |
Definition at line 4774 of file pbx.c.
References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::callbacks, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
04775 { 04776 struct ast_state_cb *p_cur; 04777 int ret = -1; 04778 04779 if (!id) { /* id == 0 is a callback without extension */ 04780 if (!change_cb) { 04781 return ret; 04782 } 04783 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 04784 if (p_cur) { 04785 ret = 0; 04786 ao2_ref(p_cur, -1); 04787 } 04788 } else { /* callback with extension, find the callback based on ID */ 04789 struct ast_hint *hint; 04790 04791 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04792 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04793 if (hint) { 04794 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04795 if (p_cur) { 04796 ret = 0; 04797 ao2_ref(p_cur, -1); 04798 } 04799 ao2_ref(hint, -1); 04800 } 04801 ao2_unlock(hints); 04802 } 04803 04804 return ret; 04805 }
| 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 5031 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().
05032 { 05033 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05034 }
| int ast_findlabel_extension2 | ( | struct ast_channel * | c, | |
| struct ast_context * | con, | |||
| const char * | exten, | |||
| const char * | label, | |||
| const char * | callerid | |||
| ) |
Find the priority of an extension that has the specified label.
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.
Definition at line 5036 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05037 { 05038 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05039 }
| int ast_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | workspace, | |||
| size_t | len | |||
| ) |
executes a read operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| workspace | A pointer to safe memory to use for a return value | |
| len | the number of bytes in workspace |
| 0 | success | |
| non-zero | failure |
Definition at line 3784 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03785 { 03786 char *copy = ast_strdupa(function); 03787 char *args = func_args(copy); 03788 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03789 int res; 03790 struct ast_module_user *u = NULL; 03791 03792 if (acfptr == NULL) { 03793 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03794 } else if (!acfptr->read && !acfptr->read2) { 03795 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03796 } else if (acfptr->read) { 03797 if (acfptr->mod) { 03798 u = __ast_module_user_add(acfptr->mod, chan); 03799 } 03800 res = acfptr->read(chan, copy, args, workspace, len); 03801 if (acfptr->mod && u) { 03802 __ast_module_user_remove(acfptr->mod, u); 03803 } 03804 return res; 03805 } else { 03806 struct ast_str *str = ast_str_create(16); 03807 if (acfptr->mod) { 03808 u = __ast_module_user_add(acfptr->mod, chan); 03809 } 03810 res = acfptr->read2(chan, copy, args, &str, 0); 03811 if (acfptr->mod && u) { 03812 __ast_module_user_remove(acfptr->mod, u); 03813 } 03814 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03815 ast_free(str); 03816 return res; 03817 } 03818 return -1; 03819 }
| int ast_func_read2 | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| struct ast_str ** | str, | |||
| ssize_t | maxlen | |||
| ) |
executes a read operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| str | A dynamic string buffer into which to place the result. | |
| maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
| 0 | success | |
| non-zero | failure |
Definition at line 3821 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
03822 { 03823 char *copy = ast_strdupa(function); 03824 char *args = func_args(copy); 03825 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03826 int res; 03827 struct ast_module_user *u = NULL; 03828 03829 if (acfptr == NULL) { 03830 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03831 } else if (!acfptr->read && !acfptr->read2) { 03832 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03833 } else { 03834 if (acfptr->mod) { 03835 u = __ast_module_user_add(acfptr->mod, chan); 03836 } 03837 ast_str_reset(*str); 03838 if (acfptr->read2) { 03839 /* ast_str enabled */ 03840 res = acfptr->read2(chan, copy, args, str, maxlen); 03841 } else { 03842 /* Legacy function pointer, allocate buffer for result */ 03843 int maxsize = ast_str_size(*str); 03844 if (maxlen > -1) { 03845 if (maxlen == 0) { 03846 if (acfptr->read_max) { 03847 maxsize = acfptr->read_max; 03848 } else { 03849 maxsize = VAR_BUF_SIZE; 03850 } 03851 } else { 03852 maxsize = maxlen; 03853 } 03854 ast_str_make_space(str, maxsize); 03855 } 03856 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03857 } 03858 if (acfptr->mod && u) { 03859 __ast_module_user_remove(acfptr->mod, u); 03860 } 03861 return res; 03862 } 03863 return -1; 03864 }
| int ast_func_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| const char * | value | |||
| ) |
executes a write operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| value | A value parameter to pass for writing |
| 0 | success | |
| non-zero | failure |
Definition at line 3866 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), confbridge_exec(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03867 { 03868 char *copy = ast_strdupa(function); 03869 char *args = func_args(copy); 03870 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03871 03872 if (acfptr == NULL) 03873 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03874 else if (!acfptr->write) 03875 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03876 else { 03877 int res; 03878 struct ast_module_user *u = NULL; 03879 if (acfptr->mod) 03880 u = __ast_module_user_add(acfptr->mod, chan); 03881 res = acfptr->write(chan, copy, args, value); 03882 if (acfptr->mod && u) 03883 __ast_module_user_remove(acfptr->mod, u); 03884 return res; 03885 } 03886 03887 return -1; 03888 }
| const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10515 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_add_hint(), ast_change_hint(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), ast_remove_hint(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10516 { 10517 return con ? con->name : NULL; 10518 }
| const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10553 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10554 { 10555 return c ? c->registrar : NULL; 10556 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10583 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_change_hint(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), get_parking_exten(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
10584 { 10585 return e ? e->app : NULL; 10586 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10588 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_masq_park_call_exten(), ast_park_call_exten(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), print_ext(), and xfer_park_call_helper().
10589 { 10590 return e ? e->data : NULL; 10591 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10578 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10579 { 10580 return e ? e->cidmatch : NULL; 10581 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10520 of file pbx.c.
References ast_exten::parent.
Referenced by ast_add_hint(), ast_change_hint(), ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
10521 { 10522 return exten ? exten->parent : NULL; 10523 }
| const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 10530 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 10573 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10574 { 10575 return e ? e->matchcid : 0; 10576 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10525 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint(), ast_change_hint(), ast_remove_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), destroy_hint(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().
10526 { 10527 return exten ? exten->exten : NULL; 10528 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10545 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().
10546 { 10547 return exten ? exten->priority : -1; 10548 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10558 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10559 { 10560 return e ? e->registrar : NULL; 10561 }
| 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 4988 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().
04989 { 04990 struct ast_exten *e = ast_hint_extension(c, context, exten); 04991 04992 if (e) { 04993 if (hint) 04994 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04995 if (name) { 04996 const char *tmp = ast_get_extension_app_data(e); 04997 if (tmp) 04998 ast_copy_string(name, tmp, namesize); 04999 } 05000 return -1; 05001 } 05002 return 0; 05003 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10540 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().
10541 { 10542 return ip ? ip->pattern : NULL; 10543 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10568 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().
10569 { 10570 return ip ? ip->registrar : NULL; 10571 }
| const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 10535 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 10563 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().
10564 { 10565 return i ? i->registrar : NULL; 10566 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10598 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().
10599 { 10600 return sw ? sw->data : NULL; 10601 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10603 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10604 { 10605 return sw->eval; 10606 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10593 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().
10594 { 10595 return sw ? sw->name : NULL; 10596 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10608 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().
10609 { 10610 return sw ? sw->registrar : NULL; 10611 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 10703 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10704 { 10705 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10706 }
| int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) |
hashtable functions for contexts
Definition at line 1186 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_hints(), lua_register_switches(), and pbx_load_module().
01187 { 01188 const struct ast_context *ac = ah_a; 01189 const struct ast_context *bc = ah_b; 01190 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01191 return 1; 01192 /* assume context names are registered in a string table! */ 01193 return strcmp(ac->name, bc->name); 01194 }
| unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1229 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_hints(), lua_register_switches(), and pbx_load_module().
01230 { 01231 const struct ast_context *ac = obj; 01232 return ast_hashtab_hash_string(ac->name); 01233 }
| int ast_ignore_pattern | ( | const char * | context, | |
| const char * | pattern | |||
| ) |
Checks to see if a number should be ignored.
| context | context to search within | |
| pattern | to check whether it should be ignored or not |
| 0 | if the pattern should not be ignored | |
| non-zero | if the pattern should be ignored |
Definition at line 8230 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), mgcp_ss(), and skinny_ss().
08231 { 08232 struct ast_context *con = ast_context_find(context); 08233 08234 if (con) { 08235 struct ast_ignorepat *pat; 08236 08237 for (pat = con->ignorepats; pat; pat = pat->next) { 08238 if (ast_extension_match(pat->pattern, pattern)) 08239 return 1; 08240 } 08241 } 08242 08243 return 0; 08244 }
| 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 5046 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().
05047 { 05048 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05049 }
| 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 7528 of file pbx.c.
References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07529 { 07530 double ft; 07531 struct ast_context *tmp; 07532 struct ast_context *oldcontextslist; 07533 struct ast_hashtab *oldtable; 07534 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07535 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07536 struct store_hint *saved_hint; 07537 struct ast_hint *hint; 07538 struct ast_exten *exten; 07539 int length; 07540 struct ast_state_cb *thiscb; 07541 struct ast_hashtab_iter *iter; 07542 struct ao2_iterator i; 07543 struct timeval begintime; 07544 struct timeval writelocktime; 07545 struct timeval endlocktime; 07546 struct timeval enddeltime; 07547 07548 /* 07549 * It is very important that this function hold the hints 07550 * container lock _and_ the conlock during its operation; not 07551 * only do we need to ensure that the list of contexts and 07552 * extensions does not change, but also that no hint callbacks 07553 * (watchers) are added or removed during the merge/delete 07554 * process 07555 * 07556 * In addition, the locks _must_ be taken in this order, because 07557 * there are already other code paths that use this order 07558 */ 07559 07560 begintime = ast_tvnow(); 07561 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07562 ast_wrlock_contexts(); 07563 iter = ast_hashtab_start_traversal(contexts_table); 07564 while ((tmp = ast_hashtab_next(iter))) { 07565 context_merge(extcontexts, exttable, tmp, registrar); 07566 } 07567 ast_hashtab_end_traversal(iter); 07568 07569 ao2_lock(hints); 07570 writelocktime = ast_tvnow(); 07571 07572 /* preserve all watchers for hints */ 07573 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07574 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07575 if (ao2_container_count(hint->callbacks)) { 07576 ao2_lock(hint); 07577 if (!hint->exten) { 07578 /* The extension has already been destroyed. (Should never happen here) */ 07579 ao2_unlock(hint); 07580 continue; 07581 } 07582 07583 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07584 + sizeof(*saved_hint); 07585 if (!(saved_hint = ast_calloc(1, length))) { 07586 ao2_unlock(hint); 07587 continue; 07588 } 07589 07590 /* This removes all the callbacks from the hint into saved_hint. */ 07591 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07592 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07593 /* 07594 * We intentionally do not unref thiscb to account for the 07595 * non-ao2 reference in saved_hint->callbacks 07596 */ 07597 } 07598 07599 saved_hint->laststate = hint->laststate; 07600 saved_hint->context = saved_hint->data; 07601 strcpy(saved_hint->data, hint->exten->parent->name); 07602 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07603 strcpy(saved_hint->exten, hint->exten->exten); 07604 ao2_unlock(hint); 07605 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07606 } 07607 } 07608 ao2_iterator_destroy(&i); 07609 07610 /* save the old table and list */ 07611 oldtable = contexts_table; 07612 oldcontextslist = contexts; 07613 07614 /* move in the new table and list */ 07615 contexts_table = exttable; 07616 contexts = *extcontexts; 07617 07618 /* 07619 * Restore the watchers for hints that can be found; notify 07620 * those that cannot be restored. 07621 */ 07622 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07623 struct pbx_find_info q = { .stacklen = 0 }; 07624 07625 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07626 PRIORITY_HINT, NULL, "", E_MATCH); 07627 /* 07628 * If this is a pattern, dynamically create a new extension for this 07629 * particular match. Note that this will only happen once for each 07630 * individual extension, because the pattern will no longer match first. 07631 */ 07632 if (exten && exten->exten[0] == '_') { 07633 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07634 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07635 exten->registrar); 07636 /* rwlocks are not recursive locks */ 07637 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07638 saved_hint->exten); 07639 } 07640 07641 /* Find the hint in the hints container */ 07642 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07643 if (!hint) { 07644 /* 07645 * Notify watchers of this removed hint later when we aren't 07646 * encumberd by so many locks. 07647 */ 07648 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07649 } else { 07650 ao2_lock(hint); 07651 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07652 ao2_link(hint->callbacks, thiscb); 07653 /* Ref that we added when putting into saved_hint->callbacks */ 07654 ao2_ref(thiscb, -1); 07655 } 07656 hint->laststate = saved_hint->laststate; 07657 ao2_unlock(hint); 07658 ao2_ref(hint, -1); 07659 ast_free(saved_hint); 07660 } 07661 } 07662 07663 ao2_unlock(hints); 07664 ast_unlock_contexts(); 07665 07666 /* 07667 * Notify watchers of all removed hints with the same lock 07668 * environment as handle_statechange(). 07669 */ 07670 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 07671 /* this hint has been removed, notify the watchers */ 07672 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07673 thiscb->change_cb(saved_hint->context, saved_hint->exten, 07674 AST_EXTENSION_REMOVED, thiscb->data); 07675 /* Ref that we added when putting into saved_hint->callbacks */ 07676 ao2_ref(thiscb, -1); 07677 } 07678 ast_free(saved_hint); 07679 } 07680 07681 ast_mutex_unlock(&context_merge_lock); 07682 endlocktime = ast_tvnow(); 07683 07684 /* 07685 * The old list and hashtab no longer are relevant, delete them 07686 * while the rest of asterisk is now freely using the new stuff 07687 * instead. 07688 */ 07689 07690 ast_hashtab_destroy(oldtable, NULL); 07691 07692 for (tmp = oldcontextslist; tmp; ) { 07693 struct ast_context *next; /* next starting point */ 07694 07695 next = tmp->next; 07696 __ast_internal_context_destroy(tmp); 07697 tmp = next; 07698 } 07699 enddeltime = ast_tvnow(); 07700 07701 ft = ast_tvdiff_us(writelocktime, begintime); 07702 ft /= 1000000.0; 07703 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07704 07705 ft = ast_tvdiff_us(endlocktime, writelocktime); 07706 ft /= 1000000.0; 07707 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07708 07709 ft = ast_tvdiff_us(enddeltime, endlocktime); 07710 ft /= 1000000.0; 07711 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07712 07713 ft = ast_tvdiff_us(enddeltime, begintime); 07714 ft /= 1000000.0; 07715 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07716 }
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 10768 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().
10769 { 10770 return pbx_parseable_goto(chan, goto_string, 0); 10771 }
| int ast_pbx_outgoing_app | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const char * | addr, | |||
| 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 9107 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
09108 { 09109 struct ast_channel *chan; 09110 struct app_tmp *tmp; 09111 int res = -1, cdr_res = -1; 09112 struct outgoing_helper oh; 09113 09114 memset(&oh, 0, sizeof(oh)); 09115 oh.vars = vars; 09116 oh.account = account; 09117 09118 if (locked_channel) 09119 *locked_channel = NULL; 09120 if (ast_strlen_zero(app)) { 09121 res = -1; 09122 goto outgoing_app_cleanup; 09123 } 09124 if (synchronous) { 09125 chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh); 09126 if (chan) { 09127 ast_set_variables(chan, vars); 09128 if (account) 09129 ast_cdr_setaccount(chan, account); 09130 if (chan->_state == AST_STATE_UP) { 09131 res = 0; 09132 ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan)); 09133 tmp = ast_calloc(1, sizeof(*tmp)); 09134 if (!tmp || ast_string_field_init(tmp, 252)) { 09135 if (tmp) { 09136 ast_free(tmp); 09137 } 09138 res = -1; 09139 } else { 09140 ast_string_field_set(tmp, app, app); 09141 ast_string_field_set(tmp, data, appdata); 09142 tmp->chan = chan; 09143 if (synchronous > 1) { 09144 if (locked_channel) 09145 ast_channel_unlock(chan); 09146 ast_pbx_run_app(tmp); 09147 } else { 09148 if (locked_channel) 09149 ast_channel_lock(chan); 09150 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09151 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", ast_channel_name(chan), strerror(errno)); 09152 ast_string_field_free_memory(tmp); 09153 ast_free(tmp); 09154 if (locked_channel) 09155 ast_channel_unlock(chan); 09156 ast_hangup(chan); 09157 res = -1; 09158 } else { 09159 if (locked_channel) 09160 *locked_channel = chan; 09161 } 09162 } 09163 } 09164 } else { 09165 ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan)); 09166 if (chan->cdr) { /* update the cdr */ 09167 /* here we update the status of the call, which sould be busy. 09168 * if that fails then we set the status to failed */ 09169 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09170 ast_cdr_failed(chan->cdr); 09171 } 09172 ast_hangup(chan); 09173 } 09174 } 09175 09176 if (res < 0) { /* the call failed for some reason */ 09177 if (*reason == 0) { /* if the call failed (not busy or no answer) 09178 * update the cdr with the failed message */ 09179 cdr_res = ast_pbx_outgoing_cdr_failed(); 09180 if (cdr_res != 0) { 09181 res = cdr_res; 09182 goto outgoing_app_cleanup; 09183 } 09184 } 09185 } 09186 09187 } else { 09188 struct async_stat *as; 09189 if (!(as = ast_calloc(1, sizeof(*as)))) { 09190 res = -1; 09191 goto outgoing_app_cleanup; 09192 } 09193 chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh); 09194 if (!chan) { 09195 ast_free(as); 09196 res = -1; 09197 goto outgoing_app_cleanup; 09198 } 09199 as->chan = chan; 09200 ast_copy_string(as->app, app, sizeof(as->app)); 09201 if (appdata) 09202 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09203 as->timeout = timeout; 09204 ast_set_variables(chan, vars); 09205 if (account) 09206 ast_cdr_setaccount(chan, account); 09207 /* Start a new thread, and get something handling this channel. */ 09208 if (locked_channel) 09209 ast_channel_lock(chan); 09210 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09211 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09212 ast_free(as); 09213 if (locked_channel) 09214 ast_channel_unlock(chan); 09215 ast_hangup(chan); 09216 res = -1; 09217 goto outgoing_app_cleanup; 09218 } else { 09219 if (locked_channel) 09220 *locked_channel = chan; 09221 } 09222 res = 0; 09223 } 09224 outgoing_app_cleanup: 09225 ast_variables_destroy(vars); 09226 return res; 09227 }
| int ast_pbx_outgoing_exten | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const char * | addr, | |||
| 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 8938 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_name(), ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
08939 { 08940 struct ast_channel *chan; 08941 struct async_stat *as; 08942 int res = -1, cdr_res = -1; 08943 struct outgoing_helper oh; 08944 08945 if (synchronous) { 08946 oh.context = context; 08947 oh.exten = exten; 08948 oh.priority = priority; 08949 oh.cid_num = cid_num; 08950 oh.cid_name = cid_name; 08951 oh.account = account; 08952 oh.vars = vars; 08953 oh.parent_channel = NULL; 08954 08955 chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh); 08956 if (channel) { 08957 *channel = chan; 08958 if (chan) 08959 ast_channel_lock(chan); 08960 } 08961 if (chan) { 08962 if (chan->_state == AST_STATE_UP) { 08963 res = 0; 08964 ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan)); 08965 08966 if (synchronous > 1) { 08967 if (channel) 08968 ast_channel_unlock(chan); 08969 if (ast_pbx_run(chan)) { 08970 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan)); 08971 if (channel) 08972 *channel = NULL; 08973 ast_hangup(chan); 08974 chan = NULL; 08975 res = -1; 08976 } 08977 } else { 08978 if (ast_pbx_start(chan)) { 08979 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", ast_channel_name(chan)); 08980 if (channel) { 08981 *channel = NULL; 08982 ast_channel_unlock(chan); 08983 } 08984 ast_hangup(chan); 08985 res = -1; 08986 } 08987 chan = NULL; 08988 } 08989 } else { 08990 ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan)); 08991 08992 if (chan->cdr) { /* update the cdr */ 08993 /* here we update the status of the call, which sould be busy. 08994 * if that fails then we set the status to failed */ 08995 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08996 ast_cdr_failed(chan->cdr); 08997 } 08998 08999 if (channel) { 09000 *channel = NULL; 09001 ast_channel_unlock(chan); 09002 } 09003 ast_hangup(chan); 09004 chan = NULL; 09005 } 09006 } 09007 09008 if (res < 0) { /* the call failed for some reason */ 09009 if (*reason == 0) { /* if the call failed (not busy or no answer) 09010 * update the cdr with the failed message */ 09011 cdr_res = ast_pbx_outgoing_cdr_failed(); 09012 if (cdr_res != 0) { 09013 res = cdr_res; 09014 goto outgoing_exten_cleanup; 09015 } 09016 } 09017 09018 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09019 /* check if "failed" exists */ 09020 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09021 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09022 if (chan) { 09023 char failed_reason[4] = ""; 09024 if (!ast_strlen_zero(context)) 09025 ast_copy_string(chan->context, context, sizeof(chan->context)); 09026 set_ext_pri(chan, "failed", 1); 09027 ast_set_variables(chan, vars); 09028 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09029 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09030 if (account) 09031 ast_cdr_setaccount(chan, account); 09032 if (ast_pbx_run(chan)) { 09033 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan)); 09034 ast_hangup(chan); 09035 } 09036 chan = NULL; 09037 } 09038 } 09039 } 09040 } else { 09041 if (!(as = ast_calloc(1, sizeof(*as)))) { 09042 res = -1; 09043 goto outgoing_exten_cleanup; 09044 } 09045 chan = ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name); 09046 if (channel) { 09047 *channel = chan; 09048 if (chan) 09049 ast_channel_lock(chan); 09050 } 09051 if (!chan) { 09052 ast_free(as); 09053 res = -1; 09054 goto outgoing_exten_cleanup; 09055 } 09056 as->chan = chan; 09057 ast_copy_string(as->context, context, sizeof(as->context)); 09058 set_ext_pri(as->chan, exten, priority); 09059 as->timeout = timeout; 09060 ast_set_variables(chan, vars); 09061 if (account) 09062 ast_cdr_setaccount(chan, account); 09063 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09064 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09065 ast_free(as); 09066 if (channel) { 09067 *channel = NULL; 09068 ast_channel_unlock(chan); 09069 } 09070 ast_hangup(chan); 09071 res = -1; 09072 goto outgoing_exten_cleanup; 09073 } 09074 res = 0; 09075 } 09076 outgoing_exten_cleanup: 09077 ast_variables_destroy(vars); 09078 return res; 09079 }
| enum ast_pbx_result ast_pbx_run | ( | struct ast_channel * | c | ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on |
| Zero | on success | |
| non-zero | on failure |
Definition at line 5541 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_notify(), mgcp_ss(), skinny_newcall(), and unistim_ss().
05542 { 05543 return ast_pbx_run_args(c, NULL); 05544 }
| enum ast_pbx_result ast_pbx_run_args | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on | |
| args | options for the pbx |
| Zero | on success | |
| non-zero | on failure |
Definition at line 5521 of file pbx.c.
References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.
Referenced by action_dialplan_exec(), ast_pbx_run(), dial_exec_full(), handle_gosub(), msg_route(), and try_calling().
05522 { 05523 enum ast_pbx_result res = AST_PBX_SUCCESS; 05524 05525 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05526 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05527 return AST_PBX_FAILED; 05528 } 05529 05530 if (increase_call_count(c)) { 05531 return AST_PBX_CALL_LIMIT; 05532 } 05533 05534 res = __ast_pbx_run(c, args); 05535 05536 decrease_call_count(); 05537 05538 return res; 05539 }
| 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 5494 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), skinny_new(), unistim_new(), and usbradio_new().
05495 { 05496 pthread_t t; 05497 05498 if (!c) { 05499 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05500 return AST_PBX_FAILED; 05501 } 05502 05503 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05504 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05505 return AST_PBX_FAILED; 05506 } 05507 05508 if (increase_call_count(c)) 05509 return AST_PBX_CALL_LIMIT; 05510 05511 /* Start a new thread, and get something handling this channel. */ 05512 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05513 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05514 decrease_call_count(); 05515 return AST_PBX_FAILED; 05516 } 05517 05518 return AST_PBX_SUCCESS; 05519 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5551 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05552 { 05553 return totalcalls; 05554 }
| 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 10502 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().
10503 { 10504 return ast_rwlock_rdlock(&con->lock); 10505 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 10484 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_hint_extension(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10485 { 10486 return ast_mutex_lock(&conlock); 10487 }
| int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
| sw | switch to register |
| 0 | success | |
| non-zero | failure |
Definition at line 6057 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().
06058 { 06059 struct ast_switch *tmp; 06060 06061 AST_RWLIST_WRLOCK(&switches); 06062 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06063 if (!strcasecmp(tmp->name, sw->name)) { 06064 AST_RWLIST_UNLOCK(&switches); 06065 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06066 return -1; 06067 } 06068 } 06069 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06070 AST_RWLIST_UNLOCK(&switches); 06071 06072 return 0; 06073 }
| 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 5051 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().
05052 { 05053 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05054 }
| int ast_str_get_hint | ( | struct ast_str ** | hint, | |
| ssize_t | hintsize, | |||
| struct ast_str ** | name, | |||
| ssize_t | namesize, | |||
| struct ast_channel * | c, | |||
| const char * | context, | |||
| const char * | exten | |||
| ) |
If an extension hint exists, return non-zero.
| hint | buffer for hint | |
| hintsize | Maximum size of hint buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
| name | buffer for name portion of hint | |
| namesize | Maximum size of name buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
| c | Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded. | |
| context | which context to look in | |
| exten | which extension to search for |
Definition at line 5006 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and ast_str_set().
Referenced by ast_str_retrieve_variable().
05007 { 05008 struct ast_exten *e = ast_hint_extension(c, context, exten); 05009 05010 if (!e) { 05011 return 0; 05012 } 05013 05014 if (hint) { 05015 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05016 } 05017 if (name) { 05018 const char *tmp = ast_get_extension_app_data(e); 05019 if (tmp) { 05020 ast_str_set(name, namesize, "%s", tmp); 05021 } 05022 } 05023 return -1; 05024 }
| const char* ast_str_retrieve_variable | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | chan, | |||
| struct varshead * | headp, | |||
| const char * | var | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| var | Variable name to retrieve. |
Definition at line 3251 of file pbx.c.
References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), ast_channel_unlock, ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_DATA_DIR, ast_config_AST_DB, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_SYSTEM_NAME, ast_config_AST_VAR_DIR, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03252 { 03253 const char not_found = '\0'; 03254 char *tmpvar; 03255 const char *ret; 03256 const char *s; /* the result */ 03257 int offset, length; 03258 int i, need_substring; 03259 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03260 03261 if (c) { 03262 ast_channel_lock(c); 03263 places[0] = &c->varshead; 03264 } 03265 /* 03266 * Make a copy of var because parse_variable_name() modifies the string. 03267 * Then if called directly, we might need to run substring() on the result; 03268 * remember this for later in 'need_substring', 'offset' and 'length' 03269 */ 03270 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03271 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03272 03273 /* 03274 * Look first into predefined variables, then into variable lists. 03275 * Variable 's' points to the result, according to the following rules: 03276 * s == ¬_found (set at the beginning) means that we did not find a 03277 * matching variable and need to look into more places. 03278 * If s != ¬_found, s is a valid result string as follows: 03279 * s = NULL if the variable does not have a value; 03280 * you typically do this when looking for an unset predefined variable. 03281 * s = workspace if the result has been assembled there; 03282 * typically done when the result is built e.g. with an snprintf(), 03283 * so we don't need to do an additional copy. 03284 * s != workspace in case we have a string, that needs to be copied 03285 * (the ast_copy_string is done once for all at the end). 03286 * Typically done when the result is already available in some string. 03287 */ 03288 s = ¬_found; /* default value */ 03289 if (c) { /* This group requires a valid channel */ 03290 /* Names with common parts are looked up a piece at a time using strncmp. */ 03291 if (!strncmp(var, "CALL", 4)) { 03292 if (!strncmp(var + 4, "ING", 3)) { 03293 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03294 ast_str_set(str, maxlen, "%d", 03295 ast_party_id_presentation(&c->caller.id)); 03296 s = ast_str_buffer(*str); 03297 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03298 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03299 s = ast_str_buffer(*str); 03300 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03301 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03302 s = ast_str_buffer(*str); 03303 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03304 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03305 s = ast_str_buffer(*str); 03306 } 03307 } 03308 } else if (!strcmp(var, "HINT")) { 03309 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03310 } else if (!strcmp(var, "HINTNAME")) { 03311 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03312 } else if (!strcmp(var, "EXTEN")) { 03313 s = c->exten; 03314 } else if (!strcmp(var, "CONTEXT")) { 03315 s = c->context; 03316 } else if (!strcmp(var, "PRIORITY")) { 03317 ast_str_set(str, maxlen, "%d", c->priority); 03318 s = ast_str_buffer(*str); 03319 } else if (!strcmp(var, "CHANNEL")) { 03320 s = ast_channel_name(c); 03321 } else if (!strcmp(var, "UNIQUEID")) { 03322 s = ast_channel_uniqueid(c); 03323 } else if (!strcmp(var, "HANGUPCAUSE")) { 03324 ast_str_set(str, maxlen, "%d", c->hangupcause); 03325 s = ast_str_buffer(*str); 03326 } 03327 } 03328 if (s == ¬_found) { /* look for more */ 03329 if (!strcmp(var, "EPOCH")) { 03330 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03331 s = ast_str_buffer(*str); 03332 } else if (!strcmp(var, "SYSTEMNAME")) { 03333 s = ast_config_AST_SYSTEM_NAME; 03334 } else if (!strcmp(var, "ASTETCDIR")) { 03335 s = ast_config_AST_CONFIG_DIR; 03336 } else if (!strcmp(var, "ASTMODDIR")) { 03337 s = ast_config_AST_MODULE_DIR; 03338 } else if (!strcmp(var, "ASTVARLIBDIR")) { 03339 s = ast_config_AST_VAR_DIR; 03340 } else if (!strcmp(var, "ASTDBDIR")) { 03341 s = ast_config_AST_DB; 03342 } else if (!strcmp(var, "ASTKEYDIR")) { 03343 s = ast_config_AST_KEY_DIR; 03344 } else if (!strcmp(var, "ASTDATADIR")) { 03345 s = ast_config_AST_DATA_DIR; 03346 } else if (!strcmp(var, "ASTAGIDIR")) { 03347 s = ast_config_AST_AGI_DIR; 03348 } else if (!strcmp(var, "ASTSPOOLDIR")) { 03349 s = ast_config_AST_SPOOL_DIR; 03350 } else if (!strcmp(var, "ASTRUNDIR")) { 03351 s = ast_config_AST_RUN_DIR; 03352 } else if (!strcmp(var, "ASTLOGDIR")) { 03353 s = ast_config_AST_LOG_DIR; 03354 } else if (!strcmp(var, "ENTITYID")) { 03355 char workspace[20]; 03356 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03357 s = workspace; 03358 } 03359 } 03360 /* if not found, look into chanvars or global vars */ 03361 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03362 struct ast_var_t *variables; 03363 if (!places[i]) 03364 continue; 03365 if (places[i] == &globals) 03366 ast_rwlock_rdlock(&globalslock); 03367 AST_LIST_TRAVERSE(places[i], variables, entries) { 03368 if (!strcasecmp(ast_var_name(variables), var)) { 03369 s = ast_var_value(variables); 03370 break; 03371 } 03372 } 03373 if (places[i] == &globals) 03374 ast_rwlock_unlock(&globalslock); 03375 } 03376 if (s == ¬_found || s == NULL) { 03377 ast_debug(5, "Result of '%s' is NULL\n", var); 03378 ret = NULL; 03379 } else { 03380 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03381 if (s != ast_str_buffer(*str)) { 03382 ast_str_set(str, maxlen, "%s", s); 03383 } 03384 ret = ast_str_buffer(*str); 03385 if (need_substring) { 03386 ret = ast_str_substring(*str, offset, length); 03387 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03388 } 03389 } 03390 03391 if (c) { 03392 ast_channel_unlock(c); 03393 } 03394 return ret; 03395 }
| void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | chan, | |||
| const char * | templ | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| templ | Variable template to expand. |
Definition at line 4069 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), do_notify(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), strreplace(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().
04070 { 04071 size_t used; 04072 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04073 }
| void ast_str_substitute_variables_full | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | c, | |||
| struct varshead * | headp, | |||
| const char * | templ, | |||
| size_t * | used | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| c | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| templ | Variable template to expand. | |
| used | Number of bytes read from the template. |
Definition at line 3890 of file pbx.c.
References ast_channel_unref, ast_debug, ast_dummy_channel_alloc(), ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().
03891 { 03892 /* Substitutes variables into buf, based on string templ */ 03893 char *cp4 = NULL; 03894 const char *whereweare; 03895 int orig_size = 0; 03896 int offset, offset2, isfunction; 03897 const char *nextvar, *nextexp, *nextthing; 03898 const char *vars, *vare; 03899 char *finalvars; 03900 int pos, brackets, needsub, len; 03901 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03902 03903 ast_str_reset(*buf); 03904 whereweare = templ; 03905 while (!ast_strlen_zero(whereweare)) { 03906 /* reset our buffer */ 03907 ast_str_reset(substr3); 03908 03909 /* Assume we're copying the whole remaining string */ 03910 pos = strlen(whereweare); 03911 nextvar = NULL; 03912 nextexp = NULL; 03913 nextthing = strchr(whereweare, '$'); 03914 if (nextthing) { 03915 switch (nextthing[1]) { 03916 case '{': 03917 nextvar = nextthing; 03918 pos = nextvar - whereweare; 03919 break; 03920 case '[': 03921 nextexp = nextthing; 03922 pos = nextexp - whereweare; 03923 break; 03924 default: 03925 pos = 1; 03926 } 03927 } 03928 03929 if (pos) { 03930 /* Copy that many bytes */ 03931 ast_str_append_substr(buf, maxlen, whereweare, pos); 03932 03933 templ += pos; 03934 whereweare += pos; 03935 } 03936 03937 if (nextvar) { 03938 /* We have a variable. Find the start and end, and determine 03939 if we are going to have to recursively call ourselves on the 03940 contents */ 03941 vars = vare = nextvar + 2; 03942 brackets = 1; 03943 needsub = 0; 03944 03945 /* Find the end of it */ 03946 while (brackets && *vare) { 03947 if ((vare[0] == '$') && (vare[1] == '{')) { 03948 needsub++; 03949 } else if (vare[0] == '{') { 03950 brackets++; 03951 } else if (vare[0] == '}') { 03952 brackets--; 03953 } else if ((vare[0] == '$') && (vare[1] == '[')) 03954 needsub++; 03955 vare++; 03956 } 03957 if (brackets) 03958 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03959 len = vare - vars - 1; 03960 03961 /* Skip totally over variable string */ 03962 whereweare += (len + 3); 03963 03964 /* Store variable name (and truncate) */ 03965 ast_str_set_substr(&substr1, 0, vars, len); 03966 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03967 03968 /* Substitute if necessary */ 03969 if (needsub) { 03970 size_t used; 03971 if (!substr2) { 03972 substr2 = ast_str_create(16); 03973 } 03974 03975 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03976 finalvars = ast_str_buffer(substr2); 03977 } else { 03978 finalvars = ast_str_buffer(substr1); 03979 } 03980 03981 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03982 if (isfunction) { 03983 /* Evaluate function */ 03984 if (c || !headp) { 03985 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03986 } else { 03987 struct varshead old; 03988 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03989 if (bogus) { 03990 memcpy(&old, &bogus->varshead, sizeof(old)); 03991 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03992 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03993 /* Don't deallocate the varshead that was passed in */ 03994 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03995 ast_channel_unref(bogus); 03996 } else { 03997 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03998 } 03999 } 04000 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04001 } else { 04002 /* Retrieve variable value */ 04003 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04004 cp4 = ast_str_buffer(substr3); 04005 } 04006 if (cp4) { 04007 ast_str_substring(substr3, offset, offset2); 04008 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04009 } 04010 } else if (nextexp) { 04011 /* We have an expression. Find the start and end, and determine 04012 if we are going to have to recursively call ourselves on the 04013 contents */ 04014 vars = vare = nextexp + 2; 04015 brackets = 1; 04016 needsub = 0; 04017 04018 /* Find the end of it */ 04019 while (brackets && *vare) { 04020 if ((vare[0] == '$') && (vare[1] == '[')) { 04021 needsub++; 04022 brackets++; 04023 vare++; 04024 } else if (vare[0] == '[') { 04025 brackets++; 04026 } else if (vare[0] == ']') { 04027 brackets--; 04028 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04029 needsub++; 04030 vare++; 04031 } 04032 vare++; 04033 } 04034 if (brackets) 04035 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04036 len = vare - vars - 1; 04037 04038 /* Skip totally over expression */ 04039 whereweare += (len + 3); 04040 04041 /* Store variable name (and truncate) */ 04042 ast_str_set_substr(&substr1, 0, vars, len); 04043 04044 /* Substitute if necessary */ 04045 if (needsub) { 04046 size_t used; 04047 if (!substr2) { 04048 substr2 = ast_str_create(16); 04049 } 04050 04051 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04052 finalvars = ast_str_buffer(substr2); 04053 } else { 04054 finalvars = ast_str_buffer(substr1); 04055 } 04056 04057 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04058 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04059 } 04060 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04061 } 04062 } 04063 *used = ast_str_strlen(*buf) - orig_size; 04064 ast_free(substr1); 04065 ast_free(substr2); 04066 ast_free(substr3); 04067 }
| void ast_str_substitute_variables_varshead | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct varshead * | headp, | |||
| const char * | templ | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| templ | Variable template to expand. |
Definition at line 4075 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().
04076 { 04077 size_t used; 04078 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04079 }
| 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 10507 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().
10508 { 10509 return ast_rwlock_unlock(&con->lock); 10510 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 10489 of file pbx.c.
References ast_mutex_unlock, and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10490 { 10491 return ast_mutex_unlock(&conlock); 10492 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Definition at line 6075 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06076 { 06077 AST_RWLIST_WRLOCK(&switches); 06078 AST_RWLIST_REMOVE(&switches, sw, list); 06079 AST_RWLIST_UNLOCK(&switches); 06080 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 10621 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().
10623 { 10624 if (!exten) 10625 return con ? con->root : NULL; 10626 else 10627 return exten->next; 10628 }
| struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
| struct ast_ignorepat * | ip | |||
| ) | [read] |
Definition at line 10654 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().
10656 { 10657 if (!ip) 10658 return con ? con->ignorepats : NULL; 10659 else 10660 return ip->next; 10661 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 10645 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().
10647 { 10648 if (!inc) 10649 return con ? con->includes : NULL; 10650 else 10651 return inc->next; 10652 }
| struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
| struct ast_sw * | sw | |||
| ) | [read] |
Definition at line 10630 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().
10632 { 10633 if (!sw) 10634 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10635 else 10636 return AST_LIST_NEXT(sw, list); 10637 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 10616 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
| struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 10639 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
10641 { 10642 return priority ? priority->peer : exten; 10643 }
| 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 10497 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().
10498 { 10499 return ast_rwlock_wrlock(&con->lock); 10500 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 10479 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
10480 { 10481 return ast_mutex_lock(&conlock); 10482 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10273 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().
10274 { 10275 struct ast_var_t *vardata; 10276 10277 ast_rwlock_wrlock(&globalslock); 10278 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10279 ast_var_delete(vardata); 10280 ast_rwlock_unlock(&globalslock); 10281 }
| const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name | |||
| ) |
Return a pointer to the value of the corresponding channel variable.
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 10035 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), manager_mixmonitor(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), setsubstate(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
10036 { 10037 struct ast_var_t *variables; 10038 const char *ret = NULL; 10039 int i; 10040 struct varshead *places[2] = { NULL, &globals }; 10041 10042 if (!name) 10043 return NULL; 10044 10045 if (chan) { 10046 ast_channel_lock(chan); 10047 places[0] = &chan->varshead; 10048 } 10049 10050 for (i = 0; i < 2; i++) { 10051 if (!places[i]) 10052 continue; 10053 if (places[i] == &globals) 10054 ast_rwlock_rdlock(&globalslock); 10055 AST_LIST_TRAVERSE(places[i], variables, entries) { 10056 if (!strcmp(name, ast_var_name(variables))) { 10057 ret = ast_var_value(variables); 10058 break; 10059 } 10060 } 10061 if (places[i] == &globals) 10062 ast_rwlock_unlock(&globalslock); 10063 if (ret) 10064 break; 10065 } 10066 10067 if (chan) 10068 ast_channel_unlock(chan); 10069 10070 return ret; 10071 }
| 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 10073 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
10074 { 10075 struct ast_var_t *newvariable; 10076 struct varshead *headp; 10077 10078 if (name[strlen(name)-1] == ')') { 10079 char *function = ast_strdupa(name); 10080 10081 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10082 ast_func_write(chan, function, value); 10083 return; 10084 } 10085 10086 if (chan) { 10087 ast_channel_lock(chan); 10088 headp = &chan->varshead; 10089 } else { 10090 ast_rwlock_wrlock(&globalslock); 10091 headp = &globals; 10092 } 10093 10094 if (value) { 10095 if (headp == &globals) 10096 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10097 newvariable = ast_var_assign(name, value); 10098 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10099 } 10100 10101 if (chan) 10102 ast_channel_unlock(chan); 10103 else 10104 ast_rwlock_unlock(&globalslock); 10105 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Definition at line 3446 of file pbx.c.
References raise_exception().
03447 { 03448 /* Priority will become 1, next time through the AUTOLOOP */ 03449 return raise_exception(chan, reason, 0); 03450 }
| int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
| struct ast_str ** | buf | |||
| ) |
Create a human-readable string, specifying all variables and their corresponding values.
| chan | Channel from which to read variables | |
| buf | Dynamic string in which to place the result (should be allocated with ast_str_create). |
Definition at line 10004 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().
10005 { 10006 struct ast_var_t *variables; 10007 const char *var, *val; 10008 int total = 0; 10009 10010 if (!chan) 10011 return 0; 10012 10013 ast_str_reset(*buf); 10014 10015 ast_channel_lock(chan); 10016 10017 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10018 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10019 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10020 ) { 10021 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10022 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10023 break; 10024 } else 10025 total++; 10026 } else 10027 break; 10028 } 10029 10030 ast_channel_unlock(chan); 10031 10032 return total; 10033 }
| int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 10165 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), strsep(), and value.
Referenced by ast_compile_ael2(), and rpt_exec().
10166 { 10167 char *name, *value, *mydata; 10168 10169 if (ast_compat_app_set) { 10170 return pbx_builtin_setvar_multiple(chan, data); 10171 } 10172 10173 if (ast_strlen_zero(data)) { 10174 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10175 return 0; 10176 } 10177 10178 mydata = ast_strdupa(data); 10179 name = strsep(&mydata, "="); 10180 value = mydata; 10181 if (!value) { 10182 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10183 return 0; 10184 } 10185 10186 if (strchr(name, ' ')) { 10187 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10188 } 10189 10190 pbx_builtin_setvar_helper(chan, name, value); 10191 10192 return 0; 10193 }
| int pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Add a variable to the channel variable stack, removing the most recently set value for the same name.
Definition at line 10107 of file pbx.c.
References ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), calendar_write_exec(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_notify(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), fax_detect_framehook(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), launch_monitor_thread(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), msg_send_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), setsubstate(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
10108 { 10109 struct ast_var_t *newvariable; 10110 struct varshead *headp; 10111 const char *nametail = name; 10112 10113 if (name[strlen(name) - 1] == ')') { 10114 char *function = ast_strdupa(name); 10115 10116 return ast_func_write(chan, function, value); 10117 } 10118 10119 if (chan) { 10120 ast_channel_lock(chan); 10121 headp = &chan->varshead; 10122 } else { 10123 ast_rwlock_wrlock(&globalslock); 10124 headp = &globals; 10125 } 10126 10127 /* For comparison purposes, we have to strip leading underscores */ 10128 if (*nametail == '_') { 10129 nametail++; 10130 if (*nametail == '_') 10131 nametail++; 10132 } 10133 10134 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10135 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10136 /* there is already such a variable, delete it */ 10137 AST_LIST_REMOVE_CURRENT(entries); 10138 ast_var_delete(newvariable); 10139 break; 10140 } 10141 } 10142 AST_LIST_TRAVERSE_SAFE_END; 10143 10144 if (value) { 10145 if (headp == &globals) 10146 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10147 newvariable = ast_var_assign(name, value); 10148 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10149 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10150 "Channel: %s\r\n" 10151 "Variable: %s\r\n" 10152 "Value: %s\r\n" 10153 "Uniqueid: %s\r\n", 10154 chan ? ast_channel_name(chan) : "none", name, value, 10155 chan ? ast_channel_uniqueid(chan) : "none"); 10156 } 10157 10158 if (chan) 10159 ast_channel_unlock(chan); 10160 else 10161 ast_rwlock_unlock(&globalslock); 10162 return 0; 10163 }
| int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
Definition at line 10195 of file pbx.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
10196 { 10197 char *data; 10198 int x; 10199 AST_DECLARE_APP_ARGS(args, 10200 AST_APP_ARG(pair)[24]; 10201 ); 10202 AST_DECLARE_APP_ARGS(pair, 10203 AST_APP_ARG(name); 10204 AST_APP_ARG(value); 10205 ); 10206 10207 if (ast_strlen_zero(vdata)) { 10208 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10209 return 0; 10210 } 10211 10212 data = ast_strdupa(vdata); 10213 AST_STANDARD_APP_ARGS(args, data); 10214 10215 for (x = 0; x < args.argc; x++) { 10216 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10217 if (pair.argc == 2) { 10218 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10219 if (strchr(pair.name, ' ')) 10220 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); 10221 } else if (!chan) { 10222 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10223 } else { 10224 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10225 } 10226 } 10227 10228 return 0; 10229 }
| 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 10283 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), pbx_builtin_gotoif(), and testtime_write().
10284 { 10285 int res; 10286 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10287 return 0; 10288 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10289 return res; 10290 } else { /* Strings are true */ 10291 return 1; 10292 } 10293 }
| int pbx_exec | ( | struct ast_channel * | c, | |
| struct ast_app * | app, | |||
| const char * | data | |||
| ) |
Execute an application.
| c | channel to execute on | |
| app | which app to execute | |
| data | the data passed into the app |
| 0 | success | |
| -1 | failure |
| c | Channel |
| app | Application |
| data | Data for execution |
Definition at line 1523 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), record_thread(), try_calling(), and tryexec_exec().
01526 { 01527 int res; 01528 struct ast_module_user *u = NULL; 01529 const char *saved_c_appl; 01530 const char *saved_c_data; 01531 01532 if (c->cdr && !ast_check_hangup(c)) 01533 ast_cdr_setapp(c->cdr, app->name, data); 01534 01535 /* save channel values */ 01536 saved_c_appl= c->appl; 01537 saved_c_data= c->data; 01538 01539 c->appl = app->name; 01540 c->data = data; 01541 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01542 01543 if (app->module) 01544 u = __ast_module_user_add(app->module, c); 01545 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01546 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01547 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01548 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01549 app->name, (char *) data); 01550 } 01551 res = app->execute(c, S_OR(data, "")); 01552 if (app->module && u) 01553 __ast_module_user_remove(app->module, u); 01554 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01555 /* restore channel values */ 01556 c->appl = saved_c_appl; 01557 c->data = saved_c_data; 01558 return res; 01559 }
| 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 2819 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_debug, ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, strsep(), switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().
02823 { 02824 int x, res; 02825 struct ast_context *tmp = NULL; 02826 struct ast_exten *e = NULL, *eroot = NULL; 02827 struct ast_include *i = NULL; 02828 struct ast_sw *sw = NULL; 02829 struct ast_exten pattern = {NULL, }; 02830 struct scoreboard score = {0, }; 02831 struct ast_str *tmpdata = NULL; 02832 02833 pattern.label = label; 02834 pattern.priority = priority; 02835 #ifdef NEED_DEBUG_HERE 02836 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02837 #endif 02838 02839 /* Initialize status if appropriate */ 02840 if (q->stacklen == 0) { 02841 q->status = STATUS_NO_CONTEXT; 02842 q->swo = NULL; 02843 q->data = NULL; 02844 q->foundcontext = NULL; 02845 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02846 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02847 return NULL; 02848 } 02849 02850 /* Check first to see if we've already been checked */ 02851 for (x = 0; x < q->stacklen; x++) { 02852 if (!strcasecmp(q->incstack[x], context)) 02853 return NULL; 02854 } 02855 02856 if (bypass) { /* bypass means we only look there */ 02857 tmp = bypass; 02858 } else { /* look in contexts */ 02859 tmp = find_context(context); 02860 if (!tmp) { 02861 return NULL; 02862 } 02863 } 02864 02865 if (q->status < STATUS_NO_EXTENSION) 02866 q->status = STATUS_NO_EXTENSION; 02867 02868 /* Do a search for matching extension */ 02869 02870 eroot = NULL; 02871 score.total_specificity = 0; 02872 score.exten = 0; 02873 score.total_length = 0; 02874 if (!tmp->pattern_tree && tmp->root_table) { 02875 create_match_char_tree(tmp); 02876 #ifdef NEED_DEBUG 02877 ast_debug(1, "Tree Created in context %s:\n", context); 02878 log_match_char_tree(tmp->pattern_tree," "); 02879 #endif 02880 } 02881 #ifdef NEED_DEBUG 02882 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02883 log_match_char_tree(tmp->pattern_tree, ":: "); 02884 #endif 02885 02886 do { 02887 if (!ast_strlen_zero(overrideswitch)) { 02888 char *osw = ast_strdupa(overrideswitch), *name; 02889 struct ast_switch *asw; 02890 ast_switch_f *aswf = NULL; 02891 char *datap; 02892 int eval = 0; 02893 02894 name = strsep(&osw, "/"); 02895 asw = pbx_findswitch(name); 02896 02897 if (!asw) { 02898 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02899 break; 02900 } 02901 02902 if (osw && strchr(osw, '$')) { 02903 eval = 1; 02904 } 02905 02906 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02907 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02908 break; 02909 } else if (eval) { 02910 /* Substitute variables now */ 02911 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02912 datap = ast_str_buffer(tmpdata); 02913 } else { 02914 datap = osw; 02915 } 02916 02917 /* equivalent of extension_match_core() at the switch level */ 02918 if (action == E_CANMATCH) 02919 aswf = asw->canmatch; 02920 else if (action == E_MATCHMORE) 02921 aswf = asw->matchmore; 02922 else /* action == E_MATCH */ 02923 aswf = asw->exists; 02924 if (!aswf) { 02925 res = 0; 02926 } else { 02927 if (chan) { 02928 ast_autoservice_start(chan); 02929 } 02930 res = aswf(chan, context, exten, priority, callerid, datap); 02931 if (chan) { 02932 ast_autoservice_stop(chan); 02933 } 02934 } 02935 if (res) { /* Got a match */ 02936 q->swo = asw; 02937 q->data = datap; 02938 q->foundcontext = context; 02939 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02940 return NULL; 02941 } 02942 } 02943 } while (0); 02944 02945 if (extenpatternmatchnew) { 02946 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02947 eroot = score.exten; 02948 02949 if (score.last_char == '!' && action == E_MATCHMORE) { 02950 /* We match an extension ending in '!'. 02951 * The decision in this case is final and is NULL (no match). 02952 */ 02953 #ifdef NEED_DEBUG_HERE 02954 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02955 #endif 02956 return NULL; 02957 } 02958 02959 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02960 q->status = STATUS_SUCCESS; 02961 #ifdef NEED_DEBUG_HERE 02962 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02963 #endif 02964 return score.canmatch_exten; 02965 } 02966 02967 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02968 if (score.node) { 02969 struct ast_exten *z = trie_find_next_match(score.node); 02970 if (z) { 02971 #ifdef NEED_DEBUG_HERE 02972 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02973 #endif 02974 } else { 02975 if (score.canmatch_exten) { 02976 #ifdef NEED_DEBUG_HERE 02977 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02978 #endif 02979 return score.canmatch_exten; 02980 } else { 02981 #ifdef NEED_DEBUG_HERE 02982 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02983 #endif 02984 } 02985 } 02986 return z; 02987 } 02988 #ifdef NEED_DEBUG_HERE 02989 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02990 #endif 02991 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02992 } 02993 02994 if (eroot) { 02995 /* found entry, now look for the right priority */ 02996 if (q->status < STATUS_NO_PRIORITY) 02997 q->status = STATUS_NO_PRIORITY; 02998 e = NULL; 02999 if (action == E_FINDLABEL && label ) { 03000 if (q->status < STATUS_NO_LABEL) 03001 q->status = STATUS_NO_LABEL; 03002 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03003 } else { 03004 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03005 } 03006 if (e) { /* found a valid match */ 03007 q->status = STATUS_SUCCESS; 03008 q->foundcontext = context; 03009 #ifdef NEED_DEBUG_HERE 03010 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03011 #endif 03012 return e; 03013 } 03014 } 03015 } else { /* the old/current default exten pattern match algorithm */ 03016 03017 /* scan the list trying to match extension and CID */ 03018 eroot = NULL; 03019 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03020 int match = extension_match_core(eroot->exten, exten, action); 03021 /* 0 on fail, 1 on match, 2 on earlymatch */ 03022 03023 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03024 continue; /* keep trying */ 03025 if (match == 2 && action == E_MATCHMORE) { 03026 /* We match an extension ending in '!'. 03027 * The decision in this case is final and is NULL (no match). 03028 */ 03029 return NULL; 03030 } 03031 /* found entry, now look for the right priority */ 03032 if (q->status < STATUS_NO_PRIORITY) 03033 q->status = STATUS_NO_PRIORITY; 03034 e = NULL; 03035 if (action == E_FINDLABEL && label ) { 03036 if (q->status < STATUS_NO_LABEL) 03037 q->status = STATUS_NO_LABEL; 03038 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03039 } else { 03040 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03041 } 03042 if (e) { /* found a valid match */ 03043 q->status = STATUS_SUCCESS; 03044 q->foundcontext = context; 03045 return e; 03046 } 03047 } 03048 } 03049 03050 /* Check alternative switches */ 03051 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03052 struct ast_switch *asw = pbx_findswitch(sw->name); 03053 ast_switch_f *aswf = NULL; 03054 char *datap; 03055 03056 if (!asw) { 03057 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03058 continue; 03059 } 03060 03061 /* Substitute variables now */ 03062 if (sw->eval) { 03063 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03064 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 03065 continue; 03066 } 03067 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03068 } 03069 03070 /* equivalent of extension_match_core() at the switch level */ 03071 if (action == E_CANMATCH) 03072 aswf = asw->canmatch; 03073 else if (action == E_MATCHMORE) 03074 aswf = asw->matchmore; 03075 else /* action == E_MATCH */ 03076 aswf = asw->exists; 03077 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03078 if (!aswf) 03079 res = 0; 03080 else { 03081 if (chan) 03082 ast_autoservice_start(chan); 03083 res = aswf(chan, context, exten, priority, callerid, datap); 03084 if (chan) 03085 ast_autoservice_stop(chan); 03086 } 03087 if (res) { /* Got a match */ 03088 q->swo = asw; 03089 q->data = datap; 03090 q->foundcontext = context; 03091 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03092 return NULL; 03093 } 03094 } 03095 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03096 /* Now try any includes we have in this context */ 03097 for (i = tmp->includes; i; i = i->next) { 03098 if (include_valid(i)) { 03099 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03100 #ifdef NEED_DEBUG_HERE 03101 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03102 #endif 03103 return e; 03104 } 03105 if (q->swo) 03106 return NULL; 03107 } 03108 } 03109 return NULL; 03110 }
| struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Look up an application.
| app | name of the app |
Definition at line 1567 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), conf_start_record(), 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(), record_thread(), try_calling(), and tryexec_exec().
01568 { 01569 struct ast_app *tmp; 01570 01571 AST_RWLIST_RDLOCK(&apps); 01572 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01573 if (!strcasecmp(tmp->name, app)) 01574 break; 01575 } 01576 AST_RWLIST_UNLOCK(&apps); 01577 01578 return tmp; 01579 }
| void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
| const char * | var, | |||
| char ** | ret, | |||
| char * | workspace, | |||
| int | workspacelen, | |||
| struct varshead * | headp | |||
| ) |
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 3240 of file pbx.c.
References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_retrieve_variable(), and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03241 { 03242 struct ast_str *str = ast_str_create(16); 03243 const char *cret; 03244 03245 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03246 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03247 *ret = cret ? workspace : NULL; 03248 ast_free(str); 03249 }
| 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 5556 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05557 { 05558 int oldval = autofallthrough; 05559 autofallthrough = newval; 05560 return oldval; 05561 }
| 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 5563 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05564 { 05565 int oldval = extenpatternmatchnew; 05566 extenpatternmatchnew = newval; 05567 return oldval; 05568 }
| 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 5570 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05571 { 05572 if (overrideswitch) { 05573 ast_free(overrideswitch); 05574 } 05575 if (!ast_strlen_zero(newval)) { 05576 overrideswitch = ast_strdup(newval); 05577 } else { 05578 overrideswitch = NULL; 05579 } 05580 }
| void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 4277 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rotate_file(), rpt_do_lstats(), rpt_exec(), substituted(), try_calling(), and write_cdr().
04278 { 04279 size_t used; 04280 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04281 }
| 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 4081 of file pbx.c.
References ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
04082 { 04083 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04084 char *cp4 = NULL; 04085 const char *whereweare, *orig_cp2 = cp2; 04086 int length, offset, offset2, isfunction; 04087 char *workspace = NULL; 04088 char *ltmp = NULL, *var = NULL; 04089 char *nextvar, *nextexp, *nextthing; 04090 char *vars, *vare; 04091 int pos, brackets, needsub, len; 04092 04093 *cp2 = 0; /* just in case nothing ends up there */ 04094 whereweare = cp1; 04095 while (!ast_strlen_zero(whereweare) && count) { 04096 /* Assume we're copying the whole remaining string */ 04097 pos = strlen(whereweare); 04098 nextvar = NULL; 04099 nextexp = NULL; 04100 nextthing = strchr(whereweare, '$'); 04101 if (nextthing) { 04102 switch (nextthing[1]) { 04103 case '{': 04104 nextvar = nextthing; 04105 pos = nextvar - whereweare; 04106 break; 04107 case '[': 04108 nextexp = nextthing; 04109 pos = nextexp - whereweare; 04110 break; 04111 default: 04112 pos = 1; 04113 } 04114 } 04115 04116 if (pos) { 04117 /* Can't copy more than 'count' bytes */ 04118 if (pos > count) 04119 pos = count; 04120 04121 /* Copy that many bytes */ 04122 memcpy(cp2, whereweare, pos); 04123 04124 count -= pos; 04125 cp2 += pos; 04126 whereweare += pos; 04127 *cp2 = 0; 04128 } 04129 04130 if (nextvar) { 04131 /* We have a variable. Find the start and end, and determine 04132 if we are going to have to recursively call ourselves on the 04133 contents */ 04134 vars = vare = nextvar + 2; 04135 brackets = 1; 04136 needsub = 0; 04137 04138 /* Find the end of it */ 04139 while (brackets && *vare) { 04140 if ((vare[0] == '$') && (vare[1] == '{')) { 04141 needsub++; 04142 } else if (vare[0] == '{') { 04143 brackets++; 04144 } else if (vare[0] == '}') { 04145 brackets--; 04146 } else if ((vare[0] == '$') && (vare[1] == '[')) 04147 needsub++; 04148 vare++; 04149 } 04150 if (brackets) 04151 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04152 len = vare - vars - 1; 04153 04154 /* Skip totally over variable string */ 04155 whereweare += (len + 3); 04156 04157 if (!var) 04158 var = alloca(VAR_BUF_SIZE); 04159 04160 /* Store variable name (and truncate) */ 04161 ast_copy_string(var, vars, len + 1); 04162 04163 /* Substitute if necessary */ 04164 if (needsub) { 04165 size_t used; 04166 if (!ltmp) 04167 ltmp = alloca(VAR_BUF_SIZE); 04168 04169 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04170 vars = ltmp; 04171 } else { 04172 vars = var; 04173 } 04174 04175 if (!workspace) 04176 workspace = alloca(VAR_BUF_SIZE); 04177 04178 workspace[0] = '\0'; 04179 04180 parse_variable_name(vars, &offset, &offset2, &isfunction); 04181 if (isfunction) { 04182 /* Evaluate function */ 04183 if (c || !headp) 04184 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04185 else { 04186 struct varshead old; 04187 struct ast_channel *c = ast_dummy_channel_alloc(); 04188 if (c) { 04189 memcpy(&old, &c->varshead, sizeof(old)); 04190 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04191 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04192 /* Don't deallocate the varshead that was passed in */ 04193 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04194 c = ast_channel_unref(c); 04195 } else { 04196 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04197 } 04198 } 04199 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04200 } else { 04201 /* Retrieve variable value */ 04202 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04203 } 04204 if (cp4) { 04205 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04206 04207 length = strlen(cp4); 04208 if (length > count) 04209 length = count; 04210 memcpy(cp2, cp4, length); 04211 count -= length; 04212 cp2 += length; 04213 *cp2 = 0; 04214 } 04215 } else if (nextexp) { 04216 /* We have an expression. Find the start and end, and determine 04217 if we are going to have to recursively call ourselves on the 04218 contents */ 04219 vars = vare = nextexp + 2; 04220 brackets = 1; 04221 needsub = 0; 04222 04223 /* Find the end of it */ 04224 while (brackets && *vare) { 04225 if ((vare[0] == '$') && (vare[1] == '[')) { 04226 needsub++; 04227 brackets++; 04228 vare++; 04229 } else if (vare[0] == '[') { 04230 brackets++; 04231 } else if (vare[0] == ']') { 04232 brackets--; 04233 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04234 needsub++; 04235 vare++; 04236 } 04237 vare++; 04238 } 04239 if (brackets) 04240 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04241 len = vare - vars - 1; 04242 04243 /* Skip totally over expression */ 04244 whereweare += (len + 3); 04245 04246 if (!var) 04247 var = alloca(VAR_BUF_SIZE); 04248 04249 /* Store variable name (and truncate) */ 04250 ast_copy_string(var, vars, len + 1); 04251 04252 /* Substitute if necessary */ 04253 if (needsub) { 04254 size_t used; 04255 if (!ltmp) 04256 ltmp = alloca(VAR_BUF_SIZE); 04257 04258 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04259 vars = ltmp; 04260 } else { 04261 vars = var; 04262 } 04263 04264 length = ast_expr(vars, cp2, count, c); 04265 04266 if (length) { 04267 ast_debug(1, "Expression result is '%s'\n", cp2); 04268 count -= length; 04269 cp2 += length; 04270 *cp2 = 0; 04271 } 04272 } 04273 } 04274 *used = cp2 - orig_cp2; 04275 }
| void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 4283 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), get_mapping_weight(), and loopback_subst().
04284 { 04285 size_t used; 04286 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04287 }
1.5.6