Core PBX routines. More...
#include "asterisk.h"#include "asterisk/_private.h"#include "asterisk/paths.h"#include <ctype.h>#include <time.h>#include <sys/time.h>#include <sys/sysinfo.h>#include "asterisk/lock.h"#include "asterisk/cli.h"#include "asterisk/pbx.h"#include "asterisk/channel.h"#include "asterisk/file.h"#include "asterisk/callerid.h"#include "asterisk/cdr.h"#include "asterisk/cel.h"#include "asterisk/config.h"#include "asterisk/term.h"#include "asterisk/manager.h"#include "asterisk/ast_expr.h"#include "asterisk/linkedlists.h"#include "asterisk/say.h"#include "asterisk/utils.h"#include "asterisk/causes.h"#include "asterisk/musiconhold.h"#include "asterisk/app.h"#include "asterisk/devicestate.h"#include "asterisk/event.h"#include "asterisk/hashtab.h"#include "asterisk/module.h"#include "asterisk/indications.h"#include "asterisk/taskprocessor.h"#include "asterisk/xmldoc.h"#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
| struct | acf_root |
| struct | app_tmp |
| struct | apps |
| struct | ast_app |
| ast_app: A registered application More... | |
| struct | ast_context |
| ast_context: An extension context More... | |
| struct | ast_custom_escalating_function |
| Extra information for an ast_custom_function holding privilege escalation information. Kept in a separate structure for ABI compatibility. More... | |
| struct | ast_exten |
| ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
| struct | ast_hint |
| Structure for dial plan hints. More... | |
| struct | ast_ignorepat |
| ast_ignorepat: Ignore patterns in dial plan More... | |
| struct | ast_include |
| ast_include: include= support in extensions.conf More... | |
| struct | ast_state_cb |
| ast_state_cb: An extension state notify register item More... | |
| struct | ast_sw |
| ast_sw: Switch statement in extensions.conf More... | |
| struct | async_stat |
| struct | cfextension_states |
| struct | dialplan_counters |
| Counters for the show dialplan manager command. More... | |
| struct | escalation_root |
| struct | fake_context |
| struct | match_char |
| match_char: forms a syntax tree for quick matching of extension patterns More... | |
| struct | pattern_node |
| struct | pbx_builtin |
| Declaration of builtin applications. More... | |
| struct | pbx_exception |
| struct | scoreboard |
| struct | statechange |
| struct | store_hint |
| struct | store_hints |
| struct | switches |
Defines | |
| #define | AST_PBX_MAX_STACK 128 |
| #define | BACKGROUND_MATCHEXTEN (1 << 2) |
| #define | BACKGROUND_NOANSWER (1 << 1) |
| #define | BACKGROUND_PLAYBACK (1 << 3) |
| #define | BACKGROUND_SKIP (1 << 0) |
| #define | BITS_PER 8 |
| #define | EXT_DATA_SIZE 8192 |
| #define | HASH_EXTENHINT_SIZE 563 |
| #define | INC_DST_OVERFLOW_CHECK |
| #define | NEW_MATCHER_CHK_MATCH |
| #define | NEW_MATCHER_RECURSE |
| #define | SAY_STUBS |
| #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 | SWITCH_DATA_LENGTH 256 |
| #define | VAR_BUF_SIZE 4096 |
| #define | VAR_HARDTRAN 3 |
| #define | VAR_NORMAL 1 |
| #define | VAR_SOFTTRAN 2 |
| #define | WAITEXTEN_DIALTONE (1 << 1) |
| #define | WAITEXTEN_MOH (1 << 0) |
Functions | |
| void | __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar) |
| int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
| Register a custom function. | |
| int | __ast_custom_function_register_escalating (struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod) |
| Register a custom function which requires escalated privileges. | |
| static int | __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async) |
| static void | __ast_internal_context_destroy (struct ast_context *con) |
| static enum ast_pbx_result | __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args) |
| static void | __init_extensionstate_buf (void) |
| static void | __init_switch_data (void) |
| static void | __init_thread_inhibit_escalations_tl (void) |
| A thread local indicating whether the current thread can run 'dangerous' dialplan functions. | |
| static int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
| static int | acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
| static int | acf_retrieve_docs (struct ast_custom_function *acf) |
| static struct match_char * | add_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly) |
| static struct match_char * | add_pattern_node (struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr) |
| static int | add_priority (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace) |
| add the extension in the priority chain. | |
| static struct match_char * | already_in_tree (struct match_char *current, char *pat, int is_pattern) |
| 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) |
| Main interface to add extensions to the list for out context. | |
| static int | ast_add_extension2_lockopt (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, int lock_context) |
| Same as ast_add_extension2() but controls the context locking. | |
| static int | ast_add_extension_nolock (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) |
| static int | ast_add_hint (struct ast_exten *e) |
| Add hint to hint list, check initial extension state. | |
| 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 *channame, 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_in) |
| 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. | |
| static int | ast_change_hint (struct ast_exten *oe, struct ast_exten *ne) |
| Change hint for an 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 *value, const char *registrar) |
| Add an ignorepat. | |
| int | ast_context_add_ignorepat2 (struct ast_context *con, const char *value, 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 *value, 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 *value, 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 *context) |
| locks the macrolock in the given given context | |
| 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 matchcallerid, const char *registrar) |
| int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked) |
| 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 included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ... | |
| int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault. | |
| 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 *context) |
| 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 *data) |
| Determine if a given extension matches a given pattern (in NXX format). | |
| int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
| Check extension state for an extension by using hint. | |
| static int | ast_extension_state2 (struct ast_exten *e) |
| Check state of extension by using hints. | |
| const char * | ast_extension_state2str (int extension_state) |
| Return extension_state as string. | |
| static int | ast_extension_state3 (struct ast_str *hint_app) |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data) |
| Add watcher for extension states. | |
| 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) |
| Add watcher for extension states with destructor. | |
| int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
| ast_extension_state_del: Remove a watcher from the callback list | |
| 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 | |
| const char * | ast_get_context_name (struct ast_context *con) |
| const char * | ast_get_context_registrar (struct ast_context *c) |
| 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) |
| struct ast_context * | ast_get_extension_context (struct ast_exten *exten) |
| const char * | ast_get_extension_label (struct ast_exten *exten) |
| int | ast_get_extension_matchcid (struct ast_exten *e) |
| const char * | ast_get_extension_name (struct ast_exten *exten) |
| int | ast_get_extension_priority (struct ast_exten *exten) |
| const char * | ast_get_extension_registrar (struct ast_exten *e) |
| int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
| Get hint for channel. | |
| const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
| const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
| const char * | ast_get_include_name (struct ast_include *inc) |
| const char * | ast_get_include_registrar (struct ast_include *i) |
| 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) |
| const char * | ast_get_switch_registrar (struct ast_sw *sw) |
| int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| 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) |
| static struct ast_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
| static struct ast_exten * | ast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten) |
| Find hint for given extension in context. | |
| 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_init (void) |
| int | ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
| static int | ast_pbx_outgoing_cdr_failed (void) |
| Function to post an empty cdr after a spool call fails. | |
| int | ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) |
| enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
| Execute the PBX in the current thread. | |
| static void * | ast_pbx_run_app (void *data) |
| run the application and free the descriptor once done | |
| 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_application2 (const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod) |
| Dynamically register a new dial plan application. | |
| int | ast_register_switch (struct ast_switch *sw) |
| Register an alternative dialplan switch. | |
| static int | ast_remove_hint (struct ast_exten *e) |
| Remove hint from extension. | |
| 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) |
| Get hint for channel. | |
| const char * | ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, 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) |
| static const char * | ast_str_substring (struct ast_str *value, int offset, int length) |
| int | ast_thread_inhibit_escalations (void) |
| Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect. | |
| int | ast_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts (void) |
| Unlocks contexts. | |
| int | ast_unregister_application (const char *app) |
| Unregister an application. | |
| void | ast_unregister_switch (struct ast_switch *sw) |
| Unregister an alternative switch. | |
| struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
| 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) |
| int | ast_wrlock_context (struct ast_context *con) |
| Write locks a given context. | |
| int | ast_wrlock_contexts (void) |
| Write locks the context list. | |
| static void * | async_wait (void *data) |
| static void | cli_match_char_tree (struct match_char *node, char *prefix, int fd) |
| static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
| collect digits from the channel into the buffer. | |
| static int | compare_char (const void *a, const void *b) |
| static char * | complete_core_show_hint (const char *line, const char *word, int pos, int state) |
| autocomplete for CLI command 'core show hint' | |
| static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
| static void | context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar) |
| static void | context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar) |
| static void | create_match_char_tree (struct ast_context *con) |
| static void | decrease_call_count (void) |
| static void | destroy_exten (struct ast_exten *e) |
| static void | destroy_hint (void *obj) |
| static void | destroy_pattern_tree (struct match_char *pattern_tree) |
| static void | destroy_state_cb (void *doomed) |
| static void | device_state_cb (const struct ast_event *event, void *unused) |
| static void | exception_store_free (void *data) |
| static int | ext_cmp (const char *left, const char *right) |
| static int | ext_cmp_exten (const char *left, const char *right) |
| static int | ext_cmp_exten_partial (const char *left, const char *right) |
| static int | ext_cmp_exten_strlen (const char *str) |
| static int | ext_cmp_pattern (const char *left, const char *right) |
| static int | ext_cmp_pattern_pos (const char **p, unsigned char *bitwise) |
| helper functions to sort extension patterns in the desired way, so that more specific patterns appear first. | |
| static int | ext_strncpy (char *dst, const char *src, int len) |
| copy a string skipping whitespace | |
| static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
| static struct ast_context * | find_context (const char *context) |
| lookup for a context with a given name, | |
| static struct ast_context * | find_context_locked (const char *context) |
| lookup for a context with a given name, | |
| static int | find_hint_by_cb_id (void *obj, void *arg, int flags) |
| Remove a watcher from the callback list. | |
| static char * | func_args (char *function) |
| return a pointer to the arguments of the function, and terminates the function name with '\0' | |
| static struct ast_exten * | get_canmatch_exten (struct match_char *node) |
| static const char * | get_pattern_node (struct pattern_node *node, const char *src, int pattern, const char *extenbuf) |
| static unsigned | get_range (char *src, int max, const char *const names[], const char *msg) |
| helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
| static void | get_timerange (struct ast_timing *i, char *times) |
| store a bitmask of valid times, one bit each 1 minute | |
| static char * | handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Send ack once. | |
| static char * | handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI support for listing chanvar's variables in a parseable way. | |
| static char * | handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI support for listing global variables in a parseable way. | |
| static char * | handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| handle_show_hint: CLI support for listing registered dial plan hint | |
| static char * | handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| handle_show_hints: CLI support for listing registered dial plan hints | |
| static char * | handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| handle_show_switches: CLI support for listing registered dial plan switches | |
| static int | handle_statechange (void *datap) |
| static char * | handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | hashtab_compare_exten_labels (const void *ah_a, const void *ah_b) |
| static int | hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b) |
| static int | hashtab_compare_extens (const void *ha_a, const void *ah_b) |
| static unsigned int | hashtab_hash_extens (const void *obj) |
| static unsigned int | hashtab_hash_labels (const void *obj) |
| static unsigned int | hashtab_hash_priority (const void *obj) |
| static int | hint_cmp (void *obj, void *arg, int flags) |
| static int | hint_hash (const void *obj, const int flags) |
| static int | hint_id_cmp (void *obj, void *arg, int flags) |
| static int | hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
| static int | include_valid (struct ast_include *i) |
| static int | increase_call_count (const struct ast_channel *c) |
| Increase call count for channel. | |
| static void | insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node) |
| static int | is_read_allowed (struct ast_custom_function *acfptr) |
| Determines whether execution of a custom function's read function is allowed. | |
| static int | is_write_allowed (struct ast_custom_function *acfptr) |
| Determines whether execution of a custom function's write function is allowed. | |
| int | load_pbx (void) |
| static int | lookup_name (const char *s, const char *const names[], int max) |
| Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
| static void | manager_dpsendack (struct mansession *s, const struct message *m) |
| Send ack once. | |
| static int | manager_show_dialplan (struct mansession *s, const struct message *m) |
| Manager listing of dial plan. | |
| static int | manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude) |
| Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not. | |
| static int | matchcid (const char *cidpattern, const char *callerid) |
| static void | new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action) |
| static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
| extract offset:length from variable name. | |
| static int | pbx_builtin_answer (struct ast_channel *, const char *) |
| static int | pbx_builtin_background (struct ast_channel *, const char *) |
| static int | pbx_builtin_busy (struct ast_channel *, const char *) |
| void | pbx_builtin_clear_globals (void) |
| static int | pbx_builtin_congestion (struct ast_channel *, const char *) |
| static int | pbx_builtin_execiftime (struct ast_channel *, const char *) |
| const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
| Return a pointer to the value of the corresponding channel variable. | |
| static int | pbx_builtin_goto (struct ast_channel *, const char *) |
| static int | pbx_builtin_gotoif (struct ast_channel *, const char *) |
| static int | pbx_builtin_gotoiftime (struct ast_channel *, const char *) |
| static int | pbx_builtin_hangup (struct ast_channel *, const char *) |
| static int | pbx_builtin_importvar (struct ast_channel *, const char *) |
| static int | pbx_builtin_incomplete (struct ast_channel *, const char *) |
| static int | pbx_builtin_noop (struct ast_channel *, const char *) |
| static int | pbx_builtin_proceeding (struct ast_channel *, const char *) |
| static int | pbx_builtin_progress (struct ast_channel *, const char *) |
| 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 *reason) |
| static int | pbx_builtin_resetcdr (struct ast_channel *, const char *) |
| static int | pbx_builtin_ringing (struct ast_channel *, const char *) |
| static int | pbx_builtin_saycharacters (struct ast_channel *, const char *) |
| static int | pbx_builtin_saydigits (struct ast_channel *, const char *) |
| static int | pbx_builtin_saynumber (struct ast_channel *, const char *) |
| static int | pbx_builtin_sayphonetic (struct ast_channel *, const char *) |
| 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. | |
| static int | pbx_builtin_setamaflags (struct ast_channel *, const char *) |
| 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 *vdata) |
| Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
| static int | pbx_builtin_wait (struct ast_channel *, const char *) |
| static int | pbx_builtin_waitexten (struct ast_channel *, const char *) |
| int | pbx_checkcondition (const char *condition) |
| Evaluate a condition. | |
| static void | pbx_destroy (struct ast_pbx *p) |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
| Execute an application. | |
| static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn) |
| The return value depends on the action:. | |
| 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) |
| Find application handle in linked list. | |
| static struct ast_switch * | pbx_findswitch (const char *sw) |
| void | pbx_live_dangerously (int new_live_dangerously) |
| Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.). | |
| static int | pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async) |
| void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
| Support for Asterisk built-in variables in the dialplan. | |
| int | pbx_set_autofallthrough (int newval) |
| int | pbx_set_extenpatternmatchnew (int newval) |
| void | pbx_set_overrideswitch (const char *newval) |
| static void | pbx_shutdown (void) |
| 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 count, size_t *used) |
| void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
| static void * | pbx_thread (void *data) |
| static void | print_app_docs (struct ast_app *aa, int fd) |
| static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
| helper function to print an extension | |
| static int | raise_exception (struct ast_channel *chan, const char *reason, int priority) |
| static int | read_escalates (const struct ast_custom_function *acf) |
| Returns true if given custom function escalates privileges on read. | |
| static void | set_ext_pri (struct ast_channel *c, const char *exten, int pri) |
| static int | show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
| static int | show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
| static int | statecbs_cmp (void *obj, void *arg, int flags) |
| static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
| takes a substring. It is ok to call with value == workspace. | |
| static int | testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value) |
| static int | thread_inhibits_escalations (void) |
| Indicates whether the current thread inhibits the execution of dangerous functions. | |
| static struct ast_exten * | trie_find_next_match (struct match_char *node) |
| static void | unload_pbx (void) |
| static void | unreference_cached_app (struct ast_app *app) |
| static void | update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node) |
| static void | wait_for_hangup (struct ast_channel *chan, const void *data) |
| static int | write_escalates (const struct ast_custom_function *acf) |
| Returns true if given custom function escalates privileges on write. | |
Variables | |
| static int | autofallthrough = 1 |
| static struct ast_app_option | background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} |
| static struct pbx_builtin | builtins [] |
| Declaration of builtin applications. | |
| static ast_mutex_t | conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
| Lock for the ast_context list. | |
| static ast_mutex_t | context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
| Lock to hold off restructuring of hints by ast_merge_contexts_and_delete. | |
| static struct ast_context * | contexts |
| static struct ast_hashtab * | contexts_table = NULL |
| static int | countcalls |
| static const char *const | days [] |
| static struct ast_event_sub * | device_state_sub |
| Subscription for device state change events. | |
| static struct ast_taskprocessor * | device_state_tps |
| static struct ast_custom_function | exception_function |
| static struct ast_datastore_info | exception_store_info |
| static int | extenpatternmatchnew = 0 |
| static struct cfextension_states | extension_states [] |
| static struct ast_threadstorage | extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } |
| static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
| static ast_rwlock_t | globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } |
| static struct ao2_container * | hints |
| static struct ast_data_handler | hints_data_provider |
| static int | live_dangerously |
| Set to true (non-zero) to globally allow all dangerous dialplan functions to run. | |
| static ast_mutex_t | maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
| static const char *const | months [] |
| static char * | overrideswitch = NULL |
| static struct ast_cli_entry | pbx_cli [] |
| static struct ast_data_entry | pbx_data_providers [] |
| static struct ast_app_option | resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} |
| static struct ao2_container * | statecbs |
| static int | stateid = 1 |
| static struct ast_threadstorage | switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } |
| static struct ast_custom_function | testtime_function |
| static struct ast_threadstorage | thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , } |
| static int | totalcalls |
| static struct ast_app_option | waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} |
Core PBX routines.
Definition in file pbx.c.
| #define AST_PBX_MAX_STACK 128 |
| #define BACKGROUND_MATCHEXTEN (1 << 2) |
Definition at line 799 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_NOANSWER (1 << 1) |
Definition at line 798 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_PLAYBACK (1 << 3) |
Definition at line 800 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_SKIP (1 << 0) |
Definition at line 797 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BITS_PER 8 |
Referenced by ext_cmp_pattern_pos().
| #define EXT_DATA_SIZE 8192 |
The speed of extension handling will likely be among the most important aspects of this PBX. The switching scheme as it exists right now isn't terribly bad (it's O(N+M), where N is the # of extensions and M is the avg # of priorities, but a constant search time here would be great ;-)
A new algorithm to do searching based on a 'compiled' pattern tree is introduced here, and shows a fairly flat (constant) search time, even for over 10000 patterns.
Also, using a hash table for context/priority name lookup can help prevent the find_extension routines from absorbing exponential cpu cycles as the number of contexts/priorities grow. I've previously tested find_extension with red-black trees, which have O(log2(n)) speed. Right now, I'm using hash tables, which do searches (ideally) in O(1) time. While these techniques do not yield much speed in small dialplans, they are worth the trouble in large dialplans.
Definition at line 786 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
| #define HASH_EXTENHINT_SIZE 563 |
Definition at line 986 of file pbx.c.
Referenced by ast_pbx_init().
| #define INC_DST_OVERFLOW_CHECK |
Referenced by get_pattern_node().
| #define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
| #define NEW_MATCHER_RECURSE |
Referenced by new_find_extension().
| #define VAR_BUF_SIZE 4096 |
Definition at line 791 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
| #define WAITEXTEN_DIALTONE (1 << 1) |
Definition at line 810 of file pbx.c.
Referenced by pbx_builtin_waitexten().
| #define WAITEXTEN_MOH (1 << 0) |
Definition at line 809 of file pbx.c.
Referenced by pbx_builtin_waitexten().
| void __ast_context_destroy | ( | struct ast_context * | list, | |
| struct ast_hashtab * | contexttab, | |||
| struct ast_context * | con, | |||
| const char * | registrar | |||
| ) |
Definition at line 9641 of file pbx.c.
References __ast_internal_context_destroy(), ast_context::alts, ast_context_remove_extension_callerid2(), ast_copy_string(), ast_debug, ast_free, ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_remove_this_object(), ast_hashtab_start_traversal(), AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_MAX_EXTENSION, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ast_context::ignorepats, ast_context::includes, ast_exten::matchcid, ast_context::name, ast_include::next, ast_ignorepat::next, ast_context::next, ast_sw::next, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_context_destroy().
09642 { 09643 struct ast_context *tmp, *tmpl=NULL; 09644 struct ast_exten *exten_item, *prio_item; 09645 09646 for (tmp = list; tmp; ) { 09647 struct ast_context *next = NULL; /* next starting point */ 09648 /* The following code used to skip forward to the next 09649 context with matching registrar, but this didn't 09650 make sense; individual priorities registrar'd to 09651 the matching registrar could occur in any context! */ 09652 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 09653 if (con) { 09654 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 09655 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 09656 if ( !strcasecmp(tmp->name, con->name) ) { 09657 break; /* found it */ 09658 } 09659 } 09660 } 09661 09662 if (!tmp) /* not found, we are done */ 09663 break; 09664 ast_wrlock_context(tmp); 09665 09666 if (registrar) { 09667 /* then search thru and remove any extens that match registrar. */ 09668 struct ast_hashtab_iter *exten_iter; 09669 struct ast_hashtab_iter *prio_iter; 09670 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 09671 struct ast_include *i, *pi = NULL, *ni = NULL; 09672 struct ast_sw *sw = NULL; 09673 09674 /* remove any ignorepats whose registrar matches */ 09675 for (ip = tmp->ignorepats; ip; ip = ipn) { 09676 ipn = ip->next; 09677 if (!strcmp(ip->registrar, registrar)) { 09678 if (ipl) { 09679 ipl->next = ip->next; 09680 ast_free(ip); 09681 continue; /* don't change ipl */ 09682 } else { 09683 tmp->ignorepats = ip->next; 09684 ast_free(ip); 09685 continue; /* don't change ipl */ 09686 } 09687 } 09688 ipl = ip; 09689 } 09690 /* remove any includes whose registrar matches */ 09691 for (i = tmp->includes; i; i = ni) { 09692 ni = i->next; 09693 if (strcmp(i->registrar, registrar) == 0) { 09694 /* remove from list */ 09695 if (pi) { 09696 pi->next = i->next; 09697 /* free include */ 09698 ast_free(i); 09699 continue; /* don't change pi */ 09700 } else { 09701 tmp->includes = i->next; 09702 /* free include */ 09703 ast_free(i); 09704 continue; /* don't change pi */ 09705 } 09706 } 09707 pi = i; 09708 } 09709 /* remove any switches whose registrar matches */ 09710 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 09711 if (strcmp(sw->registrar,registrar) == 0) { 09712 AST_LIST_REMOVE_CURRENT(list); 09713 ast_free(sw); 09714 } 09715 } 09716 AST_LIST_TRAVERSE_SAFE_END; 09717 09718 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 09719 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 09720 while ((exten_item=ast_hashtab_next(exten_iter))) { 09721 int end_traversal = 1; 09722 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 09723 while ((prio_item=ast_hashtab_next(prio_iter))) { 09724 char extension[AST_MAX_EXTENSION]; 09725 char cidmatch[AST_MAX_EXTENSION]; 09726 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 09727 continue; 09728 } 09729 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 09730 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 09731 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 09732 if (prio_item->cidmatch) { 09733 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 09734 } 09735 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1); 09736 } 09737 /* Explanation: 09738 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 09739 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 09740 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 09741 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 09742 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 09743 * free the iterator 09744 */ 09745 if (end_traversal) { 09746 ast_hashtab_end_traversal(prio_iter); 09747 } else { 09748 ast_free(prio_iter); 09749 } 09750 } 09751 ast_hashtab_end_traversal(exten_iter); 09752 } 09753 09754 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 09755 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 09756 another registrar. It's not empty if there are any extensions */ 09757 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 09758 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09759 ast_hashtab_remove_this_object(contexttab, tmp); 09760 09761 next = tmp->next; 09762 if (tmpl) 09763 tmpl->next = next; 09764 else 09765 contexts = next; 09766 /* Okay, now we're safe to let it go -- in a sense, we were 09767 ready to let it go as soon as we locked it. */ 09768 ast_unlock_context(tmp); 09769 __ast_internal_context_destroy(tmp); 09770 } else { 09771 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 09772 tmp->refcount, tmp->root); 09773 ast_unlock_context(tmp); 09774 next = tmp->next; 09775 tmpl = tmp; 09776 } 09777 } else if (con) { 09778 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 09779 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09780 ast_hashtab_remove_this_object(contexttab, tmp); 09781 09782 next = tmp->next; 09783 if (tmpl) 09784 tmpl->next = next; 09785 else 09786 contexts = next; 09787 /* Okay, now we're safe to let it go -- in a sense, we were 09788 ready to let it go as soon as we locked it. */ 09789 ast_unlock_context(tmp); 09790 __ast_internal_context_destroy(tmp); 09791 } 09792 09793 /* if we have a specific match, we are done, otherwise continue */ 09794 tmp = con ? NULL : next; 09795 } 09796 }
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 3903 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by __ast_custom_function_register_escalating(), and load_pbx().
03904 { 03905 struct ast_custom_function *cur; 03906 char tmps[80]; 03907 03908 if (!acf) { 03909 return -1; 03910 } 03911 03912 acf->mod = mod; 03913 #ifdef AST_XML_DOCS 03914 acf->docsrc = AST_STATIC_DOC; 03915 #endif 03916 03917 if (acf_retrieve_docs(acf)) { 03918 return -1; 03919 } 03920 03921 AST_RWLIST_WRLOCK(&acf_root); 03922 03923 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03924 if (!strcmp(acf->name, cur->name)) { 03925 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03926 AST_RWLIST_UNLOCK(&acf_root); 03927 return -1; 03928 } 03929 } 03930 03931 /* Store in alphabetical order */ 03932 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03933 if (strcasecmp(acf->name, cur->name) < 0) { 03934 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03935 break; 03936 } 03937 } 03938 AST_RWLIST_TRAVERSE_SAFE_END; 03939 03940 if (!cur) { 03941 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03942 } 03943 03944 AST_RWLIST_UNLOCK(&acf_root); 03945 03946 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03947 03948 return 0; 03949 }
| int __ast_custom_function_register_escalating | ( | struct ast_custom_function * | acf, | |
| enum ast_custom_function_escalation | escalation, | |||
| struct ast_module * | mod | |||
| ) |
Register a custom function which requires escalated privileges.
Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).
Definition at line 3951 of file pbx.c.
References __ast_custom_function_register(), ast_custom_escalating_function::acf, ast_calloc, AST_CFE_BOTH, AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, ast_custom_function_unregister(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_custom_escalating_function::read_escalates, and ast_custom_escalating_function::write_escalates.
03952 { 03953 struct ast_custom_escalating_function *acf_escalation = NULL; 03954 int res; 03955 03956 res = __ast_custom_function_register(acf, mod); 03957 if (res != 0) { 03958 return -1; 03959 } 03960 03961 if (escalation == AST_CFE_NONE) { 03962 /* No escalations; no need to do anything else */ 03963 return 0; 03964 } 03965 03966 acf_escalation = ast_calloc(1, sizeof(*acf_escalation)); 03967 if (!acf_escalation) { 03968 ast_custom_function_unregister(acf); 03969 return -1; 03970 } 03971 03972 acf_escalation->acf = acf; 03973 switch (escalation) { 03974 case AST_CFE_NONE: 03975 break; 03976 case AST_CFE_READ: 03977 acf_escalation->read_escalates = 1; 03978 break; 03979 case AST_CFE_WRITE: 03980 acf_escalation->write_escalates = 1; 03981 break; 03982 case AST_CFE_BOTH: 03983 acf_escalation->read_escalates = 1; 03984 acf_escalation->write_escalates = 1; 03985 break; 03986 } 03987 03988 AST_RWLIST_WRLOCK(&escalation_root); 03989 AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list); 03990 AST_RWLIST_UNLOCK(&escalation_root); 03991 03992 return 0; 03993 }
| static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int | async | |||
| ) | [static] |
Definition at line 11068 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, ast_party_id::number, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
11069 { 11070 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 11071 11072 if (!chan) 11073 return -2; 11074 11075 if (context == NULL) 11076 context = chan->context; 11077 if (exten == NULL) 11078 exten = chan->exten; 11079 11080 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 11081 if (ast_exists_extension(chan, context, exten, priority, 11082 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 11083 return goto_func(chan, context, exten, priority); 11084 else { 11085 return AST_PBX_GOTO_FAILED; 11086 } 11087 }
| static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 9593 of file pbx.c.
References ast_context::alts, ast_free, ast_hashtab_destroy(), AST_LIST_REMOVE_HEAD, ast_mutex_destroy, ast_rwlock_destroy, destroy_exten(), destroy_pattern_tree(), el, ast_context::ignorepats, ast_context::includes, ast_context::lock, ast_context::macrolock, ast_exten::next, ast_ignorepat::next, ast_include::next, ast_context::pattern_tree, ast_exten::peer, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().
09594 { 09595 struct ast_include *tmpi; 09596 struct ast_sw *sw; 09597 struct ast_exten *e, *el, *en; 09598 struct ast_ignorepat *ipi; 09599 struct ast_context *tmp = con; 09600 09601 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 09602 struct ast_include *tmpil = tmpi; 09603 tmpi = tmpi->next; 09604 ast_free(tmpil); 09605 } 09606 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 09607 struct ast_ignorepat *ipl = ipi; 09608 ipi = ipi->next; 09609 ast_free(ipl); 09610 } 09611 if (tmp->registrar) 09612 ast_free(tmp->registrar); 09613 09614 /* destroy the hash tabs */ 09615 if (tmp->root_table) { 09616 ast_hashtab_destroy(tmp->root_table, 0); 09617 } 09618 /* and destroy the pattern tree */ 09619 if (tmp->pattern_tree) 09620 destroy_pattern_tree(tmp->pattern_tree); 09621 09622 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 09623 ast_free(sw); 09624 for (e = tmp->root; e;) { 09625 for (en = e->peer; en;) { 09626 el = en; 09627 en = en->peer; 09628 destroy_exten(el); 09629 } 09630 el = e; 09631 e = e->next; 09632 destroy_exten(el); 09633 } 09634 tmp->root = NULL; 09635 ast_rwlock_destroy(&tmp->lock); 09636 ast_mutex_destroy(&tmp->macrolock); 09637 ast_free(tmp); 09638 }
| static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) | [static] |
Definition at line 5426 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_copy_string(), ast_debug, ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_free, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_opt_end_cdr_before_h_exten, AST_PBX_ERROR, AST_PBX_INCOMPLETE, ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verb, autofallthrough, ast_channel::caller, ast_channel::cdr, collect_digits(), ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_pbx_args::no_hangup_chan, ast_party_id::number, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, raise_exception(), ast_pbx::rtimeoutms, S_COR, set_ext_pri(), status, ast_party_number::str, ast_party_number::valid, and ast_channel::whentohangup.
Referenced by ast_pbx_run_args(), and pbx_thread().
05428 { 05429 int found = 0; /* set if we find at least one match */ 05430 int res = 0; 05431 int autoloopflag; 05432 int error = 0; /* set an error conditions */ 05433 05434 /* A little initial setup here */ 05435 if (c->pbx) { 05436 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 05437 /* XXX and now what ? */ 05438 ast_free(c->pbx); 05439 } 05440 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 05441 return -1; 05442 /* Set reasonable defaults */ 05443 c->pbx->rtimeoutms = 10000; 05444 c->pbx->dtimeoutms = 5000; 05445 05446 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 05447 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 05448 05449 /* Start by trying whatever the channel is set to */ 05450 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05451 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05452 /* If not successful fall back to 's' */ 05453 ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority); 05454 /* XXX the original code used the existing priority in the call to 05455 * ast_exists_extension(), and reset it to 1 afterwards. 05456 * I believe the correct thing is to set it to 1 immediately. 05457 */ 05458 set_ext_pri(c, "s", 1); 05459 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05460 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05461 /* JK02: And finally back to default if everything else failed */ 05462 ast_verb(2, "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority); 05463 ast_copy_string(c->context, "default", sizeof(c->context)); 05464 } 05465 } 05466 ast_channel_lock(c); 05467 if (c->cdr) { 05468 /* allow CDR variables that have been collected after channel was created to be visible during call */ 05469 ast_cdr_update(c); 05470 } 05471 ast_channel_unlock(c); 05472 for (;;) { 05473 char dst_exten[256]; /* buffer to accumulate digits */ 05474 int pos = 0; /* XXX should check bounds */ 05475 int digit = 0; 05476 int invalid = 0; 05477 int timeout = 0; 05478 05479 /* No digits pressed yet */ 05480 dst_exten[pos] = '\0'; 05481 05482 /* loop on priorities in this context/exten */ 05483 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05484 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05485 &found, 1))) { 05486 if (!ast_check_hangup(c)) { 05487 ++c->priority; 05488 continue; 05489 } 05490 05491 /* Check softhangup flags. */ 05492 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05493 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05494 continue; 05495 } 05496 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05497 if (ast_exists_extension(c, c->context, "T", 1, 05498 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05499 set_ext_pri(c, "T", 1); 05500 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05501 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05502 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05503 continue; 05504 } else if (ast_exists_extension(c, c->context, "e", 1, 05505 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05506 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05507 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05508 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05509 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05510 continue; 05511 } 05512 05513 /* Call timed out with no special extension to jump to. */ 05514 error = 1; 05515 break; 05516 } 05517 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 05518 c->exten, c->priority); 05519 error = 1; 05520 break; 05521 } /* end while - from here on we can use 'break' to go out */ 05522 if (found && res) { 05523 /* Something bad happened, or a hangup has been requested. */ 05524 if (strchr("0123456789ABCDEF*#", res)) { 05525 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 05526 pos = 0; 05527 dst_exten[pos++] = digit = res; 05528 dst_exten[pos] = '\0'; 05529 } else if (res == AST_PBX_INCOMPLETE) { 05530 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05531 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05532 05533 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 05534 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 05535 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05536 invalid = 1; 05537 } else { 05538 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 05539 digit = 1; 05540 pos = strlen(dst_exten); 05541 } 05542 } else { 05543 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05544 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05545 05546 if ((res == AST_PBX_ERROR) 05547 && ast_exists_extension(c, c->context, "e", 1, 05548 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05549 /* if we are already on the 'e' exten, don't jump to it again */ 05550 if (!strcmp(c->exten, "e")) { 05551 ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name); 05552 error = 1; 05553 } else { 05554 raise_exception(c, "ERROR", 1); 05555 continue; 05556 } 05557 } 05558 05559 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05560 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05561 continue; 05562 } 05563 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05564 if (ast_exists_extension(c, c->context, "T", 1, 05565 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05566 set_ext_pri(c, "T", 1); 05567 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05568 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05569 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05570 continue; 05571 } else if (ast_exists_extension(c, c->context, "e", 1, 05572 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05573 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05574 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05575 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05576 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05577 continue; 05578 } 05579 /* Call timed out with no special extension to jump to. */ 05580 } 05581 ast_channel_lock(c); 05582 if (c->cdr) { 05583 ast_cdr_update(c); 05584 } 05585 ast_channel_unlock(c); 05586 error = 1; 05587 break; 05588 } 05589 } 05590 if (error) 05591 break; 05592 05593 /*!\note 05594 * We get here on a failure of some kind: non-existing extension or 05595 * hangup. We have options, here. We can either catch the failure 05596 * and continue, or we can drop out entirely. */ 05597 05598 if (invalid 05599 || (ast_strlen_zero(dst_exten) && 05600 !ast_exists_extension(c, c->context, c->exten, 1, 05601 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) { 05602 /*!\note 05603 * If there is no match at priority 1, it is not a valid extension anymore. 05604 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 05605 * neither exist. 05606 */ 05607 if (ast_exists_extension(c, c->context, "i", 1, 05608 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05609 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 05610 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 05611 set_ext_pri(c, "i", 1); 05612 } else if (ast_exists_extension(c, c->context, "e", 1, 05613 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05614 raise_exception(c, "INVALID", 1); 05615 } else { 05616 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 05617 c->name, c->exten, c->context); 05618 error = 1; /* we know what to do with it */ 05619 break; 05620 } 05621 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05622 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 05623 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05624 } else { /* keypress received, get more digits for a full extension */ 05625 int waittime = 0; 05626 if (digit) 05627 waittime = c->pbx->dtimeoutms; 05628 else if (!autofallthrough) 05629 waittime = c->pbx->rtimeoutms; 05630 if (!waittime) { 05631 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 05632 if (!status) 05633 status = "UNKNOWN"; 05634 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 05635 if (!strcasecmp(status, "CONGESTION")) 05636 res = pbx_builtin_congestion(c, "10"); 05637 else if (!strcasecmp(status, "CHANUNAVAIL")) 05638 res = pbx_builtin_congestion(c, "10"); 05639 else if (!strcasecmp(status, "BUSY")) 05640 res = pbx_builtin_busy(c, "10"); 05641 error = 1; /* XXX disable message */ 05642 break; /* exit from the 'for' loop */ 05643 } 05644 05645 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 05646 break; 05647 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 05648 timeout = 1; 05649 if (!timeout 05650 && ast_exists_extension(c, c->context, dst_exten, 1, 05651 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 05652 set_ext_pri(c, dst_exten, 1); 05653 } else { 05654 /* No such extension */ 05655 if (!timeout && !ast_strlen_zero(dst_exten)) { 05656 /* An invalid extension */ 05657 if (ast_exists_extension(c, c->context, "i", 1, 05658 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05659 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 05660 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 05661 set_ext_pri(c, "i", 1); 05662 } else if (ast_exists_extension(c, c->context, "e", 1, 05663 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05664 raise_exception(c, "INVALID", 1); 05665 } else { 05666 ast_log(LOG_WARNING, 05667 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", 05668 dst_exten, c->context); 05669 found = 1; /* XXX disable message */ 05670 break; 05671 } 05672 } else { 05673 /* A simple timeout */ 05674 if (ast_exists_extension(c, c->context, "t", 1, 05675 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05676 ast_verb(3, "Timeout on %s\n", c->name); 05677 set_ext_pri(c, "t", 1); 05678 } else if (ast_exists_extension(c, c->context, "e", 1, 05679 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05680 raise_exception(c, "RESPONSETIMEOUT", 1); 05681 } else { 05682 ast_log(LOG_WARNING, 05683 "Timeout, but no rule 't' or 'e' in context '%s'\n", 05684 c->context); 05685 found = 1; /* XXX disable message */ 05686 break; 05687 } 05688 } 05689 } 05690 ast_channel_lock(c); 05691 if (c->cdr) { 05692 ast_verb(2, "CDR updated on %s\n",c->name); 05693 ast_cdr_update(c); 05694 } 05695 ast_channel_unlock(c); 05696 } 05697 } 05698 05699 if (!found && !error) { 05700 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 05701 } 05702 05703 if (!args || !args->no_hangup_chan) { 05704 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 05705 } 05706 05707 if ((!args || !args->no_hangup_chan) 05708 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 05709 && ast_exists_extension(c, c->context, "h", 1, 05710 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05711 set_ext_pri(c, "h", 1); 05712 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 05713 ast_cdr_end(c->cdr); 05714 } 05715 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05716 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05717 &found, 1)) == 0) { 05718 c->priority++; 05719 } 05720 if (found && res) { 05721 /* Something bad happened, or a hangup has been requested. */ 05722 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05723 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05724 } 05725 } 05726 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 05727 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 05728 pbx_destroy(c->pbx); 05729 c->pbx = NULL; 05730 05731 if (!args || !args->no_hangup_chan) { 05732 ast_hangup(c); 05733 } 05734 05735 return 0; 05736 }
| static void __init_extensionstate_buf | ( | void | ) | [static] |
| static void __init_switch_data | ( | void | ) | [static] |
| static void __init_thread_inhibit_escalations_tl | ( | void | ) | [static] |
| static int _extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 2697 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, ext_cmp_exten(), ext_cmp_exten_partial(), ext_cmp_exten_strlen(), ext_cmp_pattern(), LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02698 { 02699 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02700 02701 #ifdef NEED_DEBUG_HERE 02702 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02703 #endif 02704 02705 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02706 int lp = ext_cmp_exten_strlen(pattern); 02707 int ld = ext_cmp_exten_strlen(data); 02708 02709 if (lp < ld) { /* pattern too short, cannot match */ 02710 #ifdef NEED_DEBUG_HERE 02711 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02712 #endif 02713 return 0; 02714 } 02715 /* depending on the mode, accept full or partial match or both */ 02716 if (mode == E_MATCH) { 02717 #ifdef NEED_DEBUG_HERE 02718 ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data); 02719 #endif 02720 return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */ 02721 } 02722 if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */ 02723 #ifdef NEED_DEBUG_HERE 02724 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02725 #endif 02726 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02727 } else { 02728 #ifdef NEED_DEBUG_HERE 02729 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02730 #endif 02731 return 0; 02732 } 02733 } 02734 if (mode == E_MATCH && data[0] == '_') { 02735 /* 02736 * XXX It is bad design that we don't know if we should be 02737 * comparing data and pattern as patterns or comparing data if 02738 * it conforms to pattern when the function is called. First, 02739 * assume they are both patterns. If they don't match then try 02740 * to see if data conforms to the given pattern. 02741 * 02742 * note: if this test is left out, then _x. will not match _x. !!! 02743 */ 02744 #ifdef NEED_DEBUG_HERE 02745 ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data); 02746 #endif 02747 if (!ext_cmp_pattern(pattern + 1, data + 1)) { 02748 #ifdef NEED_DEBUG_HERE 02749 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02750 #endif 02751 return 1; 02752 } 02753 } 02754 02755 ++pattern; /* skip leading _ */ 02756 /* 02757 * XXX below we stop at '/' which is a separator for the CID info. However we should 02758 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02759 */ 02760 for (;;) { 02761 const char *end; 02762 02763 /* Ignore '-' chars as eye candy fluff. */ 02764 while (*data == '-') { 02765 ++data; 02766 } 02767 while (*pattern == '-') { 02768 ++pattern; 02769 } 02770 if (!*data || !*pattern || *pattern == '/') { 02771 break; 02772 } 02773 02774 switch (*pattern) { 02775 case '[': /* a range */ 02776 ++pattern; 02777 end = strchr(pattern, ']'); /* XXX should deal with escapes ? */ 02778 if (!end) { 02779 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02780 return 0; /* unconditional failure */ 02781 } 02782 if (pattern == end) { 02783 /* Ignore empty character sets. */ 02784 ++pattern; 02785 continue; 02786 } 02787 for (; pattern < end; ++pattern) { 02788 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02789 if (*data >= pattern[0] && *data <= pattern[2]) 02790 break; /* match found */ 02791 else { 02792 pattern += 2; /* skip a total of 3 chars */ 02793 continue; 02794 } 02795 } else if (*data == pattern[0]) 02796 break; /* match found */ 02797 } 02798 if (pattern >= end) { 02799 #ifdef NEED_DEBUG_HERE 02800 ast_log(LOG_NOTICE,"return (0) when pattern>=end\n"); 02801 #endif 02802 return 0; 02803 } 02804 pattern = end; /* skip and continue */ 02805 break; 02806 case 'n': 02807 case 'N': 02808 if (*data < '2' || *data > '9') { 02809 #ifdef NEED_DEBUG_HERE 02810 ast_log(LOG_NOTICE,"return (0) N is not matched\n"); 02811 #endif 02812 return 0; 02813 } 02814 break; 02815 case 'x': 02816 case 'X': 02817 if (*data < '0' || *data > '9') { 02818 #ifdef NEED_DEBUG_HERE 02819 ast_log(LOG_NOTICE,"return (0) X is not matched\n"); 02820 #endif 02821 return 0; 02822 } 02823 break; 02824 case 'z': 02825 case 'Z': 02826 if (*data < '1' || *data > '9') { 02827 #ifdef NEED_DEBUG_HERE 02828 ast_log(LOG_NOTICE,"return (0) Z is not matched\n"); 02829 #endif 02830 return 0; 02831 } 02832 break; 02833 case '.': /* Must match, even with more digits */ 02834 #ifdef NEED_DEBUG_HERE 02835 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02836 #endif 02837 return 1; 02838 case '!': /* Early match */ 02839 #ifdef NEED_DEBUG_HERE 02840 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02841 #endif 02842 return 2; 02843 default: 02844 if (*data != *pattern) { 02845 #ifdef NEED_DEBUG_HERE 02846 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02847 #endif 02848 return 0; 02849 } 02850 break; 02851 } 02852 ++data; 02853 ++pattern; 02854 } 02855 if (*data) /* data longer than pattern, no match */ { 02856 #ifdef NEED_DEBUG_HERE 02857 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02858 #endif 02859 return 0; 02860 } 02861 02862 /* 02863 * match so far, but ran off the end of data. 02864 * Depending on what is next, determine match or not. 02865 */ 02866 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02867 #ifdef NEED_DEBUG_HERE 02868 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02869 #endif 02870 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02871 } else if (*pattern == '!') { /* early match */ 02872 #ifdef NEED_DEBUG_HERE 02873 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02874 #endif 02875 return 2; 02876 } else { /* partial match */ 02877 #ifdef NEED_DEBUG_HERE 02878 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02879 #endif 02880 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02881 } 02882 }
| static int acf_exception_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 3584 of file pbx.c.
References ast_channel_datastore_find(), ast_copy_string(), pbx_exception::context, ast_datastore::data, exception_store_info, pbx_exception::exten, pbx_exception::priority, and pbx_exception::reason.
03585 { 03586 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03587 struct pbx_exception *exception = NULL; 03588 if (!ds || !ds->data) 03589 return -1; 03590 exception = ds->data; 03591 if (!strcasecmp(data, "REASON")) 03592 ast_copy_string(buf, exception->reason, buflen); 03593 else if (!strcasecmp(data, "CONTEXT")) 03594 ast_copy_string(buf, exception->context, buflen); 03595 else if (!strncasecmp(data, "EXTEN", 5)) 03596 ast_copy_string(buf, exception->exten, buflen); 03597 else if (!strcasecmp(data, "PRIORITY")) 03598 snprintf(buf, buflen, "%d", exception->priority); 03599 else 03600 return -1; 03601 return 0; 03602 }
| static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3858 of file pbx.c.
References ast_free, ast_module_name(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, and synopsis.
Referenced by __ast_custom_function_register().
03859 { 03860 #ifdef AST_XML_DOCS 03861 char *tmpxml; 03862 03863 /* Let's try to find it in the Documentation XML */ 03864 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03865 return 0; 03866 } 03867 03868 if (ast_string_field_init(acf, 128)) { 03869 return -1; 03870 } 03871 03872 /* load synopsis */ 03873 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); 03874 ast_string_field_set(acf, synopsis, tmpxml); 03875 ast_free(tmpxml); 03876 03877 /* load description */ 03878 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); 03879 ast_string_field_set(acf, desc, tmpxml); 03880 ast_free(tmpxml); 03881 03882 /* load syntax */ 03883 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod)); 03884 ast_string_field_set(acf, syntax, tmpxml); 03885 ast_free(tmpxml); 03886 03887 /* load arguments */ 03888 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod)); 03889 ast_string_field_set(acf, arguments, tmpxml); 03890 ast_free(tmpxml); 03891 03892 /* load seealso */ 03893 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod)); 03894 ast_string_field_set(acf, seealso, tmpxml); 03895 ast_free(tmpxml); 03896 03897 acf->docsrc = AST_XML_DOC; 03898 #endif 03899 03900 return 0; 03901 }
| static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
| struct ast_exten * | e1, | |||
| int | findonly | |||
| ) | [static, read] |
Definition at line 2180 of file pbx.c.
References add_pattern_node(), already_in_tree(), ARRAY_LEN, ast_copy_string(), ast_log(), pattern_node::buf, ast_exten::cidmatch, match_char::deleted, match_char::exten, ast_exten::exten, get_pattern_node(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_exten::matchcid, match_char::next_char, and ast_context::pattern_tree.
Referenced by add_priority(), ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().
02181 { 02182 struct match_char *m1 = NULL; 02183 struct match_char *m2 = NULL; 02184 struct match_char **m0; 02185 const char *pos; 02186 int already; 02187 int pattern = 0; 02188 int idx_cur; 02189 int idx_next; 02190 char extenbuf[512]; 02191 struct pattern_node pat_node[2]; 02192 02193 if (e1->matchcid) { 02194 if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) { 02195 ast_log(LOG_ERROR, 02196 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", 02197 e1->exten, e1->cidmatch); 02198 return NULL; 02199 } 02200 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */ 02201 } else { 02202 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 02203 } 02204 02205 #ifdef NEED_DEBUG 02206 ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf); 02207 #endif 02208 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 02209 m0 = &con->pattern_tree; 02210 already = 1; 02211 02212 pos = extenbuf; 02213 if (*pos == '_') { 02214 pattern = 1; 02215 ++pos; 02216 } 02217 idx_cur = 0; 02218 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf); 02219 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) { 02220 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node); 02221 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf); 02222 02223 /* See about adding node to tree. */ 02224 m2 = NULL; 02225 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern)) 02226 && m2->next_char) { 02227 if (!pat_node[idx_next].buf[0]) { 02228 /* 02229 * This is the end of the pattern, but not the end of the tree. 02230 * Mark this node with the exten... a shorter pattern might win 02231 * if the longer one doesn't match. 02232 */ 02233 if (findonly) { 02234 return m2; 02235 } 02236 if (m2->exten) { 02237 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02238 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02239 } 02240 m2->exten = e1; 02241 m2->deleted = 0; 02242 } 02243 m1 = m2->next_char; /* m1 points to the node to compare against */ 02244 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02245 } else { /* not already OR not m2 OR nor m2->next_char */ 02246 if (m2) { 02247 if (findonly) { 02248 return m2; 02249 } 02250 m1 = m2; /* while m0 stays the same */ 02251 } else { 02252 if (findonly) { 02253 return m1; 02254 } 02255 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0); 02256 if (!m1) { /* m1 is the node just added */ 02257 return NULL; 02258 } 02259 m0 = &m1->next_char; 02260 } 02261 if (!pat_node[idx_next].buf[0]) { 02262 if (m2 && m2->exten) { 02263 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02264 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02265 } 02266 m1->deleted = 0; 02267 m1->exten = e1; 02268 } 02269 02270 /* The 'already' variable is a mini-optimization designed to make it so that we 02271 * don't have to call already_in_tree when we know it will return false. 02272 */ 02273 already = 0; 02274 } 02275 } 02276 return m1; 02277 }
| static struct match_char* add_pattern_node | ( | struct ast_context * | con, | |
| struct match_char * | current, | |||
| const struct pattern_node * | pattern, | |||
| int | is_pattern, | |||
| int | already, | |||
| struct match_char ** | nextcharptr | |||
| ) | [static, read] |
Definition at line 1982 of file pbx.c.
References ast_calloc, pattern_node::buf, insert_in_next_chars_alt_char_list(), match_char::is_pattern, match_char::next_char, ast_context::pattern_tree, pattern_node::specif, match_char::specificity, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01983 { 01984 struct match_char *m; 01985 01986 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) { 01987 return NULL; 01988 } 01989 01990 /* strcpy is safe here since we know its size and have allocated 01991 * just enough space for when we allocated m 01992 */ 01993 strcpy(m->x, pattern->buf); 01994 01995 /* the specificity scores are the same as used in the old 01996 pattern matcher. */ 01997 m->is_pattern = is_pattern; 01998 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') { 01999 m->specificity = 0x0832; 02000 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') { 02001 m->specificity = 0x0931; 02002 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') { 02003 m->specificity = 0x0a30; 02004 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') { 02005 m->specificity = 0x18000; 02006 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') { 02007 m->specificity = 0x28000; 02008 } else { 02009 m->specificity = pattern->specif; 02010 } 02011 02012 if (!con->pattern_tree) { 02013 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 02014 } else { 02015 if (already) { /* switch to the new regime (traversing vs appending)*/ 02016 insert_in_next_chars_alt_char_list(nextcharptr, m); 02017 } else { 02018 insert_in_next_chars_alt_char_list(¤t->next_char, m); 02019 } 02020 } 02021 02022 return m; 02023 }
| static int add_priority | ( | struct ast_context * | con, | |
| struct ast_exten * | tmp, | |||
| struct ast_exten * | el, | |||
| struct ast_exten * | e, | |||
| int | replace | |||
| ) | [static] |
add the extension in the priority chain.
| 0 | on success. | |
| -1 | on failure. |
Definition at line 8779 of file pbx.c.
References add_exten_to_pattern_tree(), ast_add_hint(), ast_change_hint(), ast_free, ast_hashtab_insert_safe(), ast_hashtab_remove_object_via_lookup(), ast_log(), ast_exten::data, ast_exten::datad, match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_WARNING, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by ast_add_extension2_lockopt().
08781 { 08782 struct ast_exten *ep; 08783 struct ast_exten *eh=e; 08784 int repeated_label = 0; /* Track if this label is a repeat, assume no. */ 08785 08786 for (ep = NULL; e ; ep = e, e = e->peer) { 08787 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) { 08788 if (strcmp(e->exten, tmp->exten)) { 08789 ast_log(LOG_WARNING, 08790 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n", 08791 tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority); 08792 } else { 08793 ast_log(LOG_WARNING, 08794 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n", 08795 tmp->exten, tmp->priority, con->name, tmp->label, e->priority); 08796 } 08797 repeated_label = 1; 08798 } 08799 if (e->priority >= tmp->priority) { 08800 break; 08801 } 08802 } 08803 08804 if (repeated_label) { /* Discard the label since it's a repeat. */ 08805 tmp->label = NULL; 08806 } 08807 08808 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 08809 ast_hashtab_insert_safe(eh->peer_table, tmp); 08810 08811 if (tmp->label) { 08812 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08813 } 08814 ep->peer = tmp; 08815 return 0; /* success */ 08816 } 08817 if (e->priority == tmp->priority) { 08818 /* Can't have something exactly the same. Is this a 08819 replacement? If so, replace, otherwise, bonk. */ 08820 if (!replace) { 08821 if (strcmp(e->exten, tmp->exten)) { 08822 ast_log(LOG_WARNING, 08823 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n", 08824 tmp->exten, tmp->priority, con->name, e->exten); 08825 } else { 08826 ast_log(LOG_WARNING, 08827 "Unable to register extension '%s' priority %d in '%s', already in use\n", 08828 tmp->exten, tmp->priority, con->name); 08829 } 08830 if (tmp->datad) { 08831 tmp->datad(tmp->data); 08832 /* if you free this, null it out */ 08833 tmp->data = NULL; 08834 } 08835 08836 ast_free(tmp); 08837 return -1; 08838 } 08839 /* we are replacing e, so copy the link fields and then update 08840 * whoever pointed to e to point to us 08841 */ 08842 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 08843 tmp->peer = e->peer; /* always meaningful */ 08844 if (ep) { /* We're in the peer list, just insert ourselves */ 08845 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 08846 08847 if (e->label) { 08848 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 08849 } 08850 08851 ast_hashtab_insert_safe(eh->peer_table,tmp); 08852 if (tmp->label) { 08853 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 08854 } 08855 08856 ep->peer = tmp; 08857 } else if (el) { /* We're the first extension. Take over e's functions */ 08858 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08859 tmp->peer_table = e->peer_table; 08860 tmp->peer_label_table = e->peer_label_table; 08861 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 08862 ast_hashtab_insert_safe(tmp->peer_table,tmp); 08863 if (e->label) { 08864 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08865 } 08866 if (tmp->label) { 08867 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08868 } 08869 08870 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08871 ast_hashtab_insert_safe(con->root_table, tmp); 08872 el->next = tmp; 08873 /* The pattern trie points to this exten; replace the pointer, 08874 and all will be well */ 08875 if (x) { /* if the trie isn't formed yet, don't sweat this */ 08876 if (x->exten) { /* this test for safety purposes */ 08877 x->exten = tmp; /* replace what would become a bad pointer */ 08878 } else { 08879 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08880 } 08881 } 08882 } else { /* We're the very first extension. */ 08883 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08884 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08885 ast_hashtab_insert_safe(con->root_table, tmp); 08886 tmp->peer_table = e->peer_table; 08887 tmp->peer_label_table = e->peer_label_table; 08888 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 08889 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08890 if (e->label) { 08891 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08892 } 08893 if (tmp->label) { 08894 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08895 } 08896 08897 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08898 ast_hashtab_insert_safe(con->root_table, tmp); 08899 con->root = tmp; 08900 /* The pattern trie points to this exten; replace the pointer, 08901 and all will be well */ 08902 if (x) { /* if the trie isn't formed yet; no problem */ 08903 if (x->exten) { /* this test for safety purposes */ 08904 x->exten = tmp; /* replace what would become a bad pointer */ 08905 } else { 08906 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08907 } 08908 } 08909 } 08910 if (tmp->priority == PRIORITY_HINT) 08911 ast_change_hint(e,tmp); 08912 /* Destroy the old one */ 08913 if (e->datad) 08914 e->datad(e->data); 08915 ast_free(e); 08916 } else { /* Slip ourselves in just before e */ 08917 tmp->peer = e; 08918 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 08919 if (ep) { /* Easy enough, we're just in the peer list */ 08920 if (tmp->label) { 08921 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08922 } 08923 ast_hashtab_insert_safe(eh->peer_table, tmp); 08924 ep->peer = tmp; 08925 } else { /* we are the first in some peer list, so link in the ext list */ 08926 tmp->peer_table = e->peer_table; 08927 tmp->peer_label_table = e->peer_label_table; 08928 e->peer_table = 0; 08929 e->peer_label_table = 0; 08930 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08931 if (tmp->label) { 08932 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08933 } 08934 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08935 ast_hashtab_insert_safe(con->root_table, tmp); 08936 if (el) 08937 el->next = tmp; /* in the middle... */ 08938 else 08939 con->root = tmp; /* ... or at the head */ 08940 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 08941 } 08942 /* And immediately return success. */ 08943 if (tmp->priority == PRIORITY_HINT) { 08944 ast_add_hint(tmp); 08945 } 08946 } 08947 return 0; 08948 }
| static struct match_char * already_in_tree | ( | struct match_char * | current, | |
| char * | pat, | |||
| int | is_pattern | |||
| ) | [static, read] |
Definition at line 1920 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01921 { 01922 struct match_char *t; 01923 01924 if (!current) { 01925 return 0; 01926 } 01927 01928 for (t = current; t; t = t->alt_char) { 01929 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01930 return t; 01931 } 01932 } 01933 01934 return 0; 01935 }
| int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5884 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05885 { 05886 return countcalls; 05887 }
| 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 8614 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().
08617 { 08618 int ret = -1; 08619 struct ast_context *c; 08620 08621 c = find_context_locked(context); 08622 if (c) { 08623 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08624 application, data, datad, registrar); 08625 ast_unlock_contexts(); 08626 } 08627 08628 return ret; 08629 }
| 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 | |||
| ) |
Main interface to add extensions to the list for out context.
Add an extension to an extension context, this time with an ast_context *.
We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.
The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.
EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set
Definition at line 8975 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
08979 { 08980 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08981 application, data, datad, registrar, 1); 08982 }
| static int ast_add_extension2_lockopt | ( | 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, | |||
| int | lock_context | |||
| ) | [static] |
Same as ast_add_extension2() but controls the context locking.
Does all the work of ast_add_extension2, but adds an arg to determine if context locking should be done.
Definition at line 8991 of file pbx.c.
References add_exten_to_pattern_tree(), add_priority(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, AST_EXT_MATCHCID_OFF, AST_EXT_MATCHCID_ON, ast_hashtab_create(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_channel::context, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_channel::exten, hashtab_compare_exten_labels(), hashtab_compare_exten_numbers(), hashtab_compare_extens(), hashtab_hash_extens(), hashtab_hash_labels(), hashtab_hash_priority(), ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::next, option_debug, ast_exten::parent, ast_context::pattern_tree, pbx_substitute_variables_helper(), ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_context::root_table, ast_exten::stuff, and VAR_BUF_SIZE.
Referenced by ast_add_extension2(), and ast_add_extension_nolock().
08995 { 08996 /* 08997 * Sort extensions (or patterns) according to the rules indicated above. 08998 * These are implemented by the function ext_cmp()). 08999 * All priorities for the same ext/pattern/cid are kept in a list, 09000 * using the 'peer' field as a link field.. 09001 */ 09002 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 09003 int res; 09004 int length; 09005 char *p; 09006 char expand_buf[VAR_BUF_SIZE]; 09007 struct ast_exten dummy_exten = {0}; 09008 char dummy_name[1024]; 09009 09010 if (ast_strlen_zero(extension)) { 09011 ast_log(LOG_ERROR,"You have to be kidding-- add exten '' to context %s? Figure out a name and call me back. Action ignored.\n", 09012 con->name); 09013 return -1; 09014 } 09015 09016 /* If we are adding a hint evalulate in variables and global variables */ 09017 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') { 09018 struct ast_channel *c = ast_dummy_channel_alloc(); 09019 09020 if (c) { 09021 ast_copy_string(c->exten, extension, sizeof(c->exten)); 09022 ast_copy_string(c->context, con->name, sizeof(c->context)); 09023 } 09024 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 09025 application = expand_buf; 09026 if (c) { 09027 ast_channel_unref(c); 09028 } 09029 } 09030 09031 length = sizeof(struct ast_exten); 09032 length += strlen(extension) + 1; 09033 length += strlen(application) + 1; 09034 if (label) 09035 length += strlen(label) + 1; 09036 if (callerid) 09037 length += strlen(callerid) + 1; 09038 else 09039 length ++; /* just the '\0' */ 09040 09041 /* Be optimistic: Build the extension structure first */ 09042 if (!(tmp = ast_calloc(1, length))) 09043 return -1; 09044 09045 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 09046 label = 0; 09047 09048 /* use p as dst in assignments, as the fields are const char * */ 09049 p = tmp->stuff; 09050 if (label) { 09051 tmp->label = p; 09052 strcpy(p, label); 09053 p += strlen(label) + 1; 09054 } 09055 tmp->exten = p; 09056 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 09057 tmp->priority = priority; 09058 tmp->cidmatch = p; /* but use p for assignments below */ 09059 09060 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 09061 if (callerid) { 09062 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 09063 tmp->matchcid = AST_EXT_MATCHCID_ON; 09064 } else { 09065 *p++ = '\0'; 09066 tmp->matchcid = AST_EXT_MATCHCID_OFF; 09067 } 09068 tmp->app = p; 09069 strcpy(p, application); 09070 tmp->parent = con; 09071 tmp->data = data; 09072 tmp->datad = datad; 09073 tmp->registrar = registrar; 09074 09075 if (lock_context) { 09076 ast_wrlock_context(con); 09077 } 09078 09079 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 09080 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 09081 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 09082 dummy_exten.exten = dummy_name; 09083 dummy_exten.matchcid = AST_EXT_MATCHCID_OFF; 09084 dummy_exten.cidmatch = 0; 09085 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 09086 if (!tmp2) { 09087 /* hmmm, not in the trie; */ 09088 add_exten_to_pattern_tree(con, tmp, 0); 09089 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 09090 } 09091 } 09092 res = 0; /* some compilers will think it is uninitialized otherwise */ 09093 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 09094 res = ext_cmp(e->exten, tmp->exten); 09095 if (res == 0) { /* extension match, now look at cidmatch */ 09096 if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF) 09097 res = 0; 09098 else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF) 09099 res = 1; 09100 else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF) 09101 res = -1; 09102 else 09103 res = ext_cmp(e->cidmatch, tmp->cidmatch); 09104 } 09105 if (res >= 0) 09106 break; 09107 } 09108 if (e && res == 0) { /* exact match, insert in the priority chain */ 09109 res = add_priority(con, tmp, el, e, replace); 09110 if (lock_context) { 09111 ast_unlock_context(con); 09112 } 09113 if (res < 0) { 09114 errno = EEXIST; /* XXX do we care ? */ 09115 return 0; /* XXX should we return -1 maybe ? */ 09116 } 09117 } else { 09118 /* 09119 * not an exact match, this is the first entry with this pattern, 09120 * so insert in the main list right before 'e' (if any) 09121 */ 09122 tmp->next = e; 09123 if (el) { /* there is another exten already in this context */ 09124 el->next = tmp; 09125 tmp->peer_table = ast_hashtab_create(13, 09126 hashtab_compare_exten_numbers, 09127 ast_hashtab_resize_java, 09128 ast_hashtab_newsize_java, 09129 hashtab_hash_priority, 09130 0); 09131 tmp->peer_label_table = ast_hashtab_create(7, 09132 hashtab_compare_exten_labels, 09133 ast_hashtab_resize_java, 09134 ast_hashtab_newsize_java, 09135 hashtab_hash_labels, 09136 0); 09137 if (label) { 09138 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 09139 } 09140 ast_hashtab_insert_safe(tmp->peer_table, tmp); 09141 } else { /* this is the first exten in this context */ 09142 if (!con->root_table) 09143 con->root_table = ast_hashtab_create(27, 09144 hashtab_compare_extens, 09145 ast_hashtab_resize_java, 09146 ast_hashtab_newsize_java, 09147 hashtab_hash_extens, 09148 0); 09149 con->root = tmp; 09150 con->root->peer_table = ast_hashtab_create(13, 09151 hashtab_compare_exten_numbers, 09152 ast_hashtab_resize_java, 09153 ast_hashtab_newsize_java, 09154 hashtab_hash_priority, 09155 0); 09156 con->root->peer_label_table = ast_hashtab_create(7, 09157 hashtab_compare_exten_labels, 09158 ast_hashtab_resize_java, 09159 ast_hashtab_newsize_java, 09160 hashtab_hash_labels, 09161 0); 09162 if (label) { 09163 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 09164 } 09165 ast_hashtab_insert_safe(con->root->peer_table, tmp); 09166 09167 } 09168 ast_hashtab_insert_safe(con->root_table, tmp); 09169 if (lock_context) { 09170 ast_unlock_context(con); 09171 } 09172 if (tmp->priority == PRIORITY_HINT) { 09173 ast_add_hint(tmp); 09174 } 09175 } 09176 if (option_debug) { 09177 if (tmp->matchcid == AST_EXT_MATCHCID_ON) { 09178 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 09179 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 09180 } else { 09181 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 09182 tmp->exten, tmp->priority, con->name, con); 09183 } 09184 } 09185 09186 if (tmp->matchcid == AST_EXT_MATCHCID_ON) { 09187 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 09188 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 09189 } else { 09190 ast_verb(3, "Added extension '%s' priority %d to %s\n", 09191 tmp->exten, tmp->priority, con->name); 09192 } 09193 09194 return 0; 09195 }
| static int ast_add_extension_nolock | ( | 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 | |||
| ) | [static] |
Definition at line 8594 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
08597 { 08598 int ret = -1; 08599 struct ast_context *c; 08600 08601 c = find_context(context); 08602 if (c) { 08603 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 08604 application, data, datad, registrar, 1); 08605 } 08606 08607 return ret; 08608 }
| static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 5227 of file pbx.c.
References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), ast_hint::callbacks, destroy_hint(), ast_hint::exten, hint_id_cmp(), hints, and ast_hint::laststate.
Referenced by add_priority(), and ast_add_extension2_lockopt().
05228 { 05229 struct ast_hint *hint_new; 05230 struct ast_hint *hint_found; 05231 05232 if (!e) { 05233 return -1; 05234 } 05235 05236 /* 05237 * We must create the hint we wish to add before determining if 05238 * it is already in the hints container to avoid possible 05239 * deadlock when getting the current extension state. 05240 */ 05241 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint); 05242 if (!hint_new) { 05243 return -1; 05244 } 05245 05246 /* Initialize new hint. */ 05247 hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); 05248 if (!hint_new->callbacks) { 05249 ao2_ref(hint_new, -1); 05250 return -1; 05251 } 05252 hint_new->exten = e; 05253 hint_new->laststate = ast_extension_state2(e); 05254 05255 /* Prevent multiple add hints from adding the same hint at the same time. */ 05256 ao2_lock(hints); 05257 05258 /* Search if hint exists, do nothing */ 05259 hint_found = ao2_find(hints, e, 0); 05260 if (hint_found) { 05261 ao2_ref(hint_found, -1); 05262 ao2_unlock(hints); 05263 ao2_ref(hint_new, -1); 05264 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", 05265 ast_get_extension_name(e), ast_get_extension_app(e)); 05266 return -1; 05267 } 05268 05269 /* Add new hint to the hints container */ 05270 ast_debug(2, "HINTS: Adding hint %s: %s\n", 05271 ast_get_extension_name(e), ast_get_extension_app(e)); 05272 ao2_link(hints, hint_new); 05273 05274 ao2_unlock(hints); 05275 ao2_ref(hint_new, -1); 05276 05277 return 0; 05278 }
| 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 8654 of file pbx.c.
References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmf(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().
08655 { 08656 int res = 0; 08657 struct ast_channel *tmpchan; 08658 struct { 08659 char *accountcode; 08660 char *exten; 08661 char *context; 08662 char *linkedid; 08663 char *name; 08664 struct ast_cdr *cdr; 08665 int amaflags; 08666 int state; 08667 format_t readformat; 08668 format_t writeformat; 08669 } tmpvars = { 0, }; 08670 08671 ast_channel_lock(chan); 08672 if (chan->pbx) { /* This channel is currently in the PBX */ 08673 ast_explicit_goto(chan, context, exten, priority + 1); 08674 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08675 ast_channel_unlock(chan); 08676 return res; 08677 } 08678 08679 /* In order to do it when the channel doesn't really exist within 08680 * the PBX, we have to make a new channel, masquerade, and start the PBX 08681 * at the new location */ 08682 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08683 tmpvars.exten = ast_strdupa(chan->exten); 08684 tmpvars.context = ast_strdupa(chan->context); 08685 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08686 tmpvars.name = ast_strdupa(chan->name); 08687 tmpvars.amaflags = chan->amaflags; 08688 tmpvars.state = chan->_state; 08689 tmpvars.writeformat = chan->writeformat; 08690 tmpvars.readformat = chan->readformat; 08691 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08692 08693 ast_channel_unlock(chan); 08694 08695 /* Do not hold any channel locks while calling channel_alloc() since the function 08696 * locks the channel container when linking the new channel in. */ 08697 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08698 ast_cdr_discard(tmpvars.cdr); 08699 return -1; 08700 } 08701 08702 /* copy the cdr info over */ 08703 if (tmpvars.cdr) { 08704 ast_cdr_discard(tmpchan->cdr); 08705 tmpchan->cdr = tmpvars.cdr; 08706 tmpvars.cdr = NULL; 08707 } 08708 08709 /* Make formats okay */ 08710 tmpchan->readformat = tmpvars.readformat; 08711 tmpchan->writeformat = tmpvars.writeformat; 08712 08713 /* Setup proper location. Never hold another channel lock while calling this function. */ 08714 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08715 08716 /* Masquerade into tmp channel */ 08717 if (ast_channel_masquerade(tmpchan, chan)) { 08718 /* Failed to set up the masquerade. It's probably chan_local 08719 * in the middle of optimizing itself out. Sad. :( */ 08720 ast_hangup(tmpchan); 08721 tmpchan = NULL; 08722 res = -1; 08723 } else { 08724 ast_do_masquerade(tmpchan); 08725 /* Start the PBX going on our stolen channel */ 08726 if (ast_pbx_start(tmpchan)) { 08727 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08728 ast_hangup(tmpchan); 08729 res = -1; 08730 } 08731 } 08732 08733 return res; 08734 }
| int ast_async_goto_by_name | ( | const char * | channame, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Set the channel to next execute the specified dialplan location.
Definition at line 8736 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08737 { 08738 struct ast_channel *chan; 08739 int res = -1; 08740 08741 if ((chan = ast_channel_get_by_name(channame))) { 08742 res = ast_async_goto(chan, context, exten, priority); 08743 chan = ast_channel_unref(chan); 08744 } 08745 08746 return res; 08747 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 11094 of file pbx.c.
References __ast_goto_if_exists().
11095 { 11096 return __ast_goto_if_exists(chan, context, exten, priority, 1); 11097 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 11159 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
11160 { 11161 return pbx_parseable_goto(chan, goto_string, 1); 11162 }
| 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 8237 of file pbx.c.
References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
08238 { 08239 char *info; 08240 int j, num_fields, last_sep = -1; 08241 08242 /* Check for empty just in case */ 08243 if (ast_strlen_zero(info_in)) { 08244 return 0; 08245 } 08246 08247 /* make a copy just in case we were passed a static string */ 08248 info = ast_strdupa(info_in); 08249 08250 /* count the number of fields in the timespec */ 08251 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08252 if (info[j] == ',') { 08253 last_sep = j; 08254 num_fields++; 08255 } 08256 } 08257 08258 /* save the timezone, if it is specified */ 08259 if (num_fields == 5) { 08260 i->timezone = ast_strdup(info + last_sep + 1); 08261 } else { 08262 i->timezone = NULL; 08263 } 08264 08265 /* Assume everything except time */ 08266 i->monthmask = 0xfff; /* 12 bits */ 08267 i->daymask = 0x7fffffffU; /* 31 bits */ 08268 i->dowmask = 0x7f; /* 7 bits */ 08269 /* on each call, use strsep() to move info to the next argument */ 08270 get_timerange(i, strsep(&info, "|,")); 08271 if (info) 08272 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08273 if (info) 08274 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08275 if (info) 08276 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08277 return 1; 08278 }
| 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 5368 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
05369 { 05370 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05371 }
Change hint for an extension.
Definition at line 5281 of file pbx.c.
References ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_hint::exten, hints, and OBJ_UNLINK.
Referenced by add_priority().
05282 { 05283 struct ast_hint *hint; 05284 05285 if (!oe || !ne) { 05286 return -1; 05287 } 05288 05289 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */ 05290 05291 /* 05292 * Unlink the hint from the hints container as the extension 05293 * name (which is the hash value) could change. 05294 */ 05295 hint = ao2_find(hints, oe, OBJ_UNLINK); 05296 if (!hint) { 05297 ao2_unlock(hints); 05298 return -1; 05299 } 05300 05301 /* Update the hint and put it back in the hints container. */ 05302 ao2_lock(hint); 05303 hint->exten = ne; 05304 ao2_unlock(hint); 05305 ao2_link(hints, hint); 05306 05307 ao2_unlock(hints); 05308 ao2_ref(hint, -1); 05309 05310 return 0; 05311 }
| 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 8280 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08281 { 08282 return ast_check_timing2(i, ast_tvnow()); 08283 }
| 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 8285 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().
08286 { 08287 struct ast_tm tm; 08288 08289 ast_localtime(&tv, &tm, i->timezone); 08290 08291 /* If it's not the right month, return */ 08292 if (!(i->monthmask & (1 << tm.tm_mon))) 08293 return 0; 08294 08295 /* If it's not that time of the month.... */ 08296 /* Warning, tm_mday has range 1..31! */ 08297 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08298 return 0; 08299 08300 /* If it's not the right day of the week */ 08301 if (!(i->dowmask & (1 << tm.tm_wday))) 08302 return 0; 08303 08304 /* Sanity check the hour just to be safe */ 08305 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08306 ast_log(LOG_WARNING, "Insane time...\n"); 08307 return 0; 08308 } 08309 08310 /* Now the tough part, we calculate if it fits 08311 in the right time based on min/hour */ 08312 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)))) 08313 return 0; 08314 08315 /* If we got this far, then we're good */ 08316 return 1; 08317 }
| 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 11164 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().
11165 { 11166 struct ast_app *app = NULL; 11167 int which = 0; 11168 char *ret = NULL; 11169 size_t wordlen = strlen(word); 11170 11171 AST_RWLIST_RDLOCK(&apps); 11172 AST_RWLIST_TRAVERSE(&apps, app, list) { 11173 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 11174 ret = ast_strdup(app->name); 11175 break; 11176 } 11177 } 11178 AST_RWLIST_UNLOCK(&apps); 11179 11180 return ret; 11181 }
| int ast_context_add_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Add an ignorepat.
| context | which context to add the ignorpattern to | |
| ignorepat | ignorepattern to set up for the extension | |
| registrar | registrar of the ignore pattern |
Adds an ignore pattern to a particular context.
| 0 | on success | |
| -1 | on failure |
Definition at line 8521 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08522 { 08523 int ret = -1; 08524 struct ast_context *c; 08525 08526 c = find_context_locked(context); 08527 if (c) { 08528 ret = ast_context_add_ignorepat2(c, value, registrar); 08529 ast_unlock_contexts(); 08530 } 08531 return ret; 08532 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | value, | |||
| const char * | registrar | |||
| ) |
Definition at line 8534 of file pbx.c.
References ast_calloc, ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08535 { 08536 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08537 int length; 08538 char *pattern; 08539 length = sizeof(struct ast_ignorepat); 08540 length += strlen(value) + 1; 08541 if (!(ignorepat = ast_calloc(1, length))) 08542 return -1; 08543 /* The cast to char * is because we need to write the initial value. 08544 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08545 * sees the cast as dereferencing a type-punned pointer and warns about 08546 * it. This is the workaround (we're telling gcc, yes, that's really 08547 * what we wanted to do). 08548 */ 08549 pattern = (char *) ignorepat->pattern; 08550 strcpy(pattern, value); 08551 ignorepat->next = NULL; 08552 ignorepat->registrar = registrar; 08553 ast_wrlock_context(con); 08554 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08555 ignorepatl = ignorepatc; 08556 if (!strcasecmp(ignorepatc->pattern, value)) { 08557 /* Already there */ 08558 ast_unlock_context(con); 08559 ast_free(ignorepat); 08560 errno = EEXIST; 08561 return -1; 08562 } 08563 } 08564 if (ignorepatl) 08565 ignorepatl->next = ignorepat; 08566 else 08567 con->ignorepats = ignorepat; 08568 ast_unlock_context(con); 08569 return 0; 08570 08571 }
| int ast_context_add_include | ( | const char * | context, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| context | context to add include to | |
| include | new include to add | |
| registrar | who's registering it |
Adds an include taking a char * string as the context parameter
| 0 | on success | |
| -1 | on error |
Definition at line 8065 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
08066 { 08067 int ret = -1; 08068 struct ast_context *c; 08069 08070 c = find_context_locked(context); 08071 if (c) { 08072 ret = ast_context_add_include2(c, include, registrar); 08073 ast_unlock_contexts(); 08074 } 08075 return ret; 08076 }
| int ast_context_add_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| con | context to add the include to | |
| include | include to add | |
| registrar | who registered the context |
Adds an include taking a struct ast_context as the first parameter
| 0 | on success | |
| -1 | on failure |
Definition at line 8334 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().
08336 { 08337 struct ast_include *new_include; 08338 char *c; 08339 struct ast_include *i, *il = NULL; /* include, include_last */ 08340 int length; 08341 char *p; 08342 08343 length = sizeof(struct ast_include); 08344 length += 2 * (strlen(value) + 1); 08345 08346 /* allocate new include structure ... */ 08347 if (!(new_include = ast_calloc(1, length))) 08348 return -1; 08349 /* Fill in this structure. Use 'p' for assignments, as the fields 08350 * in the structure are 'const char *' 08351 */ 08352 p = new_include->stuff; 08353 new_include->name = p; 08354 strcpy(p, value); 08355 p += strlen(value) + 1; 08356 new_include->rname = p; 08357 strcpy(p, value); 08358 /* Strip off timing info, and process if it is there */ 08359 if ( (c = strchr(p, ',')) ) { 08360 *c++ = '\0'; 08361 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08362 } 08363 new_include->next = NULL; 08364 new_include->registrar = registrar; 08365 08366 ast_wrlock_context(con); 08367 08368 /* ... go to last include and check if context is already included too... */ 08369 for (i = con->includes; i; i = i->next) { 08370 if (!strcasecmp(i->name, new_include->name)) { 08371 ast_destroy_timing(&(new_include->timing)); 08372 ast_free(new_include); 08373 ast_unlock_context(con); 08374 errno = EEXIST; 08375 return -1; 08376 } 08377 il = i; 08378 } 08379 08380 /* ... include new context into context list, unlock, return */ 08381 if (il) 08382 il->next = new_include; 08383 else 08384 con->includes = new_include; 08385 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08386 08387 ast_unlock_context(con); 08388 08389 return 0; 08390 }
| int ast_context_add_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| int | eval, | |||
| const char * | registrar | |||
| ) |
Add a switch.
| context | context to which to add the switch | |
| sw | switch to add | |
| data | data to pass to switch | |
| eval | whether to evaluate variables when running switch | |
| registrar | whoever registered the switch |
This function registers a switch with the asterisk switch architecture
| 0 | on success | |
| -1 | on failure |
Definition at line 8397 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08398 { 08399 int ret = -1; 08400 struct ast_context *c; 08401 08402 c = find_context_locked(context); 08403 if (c) { /* found, add switch to this context */ 08404 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08405 ast_unlock_contexts(); 08406 } 08407 return ret; 08408 }
| 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 8417 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().
08419 { 08420 struct ast_sw *new_sw; 08421 struct ast_sw *i; 08422 int length; 08423 char *p; 08424 08425 length = sizeof(struct ast_sw); 08426 length += strlen(value) + 1; 08427 if (data) 08428 length += strlen(data); 08429 length++; 08430 08431 /* allocate new sw structure ... */ 08432 if (!(new_sw = ast_calloc(1, length))) 08433 return -1; 08434 /* ... fill in this structure ... */ 08435 p = new_sw->stuff; 08436 new_sw->name = p; 08437 strcpy(new_sw->name, value); 08438 p += strlen(value) + 1; 08439 new_sw->data = p; 08440 if (data) { 08441 strcpy(new_sw->data, data); 08442 p += strlen(data) + 1; 08443 } else { 08444 strcpy(new_sw->data, ""); 08445 p++; 08446 } 08447 new_sw->eval = eval; 08448 new_sw->registrar = registrar; 08449 08450 /* ... try to lock this context ... */ 08451 ast_wrlock_context(con); 08452 08453 /* ... go to last sw and check if context is already swd too... */ 08454 AST_LIST_TRAVERSE(&con->alts, i, list) { 08455 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08456 ast_free(new_sw); 08457 ast_unlock_context(con); 08458 errno = EEXIST; 08459 return -1; 08460 } 08461 } 08462 08463 /* ... sw new context into context list, unlock, return */ 08464 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08465 08466 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08467 08468 ast_unlock_context(con); 08469 08470 return 0; 08471 }
| void ast_context_destroy | ( | struct ast_context * | con, | |
| const char * | registrar | |||
| ) |
Destroy a context (matches the specified context (or ANY context if NULL).
| con | context to destroy | |
| registrar | who registered it |
You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.
Definition at line 9798 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), features_shutdown(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09799 { 09800 ast_wrlock_contexts(); 09801 __ast_context_destroy(contexts, contexts_table, con,registrar); 09802 ast_unlock_contexts(); 09803 }
| struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
| name | name of the context to find |
Will search for the context with the given name.
Definition at line 2929 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().
02930 { 02931 struct ast_context *tmp; 02932 struct fake_context item; 02933 02934 if (!name) { 02935 return NULL; 02936 } 02937 ast_rdlock_contexts(); 02938 if (contexts_table) { 02939 ast_copy_string(item.name, name, sizeof(item.name)); 02940 tmp = ast_hashtab_lookup(contexts_table, &item); 02941 } else { 02942 tmp = NULL; 02943 while ((tmp = ast_walk_contexts(tmp))) { 02944 if (!strcasecmp(name, tmp->name)) { 02945 break; 02946 } 02947 } 02948 } 02949 ast_unlock_contexts(); 02950 return tmp; 02951 }
| struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| const char * | name, | |||
| const char * | registrar | |||
| ) | [read] |
Register a new context or find an existing one.
| extcontexts | pointer to the ast_context structure pointer | |
| exttable | pointer to the hashtable that contains all the elements in extcontexts | |
| name | name of the new context | |
| registrar | registrar of the context |
This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.
Definition at line 7664 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
07665 { 07666 struct ast_context *tmp, **local_contexts; 07667 struct fake_context search; 07668 int length = sizeof(struct ast_context) + strlen(name) + 1; 07669 07670 if (!contexts_table) { 07671 /* Protect creation of contexts_table from reentrancy. */ 07672 ast_wrlock_contexts(); 07673 if (!contexts_table) { 07674 contexts_table = ast_hashtab_create(17, 07675 ast_hashtab_compare_contexts, 07676 ast_hashtab_resize_java, 07677 ast_hashtab_newsize_java, 07678 ast_hashtab_hash_contexts, 07679 0); 07680 } 07681 ast_unlock_contexts(); 07682 } 07683 07684 ast_copy_string(search.name, name, sizeof(search.name)); 07685 if (!extcontexts) { 07686 ast_rdlock_contexts(); 07687 local_contexts = &contexts; 07688 tmp = ast_hashtab_lookup(contexts_table, &search); 07689 ast_unlock_contexts(); 07690 if (tmp) { 07691 tmp->refcount++; 07692 return tmp; 07693 } 07694 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07695 local_contexts = extcontexts; 07696 tmp = ast_hashtab_lookup(exttable, &search); 07697 if (tmp) { 07698 tmp->refcount++; 07699 return tmp; 07700 } 07701 } 07702 07703 if ((tmp = ast_calloc(1, length))) { 07704 ast_rwlock_init(&tmp->lock); 07705 ast_mutex_init(&tmp->macrolock); 07706 strcpy(tmp->name, name); 07707 tmp->root = NULL; 07708 tmp->root_table = NULL; 07709 tmp->registrar = ast_strdup(registrar); 07710 tmp->includes = NULL; 07711 tmp->ignorepats = NULL; 07712 tmp->refcount = 1; 07713 } else { 07714 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07715 return NULL; 07716 } 07717 07718 if (!extcontexts) { 07719 ast_wrlock_contexts(); 07720 tmp->next = *local_contexts; 07721 *local_contexts = tmp; 07722 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07723 ast_unlock_contexts(); 07724 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07725 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07726 } else { 07727 tmp->next = *local_contexts; 07728 if (exttable) 07729 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07730 07731 *local_contexts = tmp; 07732 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07733 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07734 } 07735 return tmp; 07736 }
| int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 6259 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06260 { 06261 struct ast_context *c; 06262 int ret = -1; 06263 06264 c = find_context_locked(context); 06265 if (c) { 06266 ast_unlock_contexts(); 06267 06268 /* if we found context, lock macrolock */ 06269 ret = ast_mutex_lock(&c->macrolock); 06270 } 06271 06272 return ret; 06273 }
| int ast_context_remove_extension | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar | |||
| ) |
Simply remove extension from context.
Definition at line 6067 of file pbx.c.
References ast_context_remove_extension_callerid(), and AST_EXT_MATCHCID_ANY.
Referenced by register_peer_exten(), remove_exten_if_exist(), sla_station_destructor(), sla_trunk_destructor(), unregister_exten(), and UnregisterExtension().
06068 { 06069 return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar); 06070 }
| 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 6097 of file pbx.c.
References ast_context_remove_extension_callerid2(), and AST_EXT_MATCHCID_ANY.
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
06098 { 06099 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked); 06100 }
| int ast_context_remove_extension_callerid | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | callerid, | |||
| int | matchcallerid, | |||
| const char * | registrar | |||
| ) |
Definition at line 6072 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().
06073 { 06074 int ret = -1; /* default error return */ 06075 struct ast_context *c; 06076 06077 c = find_context_locked(context); 06078 if (c) { /* ... remove extension ... */ 06079 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 06080 matchcallerid, registrar, 0); 06081 ast_unlock_contexts(); 06082 } 06083 06084 return ret; 06085 }
| int ast_context_remove_extension_callerid2 | ( | struct ast_context * | con, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | callerid, | |||
| int | matchcallerid, | |||
| const char * | registrar, | |||
| int | already_locked | |||
| ) |
Definition at line 6102 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().
06103 { 06104 struct ast_exten *exten, *prev_exten = NULL; 06105 struct ast_exten *peer; 06106 struct ast_exten ex, *exten2, *exten3; 06107 char dummy_name[1024]; 06108 struct ast_exten *previous_peer = NULL; 06109 struct ast_exten *next_peer = NULL; 06110 int found = 0; 06111 06112 if (!already_locked) 06113 ast_wrlock_context(con); 06114 06115 #ifdef NEED_DEBUG 06116 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 06117 #endif 06118 #ifdef CONTEXT_DEBUG 06119 check_contexts(__FILE__, __LINE__); 06120 #endif 06121 /* find this particular extension */ 06122 ex.exten = dummy_name; 06123 ex.matchcid = matchcallerid; 06124 ex.cidmatch = callerid; 06125 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 06126 exten = ast_hashtab_lookup(con->root_table, &ex); 06127 if (exten) { 06128 if (priority == 0) { 06129 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06130 if (!exten2) 06131 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); 06132 if (con->pattern_tree) { 06133 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06134 06135 if (x->exten) { /* this test for safety purposes */ 06136 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06137 x->exten = 0; /* get rid of what will become a bad pointer */ 06138 } else { 06139 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 06140 } 06141 } 06142 } else { 06143 ex.priority = priority; 06144 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 06145 if (exten2) { 06146 if (exten2->label) { /* if this exten has a label, remove that, too */ 06147 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 06148 if (!exten3) 06149 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); 06150 } 06151 06152 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 06153 if (!exten3) 06154 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); 06155 if (exten2 == exten && exten2->peer) { 06156 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06157 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 06158 } 06159 if (ast_hashtab_size(exten->peer_table) == 0) { 06160 /* well, if the last priority of an exten is to be removed, 06161 then, the extension is removed, too! */ 06162 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 06163 if (!exten3) 06164 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 06165 if (con->pattern_tree) { 06166 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06167 if (x->exten) { /* this test for safety purposes */ 06168 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06169 x->exten = 0; /* get rid of what will become a bad pointer */ 06170 } 06171 } 06172 } 06173 } else { 06174 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 06175 priority, exten->exten, con->name); 06176 } 06177 } 06178 } else { 06179 /* hmmm? this exten is not in this pattern tree? */ 06180 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 06181 extension, con->name); 06182 } 06183 #ifdef NEED_DEBUG 06184 if (con->pattern_tree) { 06185 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 06186 log_match_char_tree(con->pattern_tree, " "); 06187 } 06188 #endif 06189 06190 /* scan the extension list to find first matching extension-registrar */ 06191 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 06192 if (!strcmp(exten->exten, extension) && 06193 (!registrar || !strcmp(exten->registrar, registrar)) && 06194 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 06195 break; 06196 } 06197 if (!exten) { 06198 /* we can't find right extension */ 06199 if (!already_locked) 06200 ast_unlock_context(con); 06201 return -1; 06202 } 06203 06204 /* scan the priority list to remove extension with exten->priority == priority */ 06205 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 06206 peer && !strcmp(peer->exten, extension) && 06207 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ; 06208 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 06209 06210 if ((priority == 0 || peer->priority == priority) && 06211 (!registrar || !strcmp(peer->registrar, registrar) )) { 06212 found = 1; 06213 06214 /* we are first priority extension? */ 06215 if (!previous_peer) { 06216 /* 06217 * We are first in the priority chain, so must update the extension chain. 06218 * The next node is either the next priority or the next extension 06219 */ 06220 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 06221 if (peer->peer) { 06222 /* move the peer_table and peer_label_table down to the next peer, if 06223 it is there */ 06224 peer->peer->peer_table = peer->peer_table; 06225 peer->peer->peer_label_table = peer->peer_label_table; 06226 peer->peer_table = NULL; 06227 peer->peer_label_table = NULL; 06228 } 06229 if (!prev_exten) { /* change the root... */ 06230 con->root = next_node; 06231 } else { 06232 prev_exten->next = next_node; /* unlink */ 06233 } 06234 if (peer->peer) { /* update the new head of the pri list */ 06235 peer->peer->next = peer->next; 06236 } 06237 } else { /* easy, we are not first priority in extension */ 06238 previous_peer->peer = peer->peer; 06239 } 06240 06241 06242 /* now, free whole priority extension */ 06243 destroy_exten(peer); 06244 } else { 06245 previous_peer = peer; 06246 } 06247 } 06248 if (!already_locked) 06249 ast_unlock_context(con); 06250 return found ? 0 : -1; 06251 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8477 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08478 { 08479 int ret = -1; 08480 struct ast_context *c; 08481 08482 c = find_context_locked(context); 08483 if (c) { 08484 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08485 ast_unlock_contexts(); 08486 } 08487 return ret; 08488 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8490 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().
08491 { 08492 struct ast_ignorepat *ip, *ipl = NULL; 08493 08494 ast_wrlock_context(con); 08495 08496 for (ip = con->ignorepats; ip; ip = ip->next) { 08497 if (!strcmp(ip->pattern, ignorepat) && 08498 (!registrar || (registrar == ip->registrar))) { 08499 if (ipl) { 08500 ipl->next = ip->next; 08501 ast_free(ip); 08502 } else { 08503 con->ignorepats = ip->next; 08504 ast_free(ip); 08505 } 08506 ast_unlock_context(con); 08507 return 0; 08508 } 08509 ipl = ip; 08510 } 08511 08512 ast_unlock_context(con); 08513 errno = EINVAL; 08514 return -1; 08515 }
| int ast_context_remove_include | ( | const char * | context, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ...
Remove a context include.
Definition at line 5960 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05961 { 05962 int ret = -1; 05963 struct ast_context *c; 05964 05965 c = find_context_locked(context); 05966 if (c) { 05967 /* found, remove include from this context ... */ 05968 ret = ast_context_remove_include2(c, include, registrar); 05969 ast_unlock_contexts(); 05970 } 05971 return ret; 05972 }
| int ast_context_remove_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.
Removes an include by an ast_context structure.
| 0 | on success. | |
| -1 | on failure. |
Definition at line 5983 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().
05984 { 05985 struct ast_include *i, *pi = NULL; 05986 int ret = -1; 05987 05988 ast_wrlock_context(con); 05989 05990 /* find our include */ 05991 for (i = con->includes; i; pi = i, i = i->next) { 05992 if (!strcmp(i->name, include) && 05993 (!registrar || !strcmp(i->registrar, registrar))) { 05994 /* remove from list */ 05995 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05996 if (pi) 05997 pi->next = i->next; 05998 else 05999 con->includes = i->next; 06000 /* free include and return */ 06001 ast_destroy_timing(&(i->timing)); 06002 ast_free(i); 06003 ret = 0; 06004 break; 06005 } 06006 } 06007 06008 ast_unlock_context(con); 06009 06010 return ret; 06011 }
| int ast_context_remove_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
Remove a switch.
Definition at line 6018 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
06019 { 06020 int ret = -1; /* default error return */ 06021 struct ast_context *c; 06022 06023 c = find_context_locked(context); 06024 if (c) { 06025 /* remove switch from this context ... */ 06026 ret = ast_context_remove_switch2(c, sw, data, registrar); 06027 ast_unlock_contexts(); 06028 } 06029 return ret; 06030 }
| 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 6040 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().
06041 { 06042 struct ast_sw *i; 06043 int ret = -1; 06044 06045 ast_wrlock_context(con); 06046 06047 /* walk switches */ 06048 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 06049 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 06050 (!registrar || !strcmp(i->registrar, registrar))) { 06051 /* found, remove from list */ 06052 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 06053 AST_LIST_REMOVE_CURRENT(list); 06054 ast_free(i); /* free switch and return */ 06055 ret = 0; 06056 break; 06057 } 06058 } 06059 AST_LIST_TRAVERSE_SAFE_END; 06060 06061 ast_unlock_context(con); 06062 06063 return ret; 06064 }
| int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 6280 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06281 { 06282 struct ast_context *c; 06283 int ret = -1; 06284 06285 c = find_context_locked(context); 06286 if (c) { 06287 ast_unlock_contexts(); 06288 06289 /* if we found context, unlock macrolock */ 06290 ret = ast_mutex_unlock(&c->macrolock); 06291 } 06292 06293 return ret; 06294 }
| 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 11049 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().
11050 { 11051 struct ast_include *inc = NULL; 11052 int res = 0; 11053 11054 while ( (inc = ast_walk_context_includes(con, inc)) ) { 11055 if (ast_context_find(inc->rname)) 11056 continue; 11057 11058 res = -1; 11059 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 11060 ast_get_context_name(con), inc->rname); 11061 break; 11062 } 11063 11064 return res; 11065 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3758 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_compile_ael2(), ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03759 { 03760 struct ast_custom_function *acf = NULL; 03761 03762 AST_RWLIST_RDLOCK(&acf_root); 03763 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03764 if (!strcmp(name, acf->name)) 03765 break; 03766 } 03767 AST_RWLIST_UNLOCK(&acf_root); 03768 03769 return acf; 03770 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3772 of file pbx.c.
References ast_custom_escalating_function::acf, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by __ast_custom_function_register_escalating(), _unload_module(), load_module(), reload(), unload_module(), and unload_pbx().
03773 { 03774 struct ast_custom_function *cur; 03775 struct ast_custom_escalating_function *cur_escalation; 03776 03777 if (!acf) { 03778 return -1; 03779 } 03780 03781 AST_RWLIST_WRLOCK(&acf_root); 03782 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03783 #ifdef AST_XML_DOCS 03784 if (cur->docsrc == AST_XML_DOC) { 03785 ast_string_field_free_memory(acf); 03786 } 03787 #endif 03788 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03789 } 03790 AST_RWLIST_UNLOCK(&acf_root); 03791 03792 /* Remove from the escalation list */ 03793 AST_RWLIST_WRLOCK(&escalation_root); 03794 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) { 03795 if (cur_escalation->acf == acf) { 03796 AST_RWLIST_REMOVE_CURRENT(list); 03797 break; 03798 } 03799 } 03800 AST_RWLIST_TRAVERSE_SAFE_END; 03801 AST_RWLIST_UNLOCK(&escalation_root); 03802 03803 return cur ? 0 : -1; 03804 }
| 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 8319 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
| enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
| [in] | devstate | device state |
Definition at line 4801 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().
04802 { 04803 switch (devstate) { 04804 case AST_DEVICE_ONHOLD: 04805 return AST_EXTENSION_ONHOLD; 04806 case AST_DEVICE_BUSY: 04807 return AST_EXTENSION_BUSY; 04808 case AST_DEVICE_UNKNOWN: 04809 return AST_EXTENSION_NOT_INUSE; 04810 case AST_DEVICE_UNAVAILABLE: 04811 case AST_DEVICE_INVALID: 04812 return AST_EXTENSION_UNAVAILABLE; 04813 case AST_DEVICE_RINGINUSE: 04814 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04815 case AST_DEVICE_RINGING: 04816 return AST_EXTENSION_RINGING; 04817 case AST_DEVICE_INUSE: 04818 return AST_EXTENSION_INUSE; 04819 case AST_DEVICE_NOT_INUSE: 04820 return AST_EXTENSION_NOT_INUSE; 04821 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04822 break; 04823 } 04824 04825 return AST_EXTENSION_NOT_INUSE; 04826 }
| 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 5353 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().
05354 { 05355 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05356 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 8631 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
08632 { 08633 if (!chan) 08634 return -1; 08635 08636 ast_channel_lock(chan); 08637 08638 if (!ast_strlen_zero(context)) 08639 ast_copy_string(chan->context, context, sizeof(chan->context)); 08640 if (!ast_strlen_zero(exten)) 08641 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08642 if (priority > -1) { 08643 chan->priority = priority; 08644 /* see flag description in channel.h for explanation */ 08645 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08646 chan->priority--; 08647 } 08648 08649 ast_channel_unlock(chan); 08650 08651 return 0; 08652 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 2906 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().
02907 { 02908 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02909 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02910 return extension_match_core(pattern, data, needmore); 02911 }
| 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 2671 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02672 { 02673 int cmp; 02674 02675 cmp = ext_cmp(a, b); 02676 if (cmp < 0) { 02677 return -1; 02678 } 02679 if (cmp > 0) { 02680 return 1; 02681 } 02682 return 0; 02683 }
| 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 2901 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().
02902 { 02903 return extension_match_core(pattern, data, E_MATCH); 02904 }
| int ast_extension_state | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten | |||
| ) |
Check extension state for an extension by using hint.
Uses hint and devicestate callback to get the state of an extension.
Definition at line 4871 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().
04872 { 04873 struct ast_exten *e; 04874 04875 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04876 return -1; /* No hint, return -1 */ 04877 } 04878 04879 if (e->exten[0] == '_') { 04880 /* Create this hint on-the-fly */ 04881 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04882 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04883 e->registrar); 04884 if (!(e = ast_hint_extension(c, context, exten))) { 04885 /* Improbable, but not impossible */ 04886 return -1; 04887 } 04888 } 04889 04890 return ast_extension_state2(e); /* Check all devices in the hint */ 04891 }
| static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4846 of file pbx.c.
References ast_extension_state3(), ast_get_extension_app(), ast_str_set(), ast_str_thread_get(), and extensionstate_buf.
Referenced by ast_add_hint(), and ast_extension_state().
04847 { 04848 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32); 04849 04850 if (!e || !hint_app) { 04851 return -1; 04852 } 04853 04854 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e)); 04855 return ast_extension_state3(hint_app); 04856 }
| const char* ast_extension_state2str | ( | int | extension_state | ) |
Return extension_state as string.
Return string representation of the state of an extension.
Definition at line 4859 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), and show_channels_cb().
04860 { 04861 int i; 04862 04863 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04864 if (extension_states[i].extension_state == extension_state) 04865 return extension_states[i].text; 04866 } 04867 return "Unknown"; 04868 }
| static int ast_extension_state3 | ( | struct ast_str * | hint_app | ) | [static] |
Definition at line 4828 of file pbx.c.
References ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), and ast_str_buffer().
Referenced by ast_extension_state2(), and handle_statechange().
04829 { 04830 char *cur; 04831 char *rest; 04832 struct ast_devstate_aggregate agg; 04833 04834 /* One or more devices separated with a & character */ 04835 rest = ast_str_buffer(hint_app); 04836 04837 ast_devstate_aggregate_init(&agg); 04838 while ((cur = strsep(&rest, "&"))) { 04839 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04840 } 04841 04842 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04843 }
| int ast_extension_state_add | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | change_cb, | |||
| void * | data | |||
| ) |
Add watcher for extension states.
Registers a state change callback.
Definition at line 5092 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
05094 { 05095 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 05096 }
| 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 | |||
| ) |
Add watcher for extension states with destructor.
Registers a state change callback with destructor.
Definition at line 5005 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().
05007 { 05008 struct ast_hint *hint; 05009 struct ast_state_cb *state_cb; 05010 struct ast_exten *e; 05011 int id; 05012 05013 /* If there's no context and extension: add callback to statecbs list */ 05014 if (!context && !exten) { 05015 /* Prevent multiple adds from adding the same change_cb at the same time. */ 05016 ao2_lock(statecbs); 05017 05018 /* Remove any existing change_cb. */ 05019 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 05020 05021 /* Now insert the change_cb */ 05022 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05023 ao2_unlock(statecbs); 05024 return -1; 05025 } 05026 state_cb->id = 0; 05027 state_cb->change_cb = change_cb; 05028 state_cb->destroy_cb = destroy_cb; 05029 state_cb->data = data; 05030 ao2_link(statecbs, state_cb); 05031 05032 ao2_ref(state_cb, -1); 05033 ao2_unlock(statecbs); 05034 return 0; 05035 } 05036 05037 if (!context || !exten) 05038 return -1; 05039 05040 /* This callback type is for only one hint, so get the hint */ 05041 e = ast_hint_extension(NULL, context, exten); 05042 if (!e) { 05043 return -1; 05044 } 05045 05046 /* If this is a pattern, dynamically create a new extension for this 05047 * particular match. Note that this will only happen once for each 05048 * individual extension, because the pattern will no longer match first. 05049 */ 05050 if (e->exten[0] == '_') { 05051 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 05052 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 05053 e->registrar); 05054 e = ast_hint_extension(NULL, context, exten); 05055 if (!e || e->exten[0] == '_') { 05056 return -1; 05057 } 05058 } 05059 05060 /* Find the hint in the hints container */ 05061 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05062 hint = ao2_find(hints, e, 0); 05063 if (!hint) { 05064 ao2_unlock(hints); 05065 return -1; 05066 } 05067 05068 /* Now insert the callback in the callback list */ 05069 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05070 ao2_ref(hint, -1); 05071 ao2_unlock(hints); 05072 return -1; 05073 } 05074 do { 05075 id = stateid++; /* Unique ID for this callback */ 05076 /* Do not allow id to ever be -1 or 0. */ 05077 } while (id == -1 || id == 0); 05078 state_cb->id = id; 05079 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 05080 state_cb->destroy_cb = destroy_cb; 05081 state_cb->data = data; /* Data for the callback */ 05082 ao2_link(hint->callbacks, state_cb); 05083 05084 ao2_ref(state_cb, -1); 05085 ao2_ref(hint, -1); 05086 ao2_unlock(hints); 05087 05088 return id; 05089 }
| int ast_extension_state_del | ( | int | id, | |
| ast_state_cb_type | change_cb | |||
| ) |
ast_extension_state_del: Remove a watcher from the callback list
Deletes a registered state change callback by ID.
Definition at line 5114 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().
05115 { 05116 struct ast_state_cb *p_cur; 05117 int ret = -1; 05118 05119 if (!id) { /* id == 0 is a callback without extension */ 05120 if (!change_cb) { 05121 return ret; 05122 } 05123 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 05124 if (p_cur) { 05125 ret = 0; 05126 ao2_ref(p_cur, -1); 05127 } 05128 } else { /* callback with extension, find the callback based on ID */ 05129 struct ast_hint *hint; 05130 05131 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05132 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 05133 if (hint) { 05134 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 05135 if (p_cur) { 05136 ret = 0; 05137 ao2_ref(p_cur, -1); 05138 } 05139 ao2_ref(hint, -1); 05140 } 05141 ao2_unlock(hints); 05142 } 05143 05144 return ret; 05145 }
| 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 5358 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().
05359 { 05360 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05361 }
| int ast_findlabel_extension2 | ( | struct ast_channel * | c, | |
| struct ast_context * | con, | |||
| const char * | exten, | |||
| const char * | label, | |||
| const char * | callerid | |||
| ) |
Find the priority of an extension that has the specified label.
Definition at line 5363 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05364 { 05365 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05366 }
| int ast_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | workspace, | |||
| size_t | len | |||
| ) |
executes a read operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| workspace | A pointer to safe memory to use for a return value | |
| len | the number of bytes in workspace |
This application executes a function in read mode on a given channel.
| 0 | success | |
| non-zero | failure |
Definition at line 4134 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
04135 { 04136 char *copy = ast_strdupa(function); 04137 char *args = func_args(copy); 04138 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04139 int res; 04140 struct ast_module_user *u = NULL; 04141 04142 if (acfptr == NULL) { 04143 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04144 } else if (!acfptr->read && !acfptr->read2) { 04145 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04146 } else if (!is_read_allowed(acfptr)) { 04147 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04148 } else if (acfptr->read) { 04149 if (acfptr->mod) { 04150 u = __ast_module_user_add(acfptr->mod, chan); 04151 } 04152 res = acfptr->read(chan, copy, args, workspace, len); 04153 if (acfptr->mod && u) { 04154 __ast_module_user_remove(acfptr->mod, u); 04155 } 04156 return res; 04157 } else { 04158 struct ast_str *str = ast_str_create(16); 04159 if (acfptr->mod) { 04160 u = __ast_module_user_add(acfptr->mod, chan); 04161 } 04162 res = acfptr->read2(chan, copy, args, &str, 0); 04163 if (acfptr->mod && u) { 04164 __ast_module_user_remove(acfptr->mod, u); 04165 } 04166 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 04167 ast_free(str); 04168 return res; 04169 } 04170 return -1; 04171 }
| int ast_func_read2 | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| struct ast_str ** | str, | |||
| ssize_t | maxlen | |||
| ) |
executes a read operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| str | A dynamic string buffer into which to place the result. | |
| maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
This application executes a function in read mode on a given channel.
| 0 | success | |
| non-zero | failure |
Definition at line 4173 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
04174 { 04175 char *copy = ast_strdupa(function); 04176 char *args = func_args(copy); 04177 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04178 int res; 04179 struct ast_module_user *u = NULL; 04180 04181 if (acfptr == NULL) { 04182 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04183 } else if (!acfptr->read && !acfptr->read2) { 04184 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04185 } else if (!is_read_allowed(acfptr)) { 04186 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04187 } else { 04188 if (acfptr->mod) { 04189 u = __ast_module_user_add(acfptr->mod, chan); 04190 } 04191 ast_str_reset(*str); 04192 if (acfptr->read2) { 04193 /* ast_str enabled */ 04194 res = acfptr->read2(chan, copy, args, str, maxlen); 04195 } else { 04196 /* Legacy function pointer, allocate buffer for result */ 04197 int maxsize = ast_str_size(*str); 04198 if (maxlen > -1) { 04199 if (maxlen == 0) { 04200 if (acfptr->read_max) { 04201 maxsize = acfptr->read_max; 04202 } else { 04203 maxsize = VAR_BUF_SIZE; 04204 } 04205 } else { 04206 maxsize = maxlen; 04207 } 04208 ast_str_make_space(str, maxsize); 04209 } 04210 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 04211 } 04212 if (acfptr->mod && u) { 04213 __ast_module_user_remove(acfptr->mod, u); 04214 } 04215 return res; 04216 } 04217 return -1; 04218 }
| int ast_func_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| const char * | value | |||
| ) |
executes a write operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| value | A value parameter to pass for writing |
This application executes a function in write mode on a given channel.
| 0 | success | |
| non-zero | failure |
Definition at line 4220 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), is_write_allowed(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
04221 { 04222 char *copy = ast_strdupa(function); 04223 char *args = func_args(copy); 04224 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04225 04226 if (acfptr == NULL) { 04227 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04228 } else if (!acfptr->write) { 04229 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 04230 } else if (!is_write_allowed(acfptr)) { 04231 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy); 04232 } else { 04233 int res; 04234 struct ast_module_user *u = NULL; 04235 if (acfptr->mod) 04236 u = __ast_module_user_add(acfptr->mod, chan); 04237 res = acfptr->write(chan, copy, args, value); 04238 if (acfptr->mod && u) 04239 __ast_module_user_remove(acfptr->mod, u); 04240 return res; 04241 } 04242 04243 return -1; 04244 }
| const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10901 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_compile_ael2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), ast_remove_hint(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10902 { 10903 return con ? con->name : NULL; 10904 }
| const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10939 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10940 { 10941 return c ? c->registrar : NULL; 10942 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10969 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), get_parking_exten(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
10970 { 10971 return e ? e->app : NULL; 10972 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10974 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().
10975 { 10976 return e ? e->data : NULL; 10977 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10964 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10965 { 10966 return e ? e->cidmatch : NULL; 10967 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10906 of file pbx.c.
References ast_exten::parent.
Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
10907 { 10908 return exten ? exten->parent : NULL; 10909 }
| const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 10916 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10917 { 10918 return exten ? exten->label : NULL; 10919 }
| int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 10959 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10960 { 10961 return e ? e->matchcid : 0; 10962 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10911 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint(), ast_remove_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), destroy_hint(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().
10912 { 10913 return exten ? exten->exten : NULL; 10914 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10931 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().
10932 { 10933 return exten ? exten->priority : -1; 10934 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10944 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10945 { 10946 return e ? e->registrar : NULL; 10947 }
| int ast_get_hint | ( | char * | hint, | |
| int | hintsize, | |||
| char * | name, | |||
| int | namesize, | |||
| struct ast_channel * | c, | |||
| const char * | context, | |||
| const char * | exten | |||
| ) |
Get hint for channel.
If an extension hint exists, return non-zero.
Definition at line 5315 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().
05316 { 05317 struct ast_exten *e = ast_hint_extension(c, context, exten); 05318 05319 if (e) { 05320 if (hint) 05321 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05322 if (name) { 05323 const char *tmp = ast_get_extension_app_data(e); 05324 if (tmp) 05325 ast_copy_string(name, tmp, namesize); 05326 } 05327 return -1; 05328 } 05329 return 0; 05330 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10926 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().
10927 { 10928 return ip ? ip->pattern : NULL; 10929 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10954 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().
10955 { 10956 return ip ? ip->registrar : NULL; 10957 }
| const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 10921 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().
10922 { 10923 return inc ? inc->name : NULL; 10924 }
| const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 10949 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().
10950 { 10951 return i ? i->registrar : NULL; 10952 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10984 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().
10985 { 10986 return sw ? sw->data : NULL; 10987 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10989 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10990 { 10991 return sw->eval; 10992 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10979 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().
10980 { 10981 return sw ? sw->name : NULL; 10982 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10994 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().
10995 { 10996 return sw ? sw->registrar : NULL; 10997 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 11089 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
11090 { 11091 return __ast_goto_if_exists(chan, context, exten, priority, 0); 11092 }
| int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) |
hashtable functions for contexts
Definition at line 1092 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01093 { 01094 const struct ast_context *ac = ah_a; 01095 const struct ast_context *bc = ah_b; 01096 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01097 return 1; 01098 /* assume context names are registered in a string table! */ 01099 return strcmp(ac->name, bc->name); 01100 }
| unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1144 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01145 { 01146 const struct ast_context *ac = obj; 01147 return ast_hashtab_hash_string(ac->name); 01148 }
| static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten | |||
| ) | [static, read] |
Definition at line 4792 of file pbx.c.
References ast_hint_extension_nolock(), ast_rdlock_contexts(), and ast_unlock_contexts().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), ast_get_hint(), and ast_str_get_hint().
04793 { 04794 struct ast_exten *e; 04795 ast_rdlock_contexts(); 04796 e = ast_hint_extension_nolock(c, context, exten); 04797 ast_unlock_contexts(); 04798 return e; 04799 }
| static struct ast_exten* ast_hint_extension_nolock | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten | |||
| ) | [static, read] |
Find hint for given extension in context.
Definition at line 4786 of file pbx.c.
References E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by ast_hint_extension(), and ast_merge_contexts_and_delete().
04787 { 04788 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04789 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04790 }
| int ast_ignore_pattern | ( | const char * | context, | |
| const char * | pattern | |||
| ) |
Checks to see if a number should be ignored.
| context | context to search within | |
| pattern | to check whether it should be ignored or not |
Check if a number should be ignored with respect to dialtone cancellation.
| 0 | if the pattern should not be ignored | |
| non-zero | if the pattern should be ignored |
Definition at line 8573 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), and skinny_ss().
08574 { 08575 struct ast_context *con = ast_context_find(context); 08576 08577 if (con) { 08578 struct ast_ignorepat *pat; 08579 08580 for (pat = con->ignorepats; pat; pat = pat->next) { 08581 if (ast_extension_match(pat->pattern, pattern)) 08582 return 1; 08583 } 08584 } 08585 08586 return 0; 08587 }
| 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 5373 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().
05374 { 05375 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05376 }
| 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 7870 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().
07871 { 07872 double ft; 07873 struct ast_context *tmp; 07874 struct ast_context *oldcontextslist; 07875 struct ast_hashtab *oldtable; 07876 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07877 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07878 struct store_hint *saved_hint; 07879 struct ast_hint *hint; 07880 struct ast_exten *exten; 07881 int length; 07882 struct ast_state_cb *thiscb; 07883 struct ast_hashtab_iter *iter; 07884 struct ao2_iterator i; 07885 struct timeval begintime; 07886 struct timeval writelocktime; 07887 struct timeval endlocktime; 07888 struct timeval enddeltime; 07889 07890 /* 07891 * It is very important that this function hold the hints 07892 * container lock _and_ the conlock during its operation; not 07893 * only do we need to ensure that the list of contexts and 07894 * extensions does not change, but also that no hint callbacks 07895 * (watchers) are added or removed during the merge/delete 07896 * process 07897 * 07898 * In addition, the locks _must_ be taken in this order, because 07899 * there are already other code paths that use this order 07900 */ 07901 07902 begintime = ast_tvnow(); 07903 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07904 ast_wrlock_contexts(); 07905 iter = ast_hashtab_start_traversal(contexts_table); 07906 while ((tmp = ast_hashtab_next(iter))) { 07907 context_merge(extcontexts, exttable, tmp, registrar); 07908 } 07909 ast_hashtab_end_traversal(iter); 07910 07911 ao2_lock(hints); 07912 writelocktime = ast_tvnow(); 07913 07914 /* preserve all watchers for hints */ 07915 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07916 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07917 if (ao2_container_count(hint->callbacks)) { 07918 ao2_lock(hint); 07919 if (!hint->exten) { 07920 /* The extension has already been destroyed. (Should never happen here) */ 07921 ao2_unlock(hint); 07922 continue; 07923 } 07924 07925 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07926 + sizeof(*saved_hint); 07927 if (!(saved_hint = ast_calloc(1, length))) { 07928 ao2_unlock(hint); 07929 continue; 07930 } 07931 07932 /* This removes all the callbacks from the hint into saved_hint. */ 07933 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07934 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07935 /* 07936 * We intentionally do not unref thiscb to account for the 07937 * non-ao2 reference in saved_hint->callbacks 07938 */ 07939 } 07940 07941 saved_hint->laststate = hint->laststate; 07942 saved_hint->context = saved_hint->data; 07943 strcpy(saved_hint->data, hint->exten->parent->name); 07944 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07945 strcpy(saved_hint->exten, hint->exten->exten); 07946 ao2_unlock(hint); 07947 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07948 } 07949 } 07950 ao2_iterator_destroy(&i); 07951 07952 /* save the old table and list */ 07953 oldtable = contexts_table; 07954 oldcontextslist = contexts; 07955 07956 /* move in the new table and list */ 07957 contexts_table = exttable; 07958 contexts = *extcontexts; 07959 07960 /* 07961 * Restore the watchers for hints that can be found; notify 07962 * those that cannot be restored. 07963 */ 07964 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07965 struct pbx_find_info q = { .stacklen = 0 }; 07966 07967 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07968 PRIORITY_HINT, NULL, "", E_MATCH); 07969 /* 07970 * If this is a pattern, dynamically create a new extension for this 07971 * particular match. Note that this will only happen once for each 07972 * individual extension, because the pattern will no longer match first. 07973 */ 07974 if (exten && exten->exten[0] == '_') { 07975 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07976 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07977 exten->registrar); 07978 /* rwlocks are not recursive locks */ 07979 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07980 saved_hint->exten); 07981 } 07982 07983 /* Find the hint in the hints container */ 07984 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07985 if (!hint) { 07986 /* 07987 * Notify watchers of this removed hint later when we aren't 07988 * encumberd by so many locks. 07989 */ 07990 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07991 } else { 07992 ao2_lock(hint); 07993 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07994 ao2_link(hint->callbacks, thiscb); 07995 /* Ref that we added when putting into saved_hint->callbacks */ 07996 ao2_ref(thiscb, -1); 07997 } 07998 hint->laststate = saved_hint->laststate; 07999 ao2_unlock(hint); 08000 ao2_ref(hint, -1); 08001 ast_free(saved_hint); 08002 } 08003 } 08004 08005 ao2_unlock(hints); 08006 ast_unlock_contexts(); 08007 08008 /* 08009 * Notify watchers of all removed hints with the same lock 08010 * environment as handle_statechange(). 08011 */ 08012 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 08013 /* this hint has been removed, notify the watchers */ 08014 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08015 thiscb->change_cb(saved_hint->context, saved_hint->exten, 08016 AST_EXTENSION_REMOVED, thiscb->data); 08017 /* Ref that we added when putting into saved_hint->callbacks */ 08018 ao2_ref(thiscb, -1); 08019 } 08020 ast_free(saved_hint); 08021 } 08022 08023 ast_mutex_unlock(&context_merge_lock); 08024 endlocktime = ast_tvnow(); 08025 08026 /* 08027 * The old list and hashtab no longer are relevant, delete them 08028 * while the rest of asterisk is now freely using the new stuff 08029 * instead. 08030 */ 08031 08032 ast_hashtab_destroy(oldtable, NULL); 08033 08034 for (tmp = oldcontextslist; tmp; ) { 08035 struct ast_context *next; /* next starting point */ 08036 08037 next = tmp->next; 08038 __ast_internal_context_destroy(tmp); 08039 tmp = next; 08040 } 08041 enddeltime = ast_tvnow(); 08042 08043 ft = ast_tvdiff_us(writelocktime, begintime); 08044 ft /= 1000000.0; 08045 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 08046 08047 ft = ast_tvdiff_us(endlocktime, writelocktime); 08048 ft /= 1000000.0; 08049 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 08050 08051 ft = ast_tvdiff_us(enddeltime, endlocktime); 08052 ft /= 1000000.0; 08053 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 08054 08055 ft = ast_tvdiff_us(enddeltime, begintime); 08056 ft /= 1000000.0; 08057 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 08058 }
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 11154 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().
11155 { 11156 return pbx_parseable_goto(chan, goto_string, 0); 11157 }
| int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 11235 of file pbx.c.
References ao2_container_alloc, ast_register_atexit(), HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hints, pbx_shutdown(), statecbs, and statecbs_cmp().
Referenced by main().
11236 { 11237 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 11238 statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); 11239 11240 ast_register_atexit(pbx_shutdown); 11241 11242 return (hints && statecbs) ? 0 : -1; 11243 }
| int ast_pbx_outgoing_app | ( | const char * | type, | |
| format_t | format, | |||
| void * | data, | |||
| int | timeout, | |||
| const char * | app, | |||
| const char * | appdata, | |||
| int * | reason, | |||
| int | sync, | |||
| const char * | cid_num, | |||
| const char * | cid_name, | |||
| struct ast_variable * | vars, | |||
| const char * | account, | |||
| struct ast_channel ** | locked_channel | |||
| ) |
Synchronously or asynchronously make an outbound call and send it to a particular application with given extension
Definition at line 9467 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
09468 { 09469 struct ast_channel *chan; 09470 struct app_tmp *tmp; 09471 int res = -1, cdr_res = -1; 09472 struct outgoing_helper oh; 09473 09474 memset(&oh, 0, sizeof(oh)); 09475 oh.vars = vars; 09476 oh.account = account; 09477 09478 if (locked_channel) 09479 *locked_channel = NULL; 09480 if (ast_strlen_zero(app)) { 09481 res = -1; 09482 goto outgoing_app_cleanup; 09483 } 09484 if (synchronous) { 09485 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09486 if (chan) { 09487 ast_set_variables(chan, vars); 09488 if (account) 09489 ast_cdr_setaccount(chan, account); 09490 if (chan->_state == AST_STATE_UP) { 09491 res = 0; 09492 ast_verb(4, "Channel %s was answered.\n", chan->name); 09493 tmp = ast_calloc(1, sizeof(*tmp)); 09494 if (!tmp || ast_string_field_init(tmp, 252)) { 09495 if (tmp) { 09496 ast_free(tmp); 09497 } 09498 res = -1; 09499 } else { 09500 ast_string_field_set(tmp, app, app); 09501 ast_string_field_set(tmp, data, appdata); 09502 tmp->chan = chan; 09503 if (synchronous > 1) { 09504 if (locked_channel) 09505 ast_channel_unlock(chan); 09506 ast_pbx_run_app(tmp); 09507 } else { 09508 if (locked_channel) 09509 ast_channel_lock(chan); 09510 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09511 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09512 ast_string_field_free_memory(tmp); 09513 ast_free(tmp); 09514 if (locked_channel) 09515 ast_channel_unlock(chan); 09516 ast_hangup(chan); 09517 res = -1; 09518 } else { 09519 if (locked_channel) 09520 *locked_channel = chan; 09521 } 09522 } 09523 } 09524 } else { 09525 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09526 if (chan->cdr) { /* update the cdr */ 09527 /* here we update the status of the call, which sould be busy. 09528 * if that fails then we set the status to failed */ 09529 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09530 ast_cdr_failed(chan->cdr); 09531 } 09532 ast_hangup(chan); 09533 } 09534 } 09535 09536 if (res < 0) { /* the call failed for some reason */ 09537 if (*reason == 0) { /* if the call failed (not busy or no answer) 09538 * update the cdr with the failed message */ 09539 cdr_res = ast_pbx_outgoing_cdr_failed(); 09540 if (cdr_res != 0) { 09541 res = cdr_res; 09542 goto outgoing_app_cleanup; 09543 } 09544 } 09545 } 09546 09547 } else { 09548 struct async_stat *as; 09549 if (!(as = ast_calloc(1, sizeof(*as)))) { 09550 res = -1; 09551 goto outgoing_app_cleanup; 09552 } 09553 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09554 if (!chan) { 09555 ast_free(as); 09556 res = -1; 09557 goto outgoing_app_cleanup; 09558 } 09559 as->chan = chan; 09560 ast_copy_string(as->app, app, sizeof(as->app)); 09561 if (appdata) 09562 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09563 as->timeout = timeout; 09564 ast_set_variables(chan, vars); 09565 if (account) 09566 ast_cdr_setaccount(chan, account); 09567 /* Start a new thread, and get something handling this channel. */ 09568 if (locked_channel) 09569 ast_channel_lock(chan); 09570 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09571 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09572 ast_free(as); 09573 if (locked_channel) 09574 ast_channel_unlock(chan); 09575 ast_hangup(chan); 09576 res = -1; 09577 goto outgoing_app_cleanup; 09578 } else { 09579 if (locked_channel) 09580 *locked_channel = chan; 09581 } 09582 res = 0; 09583 } 09584 outgoing_app_cleanup: 09585 ast_variables_destroy(vars); 09586 return res; 09587 }
| static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 9271 of file pbx.c.
References ast_cdr_alloc(), ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_unref, ast_dummy_channel_alloc, and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
09272 { 09273 /* allocate a channel */ 09274 struct ast_channel *chan = ast_dummy_channel_alloc(); 09275 09276 if (!chan) 09277 return -1; /* failure */ 09278 09279 chan->cdr = ast_cdr_alloc(); 09280 if (!chan->cdr) { 09281 /* allocation of the cdr failed */ 09282 chan = ast_channel_unref(chan); /* free the channel */ 09283 return -1; /* return failure */ 09284 } 09285 09286 /* allocation of the cdr was successful */ 09287 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 09288 ast_cdr_start(chan->cdr); /* record the start and stop time */ 09289 ast_cdr_end(chan->cdr); 09290 ast_cdr_failed(chan->cdr); /* set the status to failed */ 09291 ast_cdr_detach(chan->cdr); /* post and free the record */ 09292 chan->cdr = NULL; 09293 chan = ast_channel_unref(chan); /* free the channel */ 09294 09295 return 0; /* success */ 09296 }
| int ast_pbx_outgoing_exten | ( | const char * | type, | |
| format_t | format, | |||
| void * | data, | |||
| int | timeout, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int * | reason, | |||
| int | sync, | |||
| const char * | cid_num, | |||
| const char * | cid_name, | |||
| struct ast_variable * | vars, | |||
| const char * | account, | |||
| struct ast_channel ** | locked_channel | |||
| ) |
Synchronously or asynchronously make an outbound call and send it to a particular extension
Definition at line 9298 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
09299 { 09300 struct ast_channel *chan; 09301 struct async_stat *as; 09302 int res = -1, cdr_res = -1; 09303 struct outgoing_helper oh; 09304 09305 if (synchronous) { 09306 oh.context = context; 09307 oh.exten = exten; 09308 oh.priority = priority; 09309 oh.cid_num = cid_num; 09310 oh.cid_name = cid_name; 09311 oh.account = account; 09312 oh.vars = vars; 09313 oh.parent_channel = NULL; 09314 09315 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09316 if (channel) { 09317 *channel = chan; 09318 if (chan) 09319 ast_channel_lock(chan); 09320 } 09321 if (chan) { 09322 if (chan->_state == AST_STATE_UP) { 09323 res = 0; 09324 ast_verb(4, "Channel %s was answered.\n", chan->name); 09325 09326 if (synchronous > 1) { 09327 if (channel) 09328 ast_channel_unlock(chan); 09329 if (ast_pbx_run(chan)) { 09330 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09331 if (channel) 09332 *channel = NULL; 09333 ast_hangup(chan); 09334 chan = NULL; 09335 res = -1; 09336 } 09337 } else { 09338 if (ast_pbx_start(chan)) { 09339 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09340 if (channel) { 09341 *channel = NULL; 09342 ast_channel_unlock(chan); 09343 } 09344 ast_hangup(chan); 09345 res = -1; 09346 } 09347 chan = NULL; 09348 } 09349 } else { 09350 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09351 09352 if (chan->cdr) { /* update the cdr */ 09353 /* here we update the status of the call, which sould be busy. 09354 * if that fails then we set the status to failed */ 09355 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09356 ast_cdr_failed(chan->cdr); 09357 } 09358 09359 if (channel) { 09360 *channel = NULL; 09361 ast_channel_unlock(chan); 09362 } 09363 ast_hangup(chan); 09364 chan = NULL; 09365 } 09366 } 09367 09368 if (res < 0) { /* the call failed for some reason */ 09369 if (*reason == 0) { /* if the call failed (not busy or no answer) 09370 * update the cdr with the failed message */ 09371 cdr_res = ast_pbx_outgoing_cdr_failed(); 09372 if (cdr_res != 0) { 09373 res = cdr_res; 09374 goto outgoing_exten_cleanup; 09375 } 09376 } 09377 09378 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09379 /* check if "failed" exists */ 09380 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09381 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09382 if (chan) { 09383 char failed_reason[4] = ""; 09384 if (!ast_strlen_zero(context)) 09385 ast_copy_string(chan->context, context, sizeof(chan->context)); 09386 set_ext_pri(chan, "failed", 1); 09387 ast_set_variables(chan, vars); 09388 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09389 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09390 if (account) 09391 ast_cdr_setaccount(chan, account); 09392 if (ast_pbx_run(chan)) { 09393 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09394 ast_hangup(chan); 09395 } 09396 chan = NULL; 09397 } 09398 } 09399 } 09400 } else { 09401 if (!(as = ast_calloc(1, sizeof(*as)))) { 09402 res = -1; 09403 goto outgoing_exten_cleanup; 09404 } 09405 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09406 if (channel) { 09407 *channel = chan; 09408 if (chan) 09409 ast_channel_lock(chan); 09410 } 09411 if (!chan) { 09412 ast_free(as); 09413 res = -1; 09414 goto outgoing_exten_cleanup; 09415 } 09416 as->chan = chan; 09417 ast_copy_string(as->context, context, sizeof(as->context)); 09418 set_ext_pri(as->chan, exten, priority); 09419 as->timeout = timeout; 09420 ast_set_variables(chan, vars); 09421 if (account) 09422 ast_cdr_setaccount(chan, account); 09423 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09424 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09425 ast_free(as); 09426 if (channel) { 09427 *channel = NULL; 09428 ast_channel_unlock(chan); 09429 } 09430 ast_hangup(chan); 09431 res = -1; 09432 goto outgoing_exten_cleanup; 09433 } 09434 res = 0; 09435 } 09436 outgoing_exten_cleanup: 09437 ast_variables_destroy(vars); 09438 return res; 09439 }
| enum ast_pbx_result ast_pbx_run | ( | struct ast_channel * | c | ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
| Zero | on success | |
| non-zero | on failure |
Definition at line 5879 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().
05880 { 05881 return ast_pbx_run_args(c, NULL); 05882 }
| static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 9451 of file pbx.c.
References app_tmp::app, ast_free, ast_hangup(), ast_log(), ast_string_field_free_memory, ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, pbx_exec(), and pbx_findapp().
Referenced by ast_pbx_outgoing_app().
09452 { 09453 struct app_tmp *tmp = data; 09454 struct ast_app *app; 09455 app = pbx_findapp(tmp->app); 09456 if (app) { 09457 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 09458 pbx_exec(tmp->chan, app, tmp->data); 09459 } else 09460 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 09461 ast_hangup(tmp->chan); 09462 ast_string_field_free_memory(tmp); 09463 ast_free(tmp); 09464 return NULL; 09465 }
| enum ast_pbx_result ast_pbx_run_args | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on | |
| args | options for the pbx |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
| Zero | on success | |
| non-zero | on failure |
Definition at line 5859 of file pbx.c.
References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
05860 { 05861 enum ast_pbx_result res = AST_PBX_SUCCESS; 05862 05863 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05864 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05865 return AST_PBX_FAILED; 05866 } 05867 05868 if (increase_call_count(c)) { 05869 return AST_PBX_CALL_LIMIT; 05870 } 05871 05872 res = __ast_pbx_run(c, args); 05873 05874 decrease_call_count(); 05875 05876 return res; 05877 }
| 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 5832 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), skinny_new(), and unistim_new().
05833 { 05834 pthread_t t; 05835 05836 if (!c) { 05837 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05838 return AST_PBX_FAILED; 05839 } 05840 05841 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05842 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05843 return AST_PBX_FAILED; 05844 } 05845 05846 if (increase_call_count(c)) 05847 return AST_PBX_CALL_LIMIT; 05848 05849 /* Start a new thread, and get something handling this channel. */ 05850 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05851 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05852 decrease_call_count(); 05853 return AST_PBX_FAILED; 05854 } 05855 05856 return AST_PBX_SUCCESS; 05857 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5889 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05890 { 05891 return totalcalls; 05892 }
| 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 10888 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().
10889 { 10890 return ast_rwlock_rdlock(&con->lock); 10891 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 10870 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().
10871 { 10872 return ast_mutex_lock(&conlock); 10873 }
| int ast_register_application2 | ( | const char * | app, | |
| int(*)(struct ast_channel *, const char *) | execute, | |||
| const char * | synopsis, | |||
| const char * | description, | |||
| void * | mod | |||
| ) |
Dynamically register a new dial plan application.
Register an application.
Definition at line 6297 of file pbx.c.
References ast_app::arguments, ast_calloc, ast_free, ast_log(), ast_module_name(), 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_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_verb, AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), COLOR_BRCYAN, ast_app::docsrc, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, ast_app::seealso, ast_app::syntax, and term_color().
Referenced by ast_cc_init(), ast_features_init(), and load_pbx().
06298 { 06299 struct ast_app *tmp, *cur = NULL; 06300 char tmps[80]; 06301 int length, res; 06302 #ifdef AST_XML_DOCS 06303 char *tmpxml; 06304 #endif 06305 06306 AST_RWLIST_WRLOCK(&apps); 06307 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 06308 if (!(res = strcasecmp(app, tmp->name))) { 06309 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 06310 AST_RWLIST_UNLOCK(&apps); 06311 return -1; 06312 } else if (res < 0) 06313 break; 06314 } 06315 06316 length = sizeof(*tmp) + strlen(app) + 1; 06317 06318 if (!(tmp = ast_calloc(1, length))) { 06319 AST_RWLIST_UNLOCK(&apps); 06320 return -1; 06321 } 06322 06323 if (ast_string_field_init(tmp, 128)) { 06324 AST_RWLIST_UNLOCK(&apps); 06325 ast_free(tmp); 06326 return -1; 06327 } 06328 06329 strcpy(tmp->name, app); 06330 tmp->execute = execute; 06331 tmp->module = mod; 06332 06333 #ifdef AST_XML_DOCS 06334 /* Try to lookup the docs in our XML documentation database */ 06335 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 06336 /* load synopsis */ 06337 tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module)); 06338 ast_string_field_set(tmp, synopsis, tmpxml); 06339 ast_free(tmpxml); 06340 06341 /* load description */ 06342 tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); 06343 ast_string_field_set(tmp, description, tmpxml); 06344 ast_free(tmpxml); 06345 06346 /* load syntax */ 06347 tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module)); 06348 ast_string_field_set(tmp, syntax, tmpxml); 06349 ast_free(tmpxml); 06350 06351 /* load arguments */ 06352 tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module)); 06353 ast_string_field_set(tmp, arguments, tmpxml); 06354 ast_free(tmpxml); 06355 06356 /* load seealso */ 06357 tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module)); 06358 ast_string_field_set(tmp, seealso, tmpxml); 06359 ast_free(tmpxml); 06360 tmp->docsrc = AST_XML_DOC; 06361 } else { 06362 #endif 06363 ast_string_field_set(tmp, synopsis, synopsis); 06364 ast_string_field_set(tmp, description, description); 06365 #ifdef AST_XML_DOCS 06366 tmp->docsrc = AST_STATIC_DOC; 06367 } 06368 #endif 06369 06370 /* Store in alphabetical order */ 06371 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 06372 if (strcasecmp(tmp->name, cur->name) < 0) { 06373 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 06374 break; 06375 } 06376 } 06377 AST_RWLIST_TRAVERSE_SAFE_END; 06378 if (!cur) 06379 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 06380 06381 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 06382 06383 AST_RWLIST_UNLOCK(&apps); 06384 06385 return 0; 06386 }
| int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
| sw | switch to register |
This function registers a populated ast_switch structure with the asterisk switching architecture.
| 0 | success | |
| non-zero | failure |
Definition at line 6392 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().
06393 { 06394 struct ast_switch *tmp; 06395 06396 AST_RWLIST_WRLOCK(&switches); 06397 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06398 if (!strcasecmp(tmp->name, sw->name)) { 06399 AST_RWLIST_UNLOCK(&switches); 06400 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06401 return -1; 06402 } 06403 } 06404 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06405 AST_RWLIST_UNLOCK(&switches); 06406 06407 return 0; 06408 }
| static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 5194 of file pbx.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::context_name, ast_hint::exten, ast_hint::exten_name, hints, and OBJ_UNLINK.
Referenced by destroy_exten().
05195 { 05196 /* Cleanup the Notifys if hint is removed */ 05197 struct ast_hint *hint; 05198 05199 if (!e) { 05200 return -1; 05201 } 05202 05203 hint = ao2_find(hints, e, OBJ_UNLINK); 05204 if (!hint) { 05205 return -1; 05206 } 05207 05208 /* 05209 * The extension is being destroyed so we must save some 05210 * information to notify that the extension is deactivated. 05211 */ 05212 ao2_lock(hint); 05213 ast_copy_string(hint->context_name, 05214 ast_get_context_name(ast_get_extension_context(hint->exten)), 05215 sizeof(hint->context_name)); 05216 ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten), 05217 sizeof(hint->exten_name)); 05218 hint->exten = NULL; 05219 ao2_unlock(hint); 05220 05221 ao2_ref(hint, -1); 05222 05223 return 0; 05224 }
| 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 5378 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().
05379 { 05380 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05381 }
| 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 | |||
| ) |
Get hint for channel.
If an extension hint exists, return non-zero.
Definition at line 5333 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().
05334 { 05335 struct ast_exten *e = ast_hint_extension(c, context, exten); 05336 05337 if (!e) { 05338 return 0; 05339 } 05340 05341 if (hint) { 05342 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05343 } 05344 if (name) { 05345 const char *tmp = ast_get_extension_app_data(e); 05346 if (tmp) { 05347 ast_str_set(name, namesize, "%s", tmp); 05348 } 05349 } 05350 return -1; 05351 }
| 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 3403 of file pbx.c.
References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03404 { 03405 const char not_found = '\0'; 03406 char *tmpvar; 03407 const char *ret; 03408 const char *s; /* the result */ 03409 int offset, length; 03410 int i, need_substring; 03411 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03412 char workspace[20]; 03413 03414 if (c) { 03415 ast_channel_lock(c); 03416 places[0] = &c->varshead; 03417 } 03418 /* 03419 * Make a copy of var because parse_variable_name() modifies the string. 03420 * Then if called directly, we might need to run substring() on the result; 03421 * remember this for later in 'need_substring', 'offset' and 'length' 03422 */ 03423 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03424 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03425 03426 /* 03427 * Look first into predefined variables, then into variable lists. 03428 * Variable 's' points to the result, according to the following rules: 03429 * s == ¬_found (set at the beginning) means that we did not find a 03430 * matching variable and need to look into more places. 03431 * If s != ¬_found, s is a valid result string as follows: 03432 * s = NULL if the variable does not have a value; 03433 * you typically do this when looking for an unset predefined variable. 03434 * s = workspace if the result has been assembled there; 03435 * typically done when the result is built e.g. with an snprintf(), 03436 * so we don't need to do an additional copy. 03437 * s != workspace in case we have a string, that needs to be copied 03438 * (the ast_copy_string is done once for all at the end). 03439 * Typically done when the result is already available in some string. 03440 */ 03441 s = ¬_found; /* default value */ 03442 if (c) { /* This group requires a valid channel */ 03443 /* Names with common parts are looked up a piece at a time using strncmp. */ 03444 if (!strncmp(var, "CALL", 4)) { 03445 if (!strncmp(var + 4, "ING", 3)) { 03446 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03447 ast_str_set(str, maxlen, "%d", 03448 ast_party_id_presentation(&c->caller.id)); 03449 s = ast_str_buffer(*str); 03450 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03451 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03452 s = ast_str_buffer(*str); 03453 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03454 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03455 s = ast_str_buffer(*str); 03456 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03457 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03458 s = ast_str_buffer(*str); 03459 } 03460 } 03461 } else if (!strcmp(var, "HINT")) { 03462 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03463 } else if (!strcmp(var, "HINTNAME")) { 03464 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03465 } else if (!strcmp(var, "EXTEN")) { 03466 s = c->exten; 03467 } else if (!strcmp(var, "CONTEXT")) { 03468 s = c->context; 03469 } else if (!strcmp(var, "PRIORITY")) { 03470 ast_str_set(str, maxlen, "%d", c->priority); 03471 s = ast_str_buffer(*str); 03472 } else if (!strcmp(var, "CHANNEL")) { 03473 s = c->name; 03474 } else if (!strcmp(var, "UNIQUEID")) { 03475 s = c->uniqueid; 03476 } else if (!strcmp(var, "HANGUPCAUSE")) { 03477 ast_str_set(str, maxlen, "%d", c->hangupcause); 03478 s = ast_str_buffer(*str); 03479 } 03480 } 03481 if (s == ¬_found) { /* look for more */ 03482 if (!strcmp(var, "EPOCH")) { 03483 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03484 s = ast_str_buffer(*str); 03485 } else if (!strcmp(var, "SYSTEMNAME")) { 03486 s = ast_config_AST_SYSTEM_NAME; 03487 } else if (!strcmp(var, "ENTITYID")) { 03488 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03489 s = workspace; 03490 } 03491 } 03492 /* if not found, look into chanvars or global vars */ 03493 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03494 struct ast_var_t *variables; 03495 if (!places[i]) 03496 continue; 03497 if (places[i] == &globals) 03498 ast_rwlock_rdlock(&globalslock); 03499 AST_LIST_TRAVERSE(places[i], variables, entries) { 03500 if (!strcasecmp(ast_var_name(variables), var)) { 03501 s = ast_var_value(variables); 03502 break; 03503 } 03504 } 03505 if (places[i] == &globals) 03506 ast_rwlock_unlock(&globalslock); 03507 } 03508 if (s == ¬_found || s == NULL) { 03509 ast_debug(5, "Result of '%s' is NULL\n", var); 03510 ret = NULL; 03511 } else { 03512 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03513 if (s != ast_str_buffer(*str)) { 03514 ast_str_set(str, maxlen, "%s", s); 03515 } 03516 ret = ast_str_buffer(*str); 03517 if (need_substring) { 03518 ret = ast_str_substring(*str, offset, length); 03519 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03520 } 03521 } 03522 03523 if (c) { 03524 ast_channel_unlock(c); 03525 } 03526 return ret; 03527 }
| 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 4425 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().
04426 { 04427 size_t used; 04428 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04429 }
| 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 4246 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().
04247 { 04248 /* Substitutes variables into buf, based on string templ */ 04249 char *cp4 = NULL; 04250 const char *tmp, *whereweare; 04251 int orig_size = 0; 04252 int offset, offset2, isfunction; 04253 const char *nextvar, *nextexp, *nextthing; 04254 const char *vars, *vare; 04255 char *finalvars; 04256 int pos, brackets, needsub, len; 04257 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04258 04259 ast_str_reset(*buf); 04260 whereweare = tmp = templ; 04261 while (!ast_strlen_zero(whereweare)) { 04262 /* reset our buffer */ 04263 ast_str_reset(substr3); 04264 04265 /* Assume we're copying the whole remaining string */ 04266 pos = strlen(whereweare); 04267 nextvar = NULL; 04268 nextexp = NULL; 04269 nextthing = strchr(whereweare, '$'); 04270 if (nextthing) { 04271 switch (nextthing[1]) { 04272 case '{': 04273 nextvar = nextthing; 04274 pos = nextvar - whereweare; 04275 break; 04276 case '[': 04277 nextexp = nextthing; 04278 pos = nextexp - whereweare; 04279 break; 04280 default: 04281 pos = 1; 04282 } 04283 } 04284 04285 if (pos) { 04286 /* Copy that many bytes */ 04287 ast_str_append_substr(buf, maxlen, whereweare, pos); 04288 04289 templ += pos; 04290 whereweare += pos; 04291 } 04292 04293 if (nextvar) { 04294 /* We have a variable. Find the start and end, and determine 04295 if we are going to have to recursively call ourselves on the 04296 contents */ 04297 vars = vare = nextvar + 2; 04298 brackets = 1; 04299 needsub = 0; 04300 04301 /* Find the end of it */ 04302 while (brackets && *vare) { 04303 if ((vare[0] == '$') && (vare[1] == '{')) { 04304 needsub++; 04305 } else if (vare[0] == '{') { 04306 brackets++; 04307 } else if (vare[0] == '}') { 04308 brackets--; 04309 } else if ((vare[0] == '$') && (vare[1] == '[')) 04310 needsub++; 04311 vare++; 04312 } 04313 if (brackets) 04314 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04315 len = vare - vars - 1; 04316 04317 /* Skip totally over variable string */ 04318 whereweare += (len + 3); 04319 04320 /* Store variable name (and truncate) */ 04321 ast_str_set_substr(&substr1, 0, vars, len); 04322 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04323 04324 /* Substitute if necessary */ 04325 if (needsub) { 04326 size_t used; 04327 if (!substr2) { 04328 substr2 = ast_str_create(16); 04329 } 04330 04331 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04332 finalvars = ast_str_buffer(substr2); 04333 } else { 04334 finalvars = ast_str_buffer(substr1); 04335 } 04336 04337 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04338 if (isfunction) { 04339 /* Evaluate function */ 04340 if (c || !headp) { 04341 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04342 } else { 04343 struct varshead old; 04344 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04345 if (bogus) { 04346 memcpy(&old, &bogus->varshead, sizeof(old)); 04347 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04348 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04349 /* Don't deallocate the varshead that was passed in */ 04350 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04351 ast_channel_unref(bogus); 04352 } else { 04353 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04354 } 04355 } 04356 ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)"); 04357 } else { 04358 /* Retrieve variable value */ 04359 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04360 cp4 = ast_str_buffer(substr3); 04361 } 04362 if (cp4) { 04363 ast_str_substring(substr3, offset, offset2); 04364 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04365 } 04366 } else if (nextexp) { 04367 /* We have an expression. Find the start and end, and determine 04368 if we are going to have to recursively call ourselves on the 04369 contents */ 04370 vars = vare = nextexp + 2; 04371 brackets = 1; 04372 needsub = 0; 04373 04374 /* Find the end of it */ 04375 while (brackets && *vare) { 04376 if ((vare[0] == '$') && (vare[1] == '[')) { 04377 needsub++; 04378 brackets++; 04379 vare++; 04380 } else if (vare[0] == '[') { 04381 brackets++; 04382 } else if (vare[0] == ']') { 04383 brackets--; 04384 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04385 needsub++; 04386 vare++; 04387 } 04388 vare++; 04389 } 04390 if (brackets) 04391 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04392 len = vare - vars - 1; 04393 04394 /* Skip totally over expression */ 04395 whereweare += (len + 3); 04396 04397 /* Store variable name (and truncate) */ 04398 ast_str_set_substr(&substr1, 0, vars, len); 04399 04400 /* Substitute if necessary */ 04401 if (needsub) { 04402 size_t used; 04403 if (!substr2) { 04404 substr2 = ast_str_create(16); 04405 } 04406 04407 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04408 finalvars = ast_str_buffer(substr2); 04409 } else { 04410 finalvars = ast_str_buffer(substr1); 04411 } 04412 04413 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04414 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04415 } 04416 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04417 } 04418 } 04419 *used = ast_str_strlen(*buf) - orig_size; 04420 ast_free(substr1); 04421 ast_free(substr2); 04422 ast_free(substr3); 04423 }
| 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 4431 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().
04432 { 04433 size_t used; 04434 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04435 }
| static const char* ast_str_substring | ( | struct ast_str * | value, | |
| int | offset, | |||
| int | length | |||
| ) | [static] |
Definition at line 3338 of file pbx.c.
References ast_str_buffer(), ast_str_reset(), ast_str_strlen(), and ast_str_update().
Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().
03339 { 03340 int lr; /* length of the input string after the copy */ 03341 03342 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 03343 03344 /* Quick check if no need to do anything */ 03345 if (offset == 0 && length >= lr) /* take the whole string */ 03346 return ast_str_buffer(value); 03347 03348 if (offset < 0) { /* translate negative offset into positive ones */ 03349 offset = lr + offset; 03350 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03351 offset = 0; 03352 } 03353 03354 /* too large offset result in empty string so we know what to return */ 03355 if (offset >= lr) { 03356 ast_str_reset(value); 03357 return ast_str_buffer(value); 03358 } 03359 03360 if (offset > 0) { 03361 /* Go ahead and chop off the beginning */ 03362 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 03363 lr -= offset; 03364 } 03365 03366 if (length >= 0 && length < lr) { /* truncate if necessary */ 03367 char *tmp = ast_str_buffer(value); 03368 tmp[length] = '\0'; 03369 ast_str_update(value); 03370 } else if (length < 0) { 03371 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 03372 char *tmp = ast_str_buffer(value); 03373 tmp[lr + length] = '\0'; 03374 ast_str_update(value); 03375 } else { 03376 ast_str_reset(value); 03377 } 03378 } else { 03379 /* Nothing to do, but update the buffer length */ 03380 ast_str_update(value); 03381 } 03382 03383 return ast_str_buffer(value); 03384 }
| int ast_thread_inhibit_escalations | ( | void | ) |
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.
Definition at line 4029 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by handle_tcptls_connection().
04030 { 04031 int *thread_inhibit_escalations; 04032 04033 thread_inhibit_escalations = ast_threadstorage_get( 04034 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04035 04036 if (thread_inhibit_escalations == NULL) { 04037 ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n"); 04038 return -1; 04039 } 04040 04041 *thread_inhibit_escalations = 1; 04042 return 0; 04043 }
| 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 10893 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().
10894 { 10895 return ast_rwlock_unlock(&con->lock); 10896 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 10875 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().
10876 { 10877 return ast_mutex_unlock(&conlock); 10878 }
| int ast_unregister_application | ( | const char * | app | ) |
Unregister an application.
| app | name of the application (does not have to be the same string as the one that was registered) |
This unregisters an application from Asterisk's internal application list.
| 0 | success | |
| -1 | failure |
Definition at line 7643 of file pbx.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, ast_app::name, and unreference_cached_app().
Referenced by __unload_module(), cc_shutdown(), features_shutdown(), load_module(), unload_module(), and unload_pbx().
07644 { 07645 struct ast_app *tmp; 07646 07647 AST_RWLIST_WRLOCK(&apps); 07648 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 07649 if (!strcasecmp(app, tmp->name)) { 07650 unreference_cached_app(tmp); 07651 AST_RWLIST_REMOVE_CURRENT(list); 07652 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 07653 ast_string_field_free_memory(tmp); 07654 ast_free(tmp); 07655 break; 07656 } 07657 } 07658 AST_RWLIST_TRAVERSE_SAFE_END; 07659 AST_RWLIST_UNLOCK(&apps); 07660 07661 return tmp ? 0 : -1; 07662 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6410 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06411 { 06412 AST_RWLIST_WRLOCK(&switches); 06413 AST_RWLIST_REMOVE(&switches, sw, list); 06414 AST_RWLIST_UNLOCK(&switches); 06415 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | exten | |||
| ) | [read] |
Definition at line 11007 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), context_used(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
| struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
| struct ast_ignorepat * | ip | |||
| ) | [read] |
Definition at line 11040 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
11042 { 11043 if (!ip) 11044 return con ? con->ignorepats : NULL; 11045 else 11046 return ip->next; 11047 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 11031 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), context_used(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
| struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
| struct ast_sw * | sw | |||
| ) | [read] |
Definition at line 11016 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11018 { 11019 if (!sw) 11020 return con ? AST_LIST_FIRST(&con->alts) : NULL; 11021 else 11022 return AST_LIST_NEXT(sw, list); 11023 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 11002 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 11025 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().
11027 { 11028 return priority ? priority->peer : exten; 11029 }
| 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 10883 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().
10884 { 10885 return ast_rwlock_wrlock(&con->lock); 10886 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 10865 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().
10866 { 10867 return ast_mutex_lock(&conlock); 10868 }
| static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 9208 of file pbx.c.
References ast_channel::_state, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_free, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_remaining_ms(), AST_STATE_UP, ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, ast_frame::subclass, and async_stat::timeout.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
09209 { 09210 struct async_stat *as = data; 09211 struct ast_channel *chan = as->chan; 09212 int timeout = as->timeout; 09213 int res; 09214 struct ast_frame *f; 09215 struct ast_app *app; 09216 struct timeval start = ast_tvnow(); 09217 int ms; 09218 09219 while ((ms = ast_remaining_ms(start, timeout)) && 09220 chan->_state != AST_STATE_UP) { 09221 res = ast_waitfor(chan, ms); 09222 if (res < 1) 09223 break; 09224 09225 f = ast_read(chan); 09226 if (!f) 09227 break; 09228 if (f->frametype == AST_FRAME_CONTROL) { 09229 if ((f->subclass.integer == AST_CONTROL_BUSY) || 09230 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 09231 ast_frfree(f); 09232 break; 09233 } 09234 } 09235 ast_frfree(f); 09236 } 09237 if (chan->_state == AST_STATE_UP) { 09238 if (!ast_strlen_zero(as->app)) { 09239 app = pbx_findapp(as->app); 09240 if (app) { 09241 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 09242 pbx_exec(chan, app, as->appdata); 09243 } else 09244 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 09245 } else { 09246 if (!ast_strlen_zero(as->context)) 09247 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 09248 if (!ast_strlen_zero(as->exten)) 09249 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 09250 if (as->priority > 0) 09251 chan->priority = as->priority; 09252 /* Run the PBX */ 09253 if (ast_pbx_run(chan)) { 09254 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 09255 } else { 09256 /* PBX will have taken care of this */ 09257 chan = NULL; 09258 } 09259 } 09260 } 09261 ast_free(as); 09262 if (chan) 09263 ast_hangup(chan); 09264 return NULL; 09265 }
| static void cli_match_char_tree | ( | struct match_char * | node, | |
| char * | prefix, | |||
| int | fd | |||
| ) | [static] |
Definition at line 1657 of file pbx.c.
References match_char::alt_char, ast_cli(), ast_str_alloca, ast_str_buffer(), ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, match_char::is_pattern, match_char::next_char, match_char::specificity, and match_char::x.
Referenced by show_debug_helper().
01658 { 01659 char extenstr[40]; 01660 struct ast_str *my_prefix = ast_str_alloca(1024); 01661 01662 extenstr[0] = '\0'; 01663 01664 if (node->exten) { 01665 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01666 } 01667 01668 if (strlen(node->x) > 1) { 01669 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01670 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01671 node->exten ? node->exten->exten : "", extenstr); 01672 } else { 01673 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01674 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01675 node->exten ? node->exten->exten : "", extenstr); 01676 } 01677 01678 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01679 01680 if (node->next_char) 01681 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01682 01683 if (node->alt_char) 01684 cli_match_char_tree(node->alt_char, prefix, fd); 01685 }
| static int collect_digits | ( | struct ast_channel * | c, | |
| int | waittime, | |||
| char * | buf, | |||
| int | buflen, | |||
| int | pos | |||
| ) | [static] |
collect digits from the channel into the buffer.
| c,buf,buflen,pos | ||
| waittime | is in milliseconds |
| 0 | on timeout or done. | |
| -1 | on error. |
Definition at line 5399 of file pbx.c.
References ast_channel::_softhangup, ast_channel_clear_softhangup(), ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::caller, ast_channel::context, ast_pbx::dtimeoutms, ast_party_caller::id, ast_party_id::number, ast_channel::pbx, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by __ast_pbx_run().
05400 { 05401 int digit; 05402 05403 buf[pos] = '\0'; /* make sure it is properly terminated */ 05404 while (ast_matchmore_extension(c, c->context, buf, 1, 05405 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05406 /* As long as we're willing to wait, and as long as it's not defined, 05407 keep reading digits until we can't possibly get a right answer anymore. */ 05408 digit = ast_waitfordigit(c, waittime); 05409 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05410 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05411 } else { 05412 if (!digit) /* No entry */ 05413 break; 05414 if (digit < 0) /* Error, maybe a hangup */ 05415 return -1; 05416 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 05417 buf[pos++] = digit; 05418 buf[pos] = '\0'; 05419 } 05420 waittime = c->pbx->dtimeoutms; 05421 } 05422 } 05423 return 0; 05424 }
| static int compare_char | ( | const void * | a, | |
| const void * | b | |||
| ) | [static] |
Definition at line 1083 of file pbx.c.
Referenced by get_pattern_node().
| static char* complete_core_show_hint | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
autocomplete for CLI command 'core show hint'
Definition at line 6597 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_get_extension_name(), ast_strdup, ast_hint::exten, and hints.
Referenced by handle_show_hint().
06598 { 06599 struct ast_hint *hint; 06600 char *ret = NULL; 06601 int which = 0; 06602 int wordlen; 06603 struct ao2_iterator i; 06604 06605 if (pos != 3) 06606 return NULL; 06607 06608 wordlen = strlen(word); 06609 06610 /* walk through all hints */ 06611 i = ao2_iterator_init(hints, 0); 06612 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06613 ao2_lock(hint); 06614 if (!hint->exten) { 06615 /* The extension has already been destroyed */ 06616 ao2_unlock(hint); 06617 continue; 06618 } 06619 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 06620 ret = ast_strdup(ast_get_extension_name(hint->exten)); 06621 ao2_unlock(hint); 06622 ao2_ref(hint, -1); 06623 break; 06624 } 06625 ao2_unlock(hint); 06626 } 06627 ao2_iterator_destroy(&i); 06628 06629 return ret; 06630 }
| static char* complete_show_dialplan_context | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 6807 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
Referenced by handle_debug_dialplan(), and handle_show_dialplan().
06809 { 06810 struct ast_context *c = NULL; 06811 char *ret = NULL; 06812 int which = 0; 06813 int wordlen; 06814 06815 /* we are do completion of [exten@]context on second position only */ 06816 if (pos != 2) 06817 return NULL; 06818 06819 ast_rdlock_contexts(); 06820 06821 wordlen = strlen(word); 06822 06823 /* walk through all contexts and return the n-th match */ 06824 while ( (c = ast_walk_contexts(c)) ) { 06825 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06826 ret = ast_strdup(ast_get_context_name(c)); 06827 break; 06828 } 06829 } 06830 06831 ast_unlock_contexts(); 06832 06833 return ret; 06834 }
| static void context_merge | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| struct ast_context * | context, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 7784 of file pbx.c.
References ast_exten::app, ast_add_extension2(), ast_context_find_or_create(), ast_hashtab_end_traversal(), ast_hashtab_lookup(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_strdup, ast_verb, ast_exten::cidmatch, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, ast_exten::datad, ast_exten::exten, first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_context::registrar, ast_exten::registrar, and ast_context::root_table.
Referenced by ast_merge_contexts_and_delete().
07785 { 07786 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 07787 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 07788 struct ast_hashtab_iter *exten_iter; 07789 struct ast_hashtab_iter *prio_iter; 07790 int insert_count = 0; 07791 int first = 1; 07792 07793 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 07794 the current registrar, and copy them to the new context. If the new context does not 07795 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 07796 only create the empty matching context if the old one meets the criteria */ 07797 07798 if (context->root_table) { 07799 exten_iter = ast_hashtab_start_traversal(context->root_table); 07800 while ((exten_item=ast_hashtab_next(exten_iter))) { 07801 if (new) { 07802 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 07803 } else { 07804 new_exten_item = NULL; 07805 } 07806 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07807 while ((prio_item=ast_hashtab_next(prio_iter))) { 07808 int res1; 07809 char *dupdstr; 07810 07811 if (new_exten_item) { 07812 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 07813 } else { 07814 new_prio_item = NULL; 07815 } 07816 if (strcmp(prio_item->registrar,registrar) == 0) { 07817 continue; 07818 } 07819 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 07820 if (!new) { 07821 new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */ 07822 } 07823 07824 /* copy in the includes, switches, and ignorepats */ 07825 if (first) { /* but, only need to do this once */ 07826 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07827 first = 0; 07828 } 07829 07830 if (!new) { 07831 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07832 ast_hashtab_end_traversal(prio_iter); 07833 ast_hashtab_end_traversal(exten_iter); 07834 return; /* no sense continuing. */ 07835 } 07836 /* we will not replace existing entries in the new context with stuff from the old context. 07837 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07838 07839 dupdstr = ast_strdup(prio_item->data); 07840 07841 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07842 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07843 if (!res1 && new_exten_item && new_prio_item){ 07844 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07845 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07846 } else { 07847 /* we do NOT pass the priority data from the old to the new -- we pass a copy of it, so no changes to the current dialplan take place, 07848 and no double frees take place, either! */ 07849 insert_count++; 07850 } 07851 } 07852 ast_hashtab_end_traversal(prio_iter); 07853 } 07854 ast_hashtab_end_traversal(exten_iter); 07855 } 07856 07857 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07858 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07859 /* we could have given it the registrar of the other module who incremented the refcount, 07860 but that's not available, so we give it the registrar we know about */ 07861 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07862 07863 /* copy in the includes, switches, and ignorepats */ 07864 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07865 } 07866 }
| static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
| struct ast_context * | old, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 7751 of file pbx.c.
References ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_get_context_name(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_eval(), ast_get_switch_name(), ast_get_switch_registrar(), ast_verb, ast_walk_context_ignorepats(), ast_walk_context_includes(), and ast_walk_context_switches().
Referenced by context_merge().
07752 { 07753 struct ast_include *i; 07754 struct ast_ignorepat *ip; 07755 struct ast_sw *sw; 07756 07757 ast_verb(3, "merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s\n", ast_get_context_name(old), ast_get_context_name(new), registrar); 07758 /* copy in the includes, switches, and ignorepats */ 07759 /* walk through includes */ 07760 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 07761 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 07762 continue; /* not mine */ 07763 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 07764 } 07765 07766 /* walk through switches */ 07767 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 07768 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 07769 continue; /* not mine */ 07770 ast_context_add_switch2(new, ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_eval(sw), ast_get_switch_registrar(sw)); 07771 } 07772 07773 /* walk thru ignorepats ... */ 07774 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 07775 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 07776 continue; /* not mine */ 07777 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 07778 } 07779 }
| static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2279 of file pbx.c.
References add_exten_to_pattern_tree(), ast_hashtab_end_traversal(), ast_hashtab_get_stats(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_exten::exten, LOG_DEBUG, LOG_ERROR, ast_context::name, and ast_context::root_table.
Referenced by pbx_find_extension().
02280 { 02281 struct ast_hashtab_iter *t1; 02282 struct ast_exten *e1; 02283 #ifdef NEED_DEBUG 02284 int biggest_bucket, resizes, numobjs, numbucks; 02285 02286 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02287 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02288 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02289 numobjs, numbucks, biggest_bucket, resizes); 02290 #endif 02291 t1 = ast_hashtab_start_traversal(con->root_table); 02292 while ((e1 = ast_hashtab_next(t1))) { 02293 if (e1->exten) { 02294 add_exten_to_pattern_tree(con, e1, 0); 02295 } else { 02296 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02297 } 02298 } 02299 ast_hashtab_end_traversal(t1); 02300 }
| static void decrease_call_count | ( | void | ) | [static] |
Definition at line 5790 of file pbx.c.
References ast_mutex_lock, ast_mutex_unlock, countcalls, and maxcalllock.
Referenced by ast_pbx_run_args(), ast_pbx_start(), and pbx_thread().
05791 { 05792 ast_mutex_lock(&maxcalllock); 05793 if (countcalls > 0) 05794 countcalls--; 05795 ast_mutex_unlock(&maxcalllock); 05796 }
| static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 5798 of file pbx.c.
References ast_free, ast_hashtab_destroy(), ast_remove_hint(), ast_exten::data, ast_exten::datad, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, and PRIORITY_HINT.
Referenced by __ast_internal_context_destroy(), and ast_context_remove_extension_callerid2().
05799 { 05800 if (e->priority == PRIORITY_HINT) 05801 ast_remove_hint(e); 05802 05803 if (e->peer_table) 05804 ast_hashtab_destroy(e->peer_table,0); 05805 if (e->peer_label_table) 05806 ast_hashtab_destroy(e->peer_label_table, 0); 05807 if (e->datad) 05808 e->datad(e->data); 05809 ast_free(e); 05810 }
| static void destroy_hint | ( | void * | obj | ) | [static] |
Definition at line 5164 of file pbx.c.
References ao2_callback, ao2_ref, AST_EXTENSION_DEACTIVATED, ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_state_cb::change_cb, ast_hint::context_name, ast_state_cb::data, ast_hint::exten, ast_hint::exten_name, and OBJ_UNLINK.
Referenced by ast_add_hint().
05165 { 05166 struct ast_hint *hint = obj; 05167 05168 if (hint->callbacks) { 05169 struct ast_state_cb *state_cb; 05170 const char *context_name; 05171 const char *exten_name; 05172 05173 if (hint->exten) { 05174 context_name = ast_get_context_name(ast_get_extension_context(hint->exten)); 05175 exten_name = ast_get_extension_name(hint->exten); 05176 hint->exten = NULL; 05177 } else { 05178 /* The extension has already been destroyed */ 05179 context_name = hint->context_name; 05180 exten_name = hint->exten_name; 05181 } 05182 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 05183 /* Notify with -1 and remove all callbacks */ 05184 /* NOTE: The casts will not be needed for v1.10 and later */ 05185 state_cb->change_cb((char *) context_name, (char *) exten_name, 05186 AST_EXTENSION_DEACTIVATED, state_cb->data); 05187 ao2_ref(state_cb, -1); 05188 } 05189 ao2_ref(hint->callbacks, -1); 05190 } 05191 }
| static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2302 of file pbx.c.
References match_char::alt_char, ast_free, match_char::exten, and match_char::next_char.
Referenced by __ast_internal_context_destroy().
02303 { 02304 /* destroy all the alternates */ 02305 if (pattern_tree->alt_char) { 02306 destroy_pattern_tree(pattern_tree->alt_char); 02307 pattern_tree->alt_char = 0; 02308 } 02309 /* destroy all the nexts */ 02310 if (pattern_tree->next_char) { 02311 destroy_pattern_tree(pattern_tree->next_char); 02312 pattern_tree->next_char = 0; 02313 } 02314 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02315 ast_free(pattern_tree); 02316 }
| static void destroy_state_cb | ( | void * | doomed | ) | [static] |
Definition at line 4995 of file pbx.c.
References ast_state_cb::data, ast_state_cb::destroy_cb, and ast_state_cb::id.
Referenced by ast_extension_state_add_destroy().
04996 { 04997 struct ast_state_cb *state_cb = doomed; 04998 04999 if (state_cb->destroy_cb) { 05000 state_cb->destroy_cb(state_cb->id, state_cb->data); 05001 } 05002 }
| static void device_state_cb | ( | const struct ast_event * | event, | |
| void * | unused | |||
| ) | [static] |
Definition at line 10733 of file pbx.c.
References ast_calloc, ast_event_get_ie_str(), AST_EVENT_IE_DEVICE, ast_free, ast_log(), ast_strlen_zero(), ast_taskprocessor_push(), statechange::dev, handle_statechange(), and LOG_ERROR.
Referenced by load_pbx().
10734 { 10735 const char *device; 10736 struct statechange *sc; 10737 10738 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 10739 if (ast_strlen_zero(device)) { 10740 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 10741 return; 10742 } 10743 10744 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 10745 return; 10746 strcpy(sc->dev, device); 10747 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 10748 ast_free(sc); 10749 } 10750 }
| static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3529 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03530 { 03531 struct pbx_exception *exception = data; 03532 ast_string_field_free_memory(exception); 03533 ast_free(exception); 03534 }
| static int ext_cmp | ( | const char * | left, | |
| const char * | right | |||
| ) | [static] |
Definition at line 2649 of file pbx.c.
References ext_cmp_exten(), and ext_cmp_pattern().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02650 { 02651 /* Make sure non-pattern extens come first. */ 02652 if (left[0] != '_') { 02653 if (right[0] == '_') { 02654 return -1; 02655 } 02656 /* Compare two non-pattern extens. */ 02657 return ext_cmp_exten(left, right); 02658 } 02659 if (right[0] != '_') { 02660 return 1; 02661 } 02662 02663 /* 02664 * OK, we need full pattern sorting routine. 02665 * 02666 * Skip past the underscores 02667 */ 02668 return ext_cmp_pattern(left + 1, right + 1); 02669 }
| static int ext_cmp_exten | ( | const char * | left, | |
| const char * | right | |||
| ) | [static] |
Definition at line 2399 of file pbx.c.
Referenced by _extension_match_core(), and ext_cmp().
02400 { 02401 int cmp; 02402 02403 for (;;) { 02404 /* Ignore '-' chars as eye candy fluff. */ 02405 while (*left == '-') { 02406 ++left; 02407 } 02408 while (*right == '-') { 02409 ++right; 02410 } 02411 02412 cmp = *left - *right; 02413 if (cmp) { 02414 break; 02415 } 02416 if (!*left) { 02417 /* 02418 * Get here only if both strings ended at the same time. cmp 02419 * would be non-zero if only one string ended. 02420 */ 02421 break; 02422 } 02423 ++left; 02424 ++right; 02425 } 02426 return cmp; 02427 }
| static int ext_cmp_exten_partial | ( | const char * | left, | |
| const char * | right | |||
| ) | [static] |
Definition at line 2356 of file pbx.c.
Referenced by _extension_match_core().
02357 { 02358 int cmp; 02359 02360 for (;;) { 02361 /* Ignore '-' chars as eye candy fluff. */ 02362 while (*left == '-') { 02363 ++left; 02364 } 02365 while (*right == '-') { 02366 ++right; 02367 } 02368 02369 if (!*right) { 02370 /* 02371 * Right ended first for partial match or both ended at the same 02372 * time for a match. 02373 */ 02374 cmp = 0; 02375 break; 02376 } 02377 02378 cmp = *left - *right; 02379 if (cmp) { 02380 break; 02381 } 02382 ++left; 02383 ++right; 02384 } 02385 return cmp; 02386 }
| static int ext_cmp_exten_strlen | ( | const char * | str | ) | [static] |
| static int ext_cmp_pattern | ( | const char * | left, | |
| const char * | right | |||
| ) | [static] |
Definition at line 2601 of file pbx.c.
References ARRAY_LEN, and ext_cmp_pattern_pos().
Referenced by _extension_match_core(), and ext_cmp().
02602 { 02603 int cmp; 02604 int left_pos; 02605 int right_pos; 02606 02607 for (;;) { 02608 unsigned char left_bitwise[32] = { 0, }; 02609 unsigned char right_bitwise[32] = { 0, }; 02610 02611 left_pos = ext_cmp_pattern_pos(&left, left_bitwise); 02612 right_pos = ext_cmp_pattern_pos(&right, right_bitwise); 02613 cmp = left_pos - right_pos; 02614 if (!cmp) { 02615 /* 02616 * Are the character sets different, even though they score the same? 02617 * 02618 * Note: Must swap left and right to get the sense of the 02619 * comparison correct. Otherwise, we would need to multiply by 02620 * -1 instead. 02621 */ 02622 cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise)); 02623 } 02624 if (cmp) { 02625 break; 02626 } 02627 if (!left) { 02628 /* 02629 * Get here only if both patterns ended at the same time. cmp 02630 * would be non-zero if only one pattern ended. 02631 */ 02632 break; 02633 } 02634 } 02635 return cmp; 02636 }
| static int ext_cmp_pattern_pos | ( | const char ** | p, | |
| unsigned char * | bitwise | |||
| ) | [static] |
helper functions to sort extension patterns in the desired way, so that more specific patterns appear first.
The function compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, bits 8-15 are the number of characters in the set, and bits 16-20 are for special cases. This way more specific patterns (smaller character sets) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x001xx one character, character set starting with xx 0x0yyxx yy characters, character set starting with xx 0x18000 '.' (one or more of anything) 0x28000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is ignored. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.
Definition at line 2486 of file pbx.c.
References ast_log(), BITS_PER, and LOG_WARNING.
Referenced by ext_cmp_pattern().
02487 { 02488 #define BITS_PER 8 /* Number of bits per unit (byte). */ 02489 unsigned char c; 02490 unsigned char cmin; 02491 int count; 02492 const char *end; 02493 02494 do { 02495 /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */ 02496 do { 02497 c = *(*p)++; 02498 } while (c == '-'); 02499 02500 /* always return unless we have a set of chars */ 02501 switch (c) { 02502 default: 02503 /* ordinary character */ 02504 bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER)); 02505 return 0x0100 | c; 02506 02507 case 'n': 02508 case 'N': 02509 /* 2..9 */ 02510 bitwise[6] = 0x3f; 02511 bitwise[7] = 0xc0; 02512 return 0x0800 | '2'; 02513 02514 case 'x': 02515 case 'X': 02516 /* 0..9 */ 02517 bitwise[6] = 0xff; 02518 bitwise[7] = 0xc0; 02519 return 0x0A00 | '0'; 02520 02521 case 'z': 02522 case 'Z': 02523 /* 1..9 */ 02524 bitwise[6] = 0x7f; 02525 bitwise[7] = 0xc0; 02526 return 0x0900 | '1'; 02527 02528 case '.': 02529 /* wildcard */ 02530 return 0x18000; 02531 02532 case '!': 02533 /* earlymatch */ 02534 return 0x28000; /* less specific than '.' */ 02535 02536 case '\0': 02537 /* empty string */ 02538 *p = NULL; 02539 return 0x30000; 02540 02541 case '[': 02542 /* char set */ 02543 break; 02544 } 02545 /* locate end of set */ 02546 end = strchr(*p, ']'); 02547 02548 if (!end) { 02549 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02550 return 0x40000; /* XXX make this entry go last... */ 02551 } 02552 02553 count = 0; 02554 cmin = 0xFF; 02555 for (; *p < end; ++*p) { 02556 unsigned char c1; /* first char in range */ 02557 unsigned char c2; /* last char in range */ 02558 02559 c1 = (*p)[0]; 02560 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02561 c2 = (*p)[2]; 02562 *p += 2; /* skip a total of 3 chars */ 02563 } else { /* individual character */ 02564 c2 = c1; 02565 } 02566 if (c1 < cmin) { 02567 cmin = c1; 02568 } 02569 for (; c1 <= c2; ++c1) { 02570 unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER)); 02571 02572 /* 02573 * Note: If two character sets score the same, the one with the 02574 * lowest ASCII values will compare as coming first. Must fill 02575 * in most significant bits for lower ASCII values to accomplish 02576 * the desired sort order. 02577 */ 02578 if (!(bitwise[c1 / BITS_PER] & mask)) { 02579 /* Add the character to the set. */ 02580 bitwise[c1 / BITS_PER] |= mask; 02581 count += 0x100; 02582 } 02583 } 02584 } 02585 ++*p; 02586 } while (!count);/* While the char set was empty. */ 02587 return count | cmin; 02588 }
| static int ext_strncpy | ( | char * | dst, | |
| const char * | src, | |||
| int | len | |||
| ) | [static] |
copy a string skipping whitespace
Definition at line 8750 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
08751 { 08752 int count = 0; 08753 int insquares = 0; 08754 08755 while (*src && (count < len - 1)) { 08756 if (*src == '[') { 08757 insquares = 1; 08758 } else if (*src == ']') { 08759 insquares = 0; 08760 } else if (*src == ' ' && !insquares) { 08761 src++; 08762 continue; 08763 } 08764 *dst = *src; 08765 dst++; 08766 src++; 08767 count++; 08768 } 08769 *dst = '\0'; 08770 08771 return count; 08772 }
| static int extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 2888 of file pbx.c.
References _extension_match_core(), ast_add_profile(), ast_mark(), and ast_strlen_zero().
Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().
02889 { 02890 int i; 02891 static int prof_id = -2; /* marker for 'unallocated' id */ 02892 if (prof_id == -2) { 02893 prof_id = ast_add_profile("ext_match", 0); 02894 } 02895 ast_mark(prof_id, 1); 02896 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode); 02897 ast_mark(prof_id, 0); 02898 return i; 02899 }
| static struct ast_context * find_context | ( | const char * | context | ) | [static, read] |
lookup for a context with a given name,
| found | context or NULL if not found. |
Definition at line 5924 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05925 { 05926 struct fake_context item; 05927 05928 ast_copy_string(item.name, context, sizeof(item.name)); 05929 05930 return ast_hashtab_lookup(contexts_table, &item); 05931 }
| static struct ast_context * find_context_locked | ( | const char * | context | ) | [static, read] |
lookup for a context with a given name,
| with | conlock held if found. | |
| NULL | if not found. |
Definition at line 5938 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, and fake_context::name.
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), and ast_context_unlockmacro().
05939 { 05940 struct ast_context *c; 05941 struct fake_context item; 05942 05943 ast_copy_string(item.name, context, sizeof(item.name)); 05944 05945 ast_rdlock_contexts(); 05946 c = ast_hashtab_lookup(contexts_table, &item); 05947 if (!c) { 05948 ast_unlock_contexts(); 05949 } 05950 05951 return c; 05952 }
| static int find_hint_by_cb_id | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Remove a watcher from the callback list.
Definition at line 5099 of file pbx.c.
References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.
Referenced by ast_extension_state_del().
| static char* func_args | ( | char * | function | ) | [static] |
return a pointer to the arguments of the function, and terminates the function name with '\0'
Definition at line 3998 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03999 { 04000 char *args = strchr(function, '('); 04001 04002 if (!args) { 04003 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 04004 } else { 04005 char *p; 04006 *args++ = '\0'; 04007 if ((p = strrchr(args, ')'))) { 04008 *p = '\0'; 04009 } else { 04010 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 04011 } 04012 } 04013 return args; 04014 }
| static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1687 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.
01688 { 01689 /* find the exten at the end of the rope */ 01690 struct match_char *node2 = node; 01691 01692 for (node2 = node; node2; node2 = node2->next_char) { 01693 if (node2->exten) { 01694 #ifdef NEED_DEBUG_HERE 01695 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01696 #endif 01697 return node2->exten; 01698 } 01699 } 01700 #ifdef NEED_DEBUG_HERE 01701 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01702 #endif 01703 return 0; 01704 }
| static const char* get_pattern_node | ( | struct pattern_node * | node, | |
| const char * | src, | |||
| int | pattern, | |||
| const char * | extenbuf | |||
| ) | [static] |
Definition at line 2036 of file pbx.c.
References ast_log(), pattern_node::buf, compare_char(), first, INC_DST_OVERFLOW_CHECK, last, LOG_ERROR, LOG_WARNING, and pattern_node::specif.
Referenced by add_exten_to_pattern_tree().
02037 { 02038 #define INC_DST_OVERFLOW_CHECK \ 02039 do { \ 02040 if (dst - node->buf < sizeof(node->buf) - 1) { \ 02041 ++dst; \ 02042 } else { \ 02043 overflow = 1; \ 02044 } \ 02045 } while (0) 02046 02047 node->specif = 0; 02048 node->buf[0] = '\0'; 02049 while (*src) { 02050 if (*src == '[' && pattern) { 02051 char *dst = node->buf; 02052 const char *src_next; 02053 int length; 02054 int overflow = 0; 02055 02056 /* get past the '[' */ 02057 ++src; 02058 for (;;) { 02059 if (*src == '\\') { 02060 /* Escaped character. */ 02061 ++src; 02062 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') { 02063 *dst = *src++; 02064 INC_DST_OVERFLOW_CHECK; 02065 } 02066 } else if (*src == '-') { 02067 unsigned char first; 02068 unsigned char last; 02069 02070 src_next = src; 02071 first = *(src_next - 1); 02072 last = *++src_next; 02073 02074 if (last == '\\') { 02075 /* Escaped character. */ 02076 last = *++src_next; 02077 } 02078 02079 /* Possible char range. */ 02080 if (node->buf[0] && last) { 02081 /* Expand the char range. */ 02082 while (++first <= last) { 02083 *dst = first; 02084 INC_DST_OVERFLOW_CHECK; 02085 } 02086 src = src_next + 1; 02087 } else { 02088 /* 02089 * There was no left or right char for the range. 02090 * It is just a '-'. 02091 */ 02092 *dst = *src++; 02093 INC_DST_OVERFLOW_CHECK; 02094 } 02095 } else if (*src == '\0') { 02096 ast_log(LOG_WARNING, 02097 "A matching ']' was not found for '[' in exten pattern '%s'\n", 02098 extenbuf); 02099 break; 02100 } else if (*src == ']') { 02101 ++src; 02102 break; 02103 } else { 02104 *dst = *src++; 02105 INC_DST_OVERFLOW_CHECK; 02106 } 02107 } 02108 /* null terminate the exploded range */ 02109 *dst = '\0'; 02110 02111 if (overflow) { 02112 ast_log(LOG_ERROR, 02113 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n", 02114 extenbuf); 02115 node->buf[0] = '\0'; 02116 continue; 02117 } 02118 02119 /* Sort the characters in character set. */ 02120 length = strlen(node->buf); 02121 if (!length) { 02122 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n", 02123 extenbuf); 02124 node->buf[0] = '\0'; 02125 continue; 02126 } 02127 qsort(node->buf, length, 1, compare_char); 02128 02129 /* Remove duplicate characters from character set. */ 02130 dst = node->buf; 02131 src_next = node->buf; 02132 while (*src_next++) { 02133 if (*dst != *src_next) { 02134 *++dst = *src_next; 02135 } 02136 } 02137 02138 length = strlen(node->buf); 02139 length <<= 8; 02140 node->specif = length | (unsigned char) node->buf[0]; 02141 break; 02142 } else if (*src == '-') { 02143 /* Skip dashes in all extensions. */ 02144 ++src; 02145 } else { 02146 if (*src == '\\') { 02147 /* 02148 * XXX The escape character here does not remove any special 02149 * meaning to characters except the '[', '\\', and '-' 02150 * characters since they are special only in this function. 02151 */ 02152 node->buf[0] = *++src; 02153 if (!node->buf[0]) { 02154 break; 02155 } 02156 } else { 02157 node->buf[0] = *src; 02158 if (pattern) { 02159 /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02160 if (node->buf[0] == 'n') { 02161 node->buf[0] = 'N'; 02162 } else if (node->buf[0] == 'x') { 02163 node->buf[0] = 'X'; 02164 } else if (node->buf[0] == 'z') { 02165 node->buf[0] = 'Z'; 02166 } 02167 } 02168 } 02169 node->buf[1] = '\0'; 02170 node->specif = 1; 02171 ++src; 02172 break; 02173 } 02174 } 02175 return src; 02176 02177 #undef INC_DST_OVERFLOW_CHECK 02178 }
| static unsigned get_range | ( | char * | src, | |
| int | max, | |||
| const char *const | names[], | |||
| const char * | msg | |||
| ) | [static] |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
Definition at line 8105 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and lookup_name().
Referenced by ast_build_timing().
08106 { 08107 int start, end; /* start and ending position */ 08108 unsigned int mask = 0; 08109 char *part; 08110 08111 /* Check for whole range */ 08112 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 08113 return (1 << max) - 1; 08114 } 08115 08116 while ((part = strsep(&src, "&"))) { 08117 /* Get start and ending position */ 08118 char *endpart = strchr(part, '-'); 08119 if (endpart) { 08120 *endpart++ = '\0'; 08121 } 08122 /* Find the start */ 08123 if ((start = lookup_name(part, names, max)) < 0) { 08124 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 08125 continue; 08126 } 08127 if (endpart) { /* find end of range */ 08128 if ((end = lookup_name(endpart, names, max)) < 0) { 08129 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 08130 continue; 08131 } 08132 } else { 08133 end = start; 08134 } 08135 /* Fill the mask. Remember that ranges are cyclic */ 08136 mask |= (1 << end); /* initialize with last element */ 08137 while (start != end) { 08138 mask |= (1 << start); 08139 if (++start >= max) { 08140 start = 0; 08141 } 08142 } 08143 } 08144 return mask; 08145 }
| static void get_timerange | ( | struct ast_timing * | i, | |
| char * | times | |||
| ) | [static] |
store a bitmask of valid times, one bit each 1 minute
Definition at line 8148 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
08149 { 08150 char *endpart, *part; 08151 int x; 08152 int st_h, st_m; 08153 int endh, endm; 08154 int minute_start, minute_end; 08155 08156 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 08157 memset(i->minmask, 0, sizeof(i->minmask)); 08158 08159 /* 1-minute per bit */ 08160 /* Star is all times */ 08161 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 08162 /* 48, because each hour takes 2 integers; 30 bits each */ 08163 for (x = 0; x < 48; x++) { 08164 i->minmask[x] = 0x3fffffff; /* 30 bits */ 08165 } 08166 return; 08167 } 08168 /* Otherwise expect a range */ 08169 while ((part = strsep(×, "&"))) { 08170 if (!(endpart = strchr(part, '-'))) { 08171 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 08172 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 08173 continue; 08174 } 08175 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 08176 continue; 08177 } 08178 *endpart++ = '\0'; 08179 /* why skip non digits? Mostly to skip spaces */ 08180 while (*endpart && !isdigit(*endpart)) { 08181 endpart++; 08182 } 08183 if (!*endpart) { 08184 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 08185 continue; 08186 } 08187 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 08188 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 08189 continue; 08190 } 08191 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 08192 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 08193 continue; 08194 } 08195 minute_start = st_h * 60 + st_m; 08196 minute_end = endh * 60 + endm; 08197 /* Go through the time and enable each appropriate bit */ 08198 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 08199 i->minmask[x / 30] |= (1 << (x % 30)); 08200 } 08201 /* Do the last one */ 08202 i->minmask[x / 30] |= (1 << (x % 30)); 08203 } 08204 /* All done */ 08205 return; 08206 }
| static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Send ack once.
Definition at line 7134 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), dialplan_counters::total_context, ast_cli_entry::usage, and ast_cli_args::word.
07135 { 07136 char *exten = NULL, *context = NULL; 07137 /* Variables used for different counters */ 07138 struct dialplan_counters counters; 07139 const char *incstack[AST_PBX_MAX_STACK]; 07140 07141 switch (cmd) { 07142 case CLI_INIT: 07143 e->command = "dialplan debug"; 07144 e->usage = 07145 "Usage: dialplan debug [context]\n" 07146 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 07147 return NULL; 07148 case CLI_GENERATE: 07149 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 07150 } 07151 07152 memset(&counters, 0, sizeof(counters)); 07153 07154 if (a->argc != 2 && a->argc != 3) 07155 return CLI_SHOWUSAGE; 07156 07157 /* we obtain [exten@]context? if yes, split them ... */ 07158 /* note: we ignore the exten totally here .... */ 07159 if (a->argc == 3) { 07160 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 07161 context = ast_strdupa(a->argv[2]); 07162 exten = strsep(&context, "@"); 07163 /* change empty strings to NULL */ 07164 if (ast_strlen_zero(exten)) 07165 exten = NULL; 07166 } else { /* no '@' char, only context given */ 07167 context = ast_strdupa(a->argv[2]); 07168 } 07169 if (ast_strlen_zero(context)) 07170 context = NULL; 07171 } 07172 /* else Show complete dial plan, context and exten are NULL */ 07173 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 07174 07175 /* check for input failure and throw some error messages */ 07176 if (context && !counters.context_existence) { 07177 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 07178 return CLI_FAILURE; 07179 } 07180 07181 07182 ast_cli(a->fd,"-= %d %s. =-\n", 07183 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 07184 07185 /* everything ok */ 07186 return CLI_SUCCESS; 07187 }
| static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7507 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_setvar_helper(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
07508 { 07509 struct ast_channel *chan; 07510 const char *chan_name, *var_name, *var_value; 07511 07512 switch (cmd) { 07513 case CLI_INIT: 07514 e->command = "dialplan set chanvar"; 07515 e->usage = 07516 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 07517 " Set channel variable <varname> to <value>\n"; 07518 return NULL; 07519 case CLI_GENERATE: 07520 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07521 } 07522 07523 if (a->argc != e->args + 3) 07524 return CLI_SHOWUSAGE; 07525 07526 chan_name = a->argv[e->args]; 07527 var_name = a->argv[e->args + 1]; 07528 var_value = a->argv[e->args + 2]; 07529 07530 if (!(chan = ast_channel_get_by_name(chan_name))) { 07531 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 07532 return CLI_FAILURE; 07533 } 07534 07535 pbx_builtin_setvar_helper(chan, var_name, var_value); 07536 07537 chan = ast_channel_unref(chan); 07538 07539 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 07540 07541 return CLI_SUCCESS; 07542 }
| static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7544 of file pbx.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pbx_set_extenpatternmatchnew(), and ast_cli_entry::usage.
07545 { 07546 int oldval = 0; 07547 07548 switch (cmd) { 07549 case CLI_INIT: 07550 e->command = "dialplan set extenpatternmatchnew true"; 07551 e->usage = 07552 "Usage: dialplan set extenpatternmatchnew true|false\n" 07553 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07554 return NULL; 07555 case CLI_GENERATE: 07556 return NULL; 07557 } 07558 07559 if (a->argc != 4) 07560 return CLI_SHOWUSAGE; 07561 07562 oldval = pbx_set_extenpatternmatchnew(1); 07563 07564 if (oldval) 07565 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07566 else 07567 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07568 07569 return CLI_SUCCESS; 07570 }
| static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7485 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pbx_builtin_setvar_helper(), and ast_cli_entry::usage.
07486 { 07487 switch (cmd) { 07488 case CLI_INIT: 07489 e->command = "dialplan set global"; 07490 e->usage = 07491 "Usage: dialplan set global <name> <value>\n" 07492 " Set global dialplan variable <name> to <value>\n"; 07493 return NULL; 07494 case CLI_GENERATE: 07495 return NULL; 07496 } 07497 07498 if (a->argc != e->args + 2) 07499 return CLI_SHOWUSAGE; 07500 07501 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 07502 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 07503 07504 return CLI_SUCCESS; 07505 }
| static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6496 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_complete_applications(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.
06497 { 06498 struct ast_app *aa; 06499 int app, no_registered_app = 1; 06500 06501 switch (cmd) { 06502 case CLI_INIT: 06503 e->command = "core show application"; 06504 e->usage = 06505 "Usage: core show application <application> [<application> [<application> [...]]]\n" 06506 " Describes a particular application.\n"; 06507 return NULL; 06508 case CLI_GENERATE: 06509 /* 06510 * There is a possibility to show informations about more than one 06511 * application at one time. You can type 'show application Dial Echo' and 06512 * you will see informations about these two applications ... 06513 */ 06514 return ast_complete_applications(a->line, a->word, a->n); 06515 } 06516 06517 if (a->argc < 4) { 06518 return CLI_SHOWUSAGE; 06519 } 06520 06521 AST_RWLIST_RDLOCK(&apps); 06522 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06523 /* Check for each app that was supplied as an argument */ 06524 for (app = 3; app < a->argc; app++) { 06525 if (strcasecmp(aa->name, a->argv[app])) { 06526 continue; 06527 } 06528 06529 /* We found it! */ 06530 no_registered_app = 0; 06531 06532 print_app_docs(aa, a->fd); 06533 } 06534 } 06535 AST_RWLIST_UNLOCK(&apps); 06536 06537 /* we found at least one app? no? */ 06538 if (no_registered_app) { 06539 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 06540 return CLI_FAILURE; 06541 } 06542 06543 return CLI_SUCCESS; 06544 }
| static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6721 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_app::description, ast_cli_args::fd, ast_cli_args::n, ast_app::name, ast_cli_args::pos, ast_app::synopsis, ast_cli_entry::usage, and ast_cli_args::word.
06722 { 06723 struct ast_app *aa; 06724 int like = 0, describing = 0; 06725 int total_match = 0; /* Number of matches in like clause */ 06726 int total_apps = 0; /* Number of apps registered */ 06727 static const char * const choices[] = { "like", "describing", NULL }; 06728 06729 switch (cmd) { 06730 case CLI_INIT: 06731 e->command = "core show applications [like|describing]"; 06732 e->usage = 06733 "Usage: core show applications [{like|describing} <text>]\n" 06734 " List applications which are currently available.\n" 06735 " If 'like', <text> will be a substring of the app name\n" 06736 " If 'describing', <text> will be a substring of the description\n"; 06737 return NULL; 06738 case CLI_GENERATE: 06739 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 06740 } 06741 06742 AST_RWLIST_RDLOCK(&apps); 06743 06744 if (AST_RWLIST_EMPTY(&apps)) { 06745 ast_cli(a->fd, "There are no registered applications\n"); 06746 AST_RWLIST_UNLOCK(&apps); 06747 return CLI_SUCCESS; 06748 } 06749 06750 /* core list applications like <keyword> */ 06751 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 06752 like = 1; 06753 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 06754 describing = 1; 06755 } 06756 06757 /* core list applications describing <keyword1> [<keyword2>] [...] */ 06758 if ((!like) && (!describing)) { 06759 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 06760 } else { 06761 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 06762 } 06763 06764 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06765 int printapp = 0; 06766 total_apps++; 06767 if (like) { 06768 if (strcasestr(aa->name, a->argv[4])) { 06769 printapp = 1; 06770 total_match++; 06771 } 06772 } else if (describing) { 06773 if (aa->description) { 06774 /* Match all words on command line */ 06775 int i; 06776 printapp = 1; 06777 for (i = 4; i < a->argc; i++) { 06778 if (!strcasestr(aa->description, a->argv[i])) { 06779 printapp = 0; 06780 } else { 06781 total_match++; 06782 } 06783 } 06784 } 06785 } else { 06786 printapp = 1; 06787 } 06788 06789 if (printapp) { 06790 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 06791 } 06792 } 06793 if ((!like) && (!describing)) { 06794 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 06795 } else { 06796 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 06797 } 06798 06799 AST_RWLIST_UNLOCK(&apps); 06800 06801 return CLI_SUCCESS; 06802 }
| static char* handle_show_chanvar | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI support for listing chanvar's variables in a parseable way.
Definition at line 7450 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), ast_str_alloca, ast_str_buffer(), ast_str_strlen(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_serialize_variables(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
07451 { 07452 struct ast_channel *chan = NULL; 07453 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 07454 07455 switch (cmd) { 07456 case CLI_INIT: 07457 e->command = "dialplan show chanvar"; 07458 e->usage = 07459 "Usage: dialplan show chanvar <channel>\n" 07460 " List current channel variables and their values\n"; 07461 return NULL; 07462 case CLI_GENERATE: 07463 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07464 } 07465 07466 if (a->argc != e->args + 1) 07467 return CLI_SHOWUSAGE; 07468 07469 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 07470 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 07471 return CLI_FAILURE; 07472 } 07473 07474 pbx_builtin_serialize_variables(chan, &vars); 07475 07476 if (ast_str_strlen(vars)) { 07477 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 07478 } 07479 07480 chan = ast_channel_unref(chan); 07481 07482 return CLI_SUCCESS; 07483 }
| static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7067 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, ast_cli_entry::usage, and ast_cli_args::word.
07068 { 07069 char *exten = NULL, *context = NULL; 07070 /* Variables used for different counters */ 07071 struct dialplan_counters counters; 07072 const char *incstack[AST_PBX_MAX_STACK]; 07073 07074 switch (cmd) { 07075 case CLI_INIT: 07076 e->command = "dialplan show"; 07077 e->usage = 07078 "Usage: dialplan show [[exten@]context]\n" 07079 " Show dialplan\n"; 07080 return NULL; 07081 case CLI_GENERATE: 07082 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 07083 } 07084 07085 memset(&counters, 0, sizeof(counters)); 07086 07087 if (a->argc != 2 && a->argc != 3) 07088 return CLI_SHOWUSAGE; 07089 07090 /* we obtain [exten@]context? if yes, split them ... */ 07091 if (a->argc == 3) { 07092 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 07093 context = ast_strdupa(a->argv[2]); 07094 exten = strsep(&context, "@"); 07095 /* change empty strings to NULL */ 07096 if (ast_strlen_zero(exten)) 07097 exten = NULL; 07098 } else { /* no '@' char, only context given */ 07099 context = ast_strdupa(a->argv[2]); 07100 } 07101 if (ast_strlen_zero(context)) 07102 context = NULL; 07103 } 07104 /* else Show complete dial plan, context and exten are NULL */ 07105 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 07106 07107 /* check for input failure and throw some error messages */ 07108 if (context && !counters.context_existence) { 07109 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 07110 return CLI_FAILURE; 07111 } 07112 07113 if (exten && !counters.extension_existence) { 07114 if (context) 07115 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 07116 exten, context); 07117 else 07118 ast_cli(a->fd, 07119 "There is no existence of '%s' extension in all contexts\n", 07120 exten); 07121 return CLI_FAILURE; 07122 } 07123 07124 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 07125 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 07126 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 07127 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 07128 07129 /* everything ok */ 07130 return CLI_SUCCESS; 07131 }
| static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3651 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), ast_free, ast_malloc, AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_custom_function::docsrc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, S_OR, synopsis, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
03652 { 03653 struct ast_custom_function *acf; 03654 /* Maximum number of characters added by terminal coloring is 22 */ 03655 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03656 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03657 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03658 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03659 char *ret = NULL; 03660 int which = 0; 03661 int wordlen; 03662 03663 switch (cmd) { 03664 case CLI_INIT: 03665 e->command = "core show function"; 03666 e->usage = 03667 "Usage: core show function <function>\n" 03668 " Describe a particular dialplan function.\n"; 03669 return NULL; 03670 case CLI_GENERATE: 03671 wordlen = strlen(a->word); 03672 /* case-insensitive for convenience in this 'complete' function */ 03673 AST_RWLIST_RDLOCK(&acf_root); 03674 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03675 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03676 ret = ast_strdup(acf->name); 03677 break; 03678 } 03679 } 03680 AST_RWLIST_UNLOCK(&acf_root); 03681 03682 return ret; 03683 } 03684 03685 if (a->argc < 4) { 03686 return CLI_SHOWUSAGE; 03687 } 03688 03689 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03690 ast_cli(a->fd, "No function by that name registered.\n"); 03691 return CLI_FAILURE; 03692 } 03693 03694 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03695 if (!(syntax = ast_malloc(syntax_size))) { 03696 ast_cli(a->fd, "Memory allocation failure!\n"); 03697 return CLI_FAILURE; 03698 } 03699 03700 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03701 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03702 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03703 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03704 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03705 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03706 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03707 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03708 #ifdef AST_XML_DOCS 03709 if (acf->docsrc == AST_XML_DOC) { 03710 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03711 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03712 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03713 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03714 } else 03715 #endif 03716 { 03717 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03718 synopsis = ast_malloc(synopsis_size); 03719 03720 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03721 description = ast_malloc(description_size); 03722 03723 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03724 arguments = ast_malloc(arguments_size); 03725 03726 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03727 seealso = ast_malloc(seealso_size); 03728 03729 /* check allocated memory. */ 03730 if (!synopsis || !description || !arguments || !seealso) { 03731 ast_free(synopsis); 03732 ast_free(description); 03733 ast_free(arguments); 03734 ast_free(seealso); 03735 ast_free(syntax); 03736 return CLI_FAILURE; 03737 } 03738 03739 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03740 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03741 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03742 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03743 } 03744 03745 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03746 infotitle, syntitle, synopsis, destitle, description, 03747 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03748 03749 ast_free(arguments); 03750 ast_free(synopsis); 03751 ast_free(description); 03752 ast_free(seealso); 03753 ast_free(syntax); 03754 03755 return CLI_SUCCESS; 03756 }
| static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3609 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, S_OR, and ast_cli_entry::usage.
03610 { 03611 struct ast_custom_function *acf; 03612 int count_acf = 0; 03613 int like = 0; 03614 03615 switch (cmd) { 03616 case CLI_INIT: 03617 e->command = "core show functions [like]"; 03618 e->usage = 03619 "Usage: core show functions [like <text>]\n" 03620 " List builtin functions, optionally only those matching a given string\n"; 03621 return NULL; 03622 case CLI_GENERATE: 03623 return NULL; 03624 } 03625 03626 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03627 like = 1; 03628 } else if (a->argc != 3) { 03629 return CLI_SHOWUSAGE; 03630 } 03631 03632 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03633 03634 AST_RWLIST_RDLOCK(&acf_root); 03635 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03636 if (!like || strstr(acf->name, a->argv[4])) { 03637 count_acf++; 03638 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03639 S_OR(acf->name, ""), 03640 S_OR(acf->syntax, ""), 03641 S_OR(acf->synopsis, "")); 03642 } 03643 } 03644 AST_RWLIST_UNLOCK(&acf_root); 03645 03646 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03647 03648 return CLI_SUCCESS; 03649 }
| static char* handle_show_globals | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI support for listing global variables in a parseable way.
Definition at line 7392 of file pbx.c.
References ast_cli(), AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, globals, globalslock, and ast_cli_entry::usage.
07393 { 07394 int i = 0; 07395 struct ast_var_t *newvariable; 07396 07397 switch (cmd) { 07398 case CLI_INIT: 07399 e->command = "dialplan show globals"; 07400 e->usage = 07401 "Usage: dialplan show globals\n" 07402 " List current global dialplan variables and their values\n"; 07403 return NULL; 07404 case CLI_GENERATE: 07405 return NULL; 07406 } 07407 07408 ast_rwlock_rdlock(&globalslock); 07409 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 07410 i++; 07411 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 07412 } 07413 ast_rwlock_unlock(&globalslock); 07414 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 07415 07416 return CLI_SUCCESS; 07417 }
| static char* handle_show_hint | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
handle_show_hint: CLI support for listing registered dial plan hint
Definition at line 6633 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
06634 { 06635 struct ast_hint *hint; 06636 int watchers; 06637 int num = 0, extenlen; 06638 struct ao2_iterator i; 06639 06640 switch (cmd) { 06641 case CLI_INIT: 06642 e->command = "core show hint"; 06643 e->usage = 06644 "Usage: core show hint <exten>\n" 06645 " List registered hint\n"; 06646 return NULL; 06647 case CLI_GENERATE: 06648 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 06649 } 06650 06651 if (a->argc < 4) 06652 return CLI_SHOWUSAGE; 06653 06654 if (ao2_container_count(hints) == 0) { 06655 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06656 return CLI_SUCCESS; 06657 } 06658 06659 extenlen = strlen(a->argv[3]); 06660 i = ao2_iterator_init(hints, 0); 06661 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06662 ao2_lock(hint); 06663 if (!hint->exten) { 06664 /* The extension has already been destroyed */ 06665 ao2_unlock(hint); 06666 continue; 06667 } 06668 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 06669 watchers = ao2_container_count(hint->callbacks); 06670 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06671 ast_get_extension_name(hint->exten), 06672 ast_get_context_name(ast_get_extension_context(hint->exten)), 06673 ast_get_extension_app(hint->exten), 06674 ast_extension_state2str(hint->laststate), watchers); 06675 num++; 06676 } 06677 ao2_unlock(hint); 06678 } 06679 ao2_iterator_destroy(&i); 06680 if (!num) 06681 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 06682 else 06683 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 06684 return CLI_SUCCESS; 06685 }
| static char* handle_show_hints | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
handle_show_hints: CLI support for listing registered dial plan hints
Definition at line 6547 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, and ast_cli_entry::usage.
06548 { 06549 struct ast_hint *hint; 06550 int num = 0; 06551 int watchers; 06552 struct ao2_iterator i; 06553 06554 switch (cmd) { 06555 case CLI_INIT: 06556 e->command = "core show hints"; 06557 e->usage = 06558 "Usage: core show hints\n" 06559 " List registered hints\n"; 06560 return NULL; 06561 case CLI_GENERATE: 06562 return NULL; 06563 } 06564 06565 if (ao2_container_count(hints) == 0) { 06566 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06567 return CLI_SUCCESS; 06568 } 06569 /* ... we have hints ... */ 06570 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 06571 06572 i = ao2_iterator_init(hints, 0); 06573 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06574 ao2_lock(hint); 06575 if (!hint->exten) { 06576 /* The extension has already been destroyed */ 06577 ao2_unlock(hint); 06578 continue; 06579 } 06580 watchers = ao2_container_count(hint->callbacks); 06581 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06582 ast_get_extension_name(hint->exten), 06583 ast_get_context_name(ast_get_extension_context(hint->exten)), 06584 ast_get_extension_app(hint->exten), 06585 ast_extension_state2str(hint->laststate), watchers); 06586 ao2_unlock(hint); 06587 num++; 06588 } 06589 ao2_iterator_destroy(&i); 06590 06591 ast_cli(a->fd, "----------------\n"); 06592 ast_cli(a->fd, "- %d hints registered\n", num); 06593 return CLI_SUCCESS; 06594 }
| static char* handle_show_switches | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
handle_show_switches: CLI support for listing registered dial plan switches
Definition at line 6689 of file pbx.c.
References ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_switch::description, ast_cli_args::fd, ast_switch::name, and ast_cli_entry::usage.
06690 { 06691 struct ast_switch *sw; 06692 06693 switch (cmd) { 06694 case CLI_INIT: 06695 e->command = "core show switches"; 06696 e->usage = 06697 "Usage: core show switches\n" 06698 " List registered switches\n"; 06699 return NULL; 06700 case CLI_GENERATE: 06701 return NULL; 06702 } 06703 06704 AST_RWLIST_RDLOCK(&switches); 06705 06706 if (AST_RWLIST_EMPTY(&switches)) { 06707 AST_RWLIST_UNLOCK(&switches); 06708 ast_cli(a->fd, "There are no registered alternative switches\n"); 06709 return CLI_SUCCESS; 06710 } 06711 06712 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 06713 AST_RWLIST_TRAVERSE(&switches, sw, list) 06714 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 06715 06716 AST_RWLIST_UNLOCK(&switches); 06717 06718 return CLI_SUCCESS; 06719 }
| static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4893 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_extension_state3(), ast_free, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_hint::callbacks, ast_state_cb::change_cb, context_merge_lock, ast_state_cb::data, statechange::dev, ast_hint::exten, hints, ast_hint::laststate, parse(), and statecbs.
Referenced by device_state_cb().
04894 { 04895 struct ast_hint *hint; 04896 struct ast_str *hint_app; 04897 struct statechange *sc = datap; 04898 struct ao2_iterator i; 04899 struct ao2_iterator cb_iter; 04900 char context_name[AST_MAX_CONTEXT]; 04901 char exten_name[AST_MAX_EXTENSION]; 04902 04903 hint_app = ast_str_create(1024); 04904 if (!hint_app) { 04905 ast_free(sc); 04906 return -1; 04907 } 04908 04909 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ 04910 i = ao2_iterator_init(hints, 0); 04911 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 04912 struct ast_state_cb *state_cb; 04913 char *cur, *parse; 04914 int state; 04915 04916 ao2_lock(hint); 04917 if (!hint->exten) { 04918 /* The extension has already been destroyed */ 04919 ao2_unlock(hint); 04920 continue; 04921 } 04922 04923 /* Does this hint monitor the device that changed state? */ 04924 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04925 parse = ast_str_buffer(hint_app); 04926 while ((cur = strsep(&parse, "&"))) { 04927 if (!strcasecmp(cur, sc->dev)) { 04928 /* The hint monitors the device. */ 04929 break; 04930 } 04931 } 04932 if (!cur) { 04933 /* The hint does not monitor the device. */ 04934 ao2_unlock(hint); 04935 continue; 04936 } 04937 04938 /* 04939 * Save off strings in case the hint extension gets destroyed 04940 * while we are notifying the watchers. 04941 */ 04942 ast_copy_string(context_name, 04943 ast_get_context_name(ast_get_extension_context(hint->exten)), 04944 sizeof(context_name)); 04945 ast_copy_string(exten_name, ast_get_extension_name(hint->exten), 04946 sizeof(exten_name)); 04947 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04948 ao2_unlock(hint); 04949 04950 /* 04951 * Get device state for this hint. 04952 * 04953 * NOTE: We cannot hold any locks while determining the hint 04954 * device state or notifying the watchers without causing a 04955 * deadlock. (conlock, hints, and hint) 04956 */ 04957 state = ast_extension_state3(hint_app); 04958 if (state == hint->laststate) { 04959 continue; 04960 } 04961 04962 /* Device state changed since last check - notify the watchers. */ 04963 hint->laststate = state; /* record we saw the change */ 04964 04965 /* For general callbacks */ 04966 cb_iter = ao2_iterator_init(statecbs, 0); 04967 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04968 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04969 } 04970 ao2_iterator_destroy(&cb_iter); 04971 04972 /* For extension callbacks */ 04973 cb_iter = ao2_iterator_init(hint->callbacks, 0); 04974 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04975 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04976 } 04977 ao2_iterator_destroy(&cb_iter); 04978 } 04979 ao2_iterator_destroy(&i); 04980 ast_mutex_unlock(&context_merge_lock); 04981 04982 ast_free(hint_app); 04983 ast_free(sc); 04984 return 0; 04985 }
| static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7572 of file pbx.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pbx_set_extenpatternmatchnew(), and ast_cli_entry::usage.
07573 { 07574 int oldval = 0; 07575 07576 switch (cmd) { 07577 case CLI_INIT: 07578 e->command = "dialplan set extenpatternmatchnew false"; 07579 e->usage = 07580 "Usage: dialplan set extenpatternmatchnew true|false\n" 07581 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07582 return NULL; 07583 case CLI_GENERATE: 07584 return NULL; 07585 } 07586 07587 if (a->argc != 4) 07588 return CLI_SHOWUSAGE; 07589 07590 oldval = pbx_set_extenpatternmatchnew(0); 07591 07592 if (!oldval) 07593 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07594 else 07595 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07596 07597 return CLI_SUCCESS; 07598 }
| static int hashtab_compare_exten_labels | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) | [static] |
| static int hashtab_compare_exten_numbers | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) | [static] |
Definition at line 1130 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
| static int hashtab_compare_extens | ( | const void * | ha_a, | |
| const void * | ah_b | |||
| ) | [static] |
Definition at line 1102 of file pbx.c.
References AST_EXT_MATCHCID_ANY, AST_EXT_MATCHCID_OFF, ast_strlen_zero(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01103 { 01104 const struct ast_exten *ac = ah_a; 01105 const struct ast_exten *bc = ah_b; 01106 int x = strcmp(ac->exten, bc->exten); 01107 if (x) { /* if exten names are diff, then return */ 01108 return x; 01109 } 01110 01111 /* but if they are the same, do the cidmatch values match? */ 01112 /* not sure which side may be using ast_ext_matchcid_types, so check both */ 01113 if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) { 01114 return 0; 01115 } 01116 if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) { 01117 return 0; 01118 } 01119 if (ac->matchcid != bc->matchcid) { 01120 return 1; 01121 } 01122 /* all other cases already disposed of, match now required on callerid string (cidmatch) */ 01123 /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */ 01124 if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) { 01125 return 0; 01126 } 01127 return strcmp(ac->cidmatch, bc->cidmatch); 01128 }
| static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1150 of file pbx.c.
References AST_EXT_MATCHCID_ON, ast_hashtab_hash_string(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01151 { 01152 const struct ast_exten *ac = obj; 01153 unsigned int x = ast_hashtab_hash_string(ac->exten); 01154 unsigned int y = 0; 01155 if (ac->matchcid == AST_EXT_MATCHCID_ON) 01156 y = ast_hashtab_hash_string(ac->cidmatch); 01157 return x+y; 01158 }
| static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1166 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01167 { 01168 const struct ast_exten *ac = obj; 01169 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01170 }
| static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1160 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01161 { 01162 const struct ast_exten *ac = obj; 01163 return ast_hashtab_hash_int(ac->priority); 01164 }
| static int hint_cmp | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
| static int hint_hash | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 11183 of file pbx.c.
References ast_get_extension_name(), ast_str_case_hash(), ast_strlen_zero(), ast_hint::exten, and ast_hint::exten_name.
Referenced by ast_pbx_init().
11184 { 11185 const struct ast_hint *hint = obj; 11186 const char *exten_name; 11187 int res; 11188 11189 exten_name = ast_get_extension_name(hint->exten); 11190 if (ast_strlen_zero(exten_name)) { 11191 /* 11192 * If the exten or extension name isn't set, return 0 so that 11193 * the ao2_find() search will start in the first bucket. 11194 */ 11195 res = 0; 11196 } else { 11197 res = ast_str_case_hash(exten_name); 11198 } 11199 11200 return res; 11201 }
| static int hint_id_cmp | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 5148 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
05149 { 05150 const struct ast_state_cb *cb = obj; 05151 int *id = arg; 05152 05153 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 05154 }
| static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
| struct ast_data * | data_root | |||
| ) | [static] |
Definition at line 10756 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_hint::exten, hints, and ast_hint::laststate.
10758 { 10759 struct ast_data *data_hint; 10760 struct ast_hint *hint; 10761 int watchers; 10762 struct ao2_iterator i; 10763 10764 if (ao2_container_count(hints) == 0) { 10765 return 0; 10766 } 10767 10768 i = ao2_iterator_init(hints, 0); 10769 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 10770 watchers = ao2_container_count(hint->callbacks); 10771 data_hint = ast_data_add_node(data_root, "hint"); 10772 if (!data_hint) { 10773 continue; 10774 } 10775 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 10776 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 10777 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 10778 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 10779 ast_data_add_int(data_hint, "watchers", watchers); 10780 10781 if (!ast_data_search_match(search, data_hint)) { 10782 ast_data_remove_node(data_root, data_hint); 10783 } 10784 } 10785 ao2_iterator_destroy(&i); 10786 10787 return 0; 10788 }
| static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1523 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01524 { 01525 if (!i->hastime) 01526 return 1; 01527 01528 return ast_check_timing(&(i->timing)); 01529 }
| static int increase_call_count | ( | const struct ast_channel * | c | ) | [static] |
Increase call count for channel.
| 0 | on success | |
| non-zero | if a configured limit (maxcalls, maxload, minmemfree) was reached |
Definition at line 5743 of file pbx.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, countcalls, LOG_WARNING, maxcalllock, option_maxcalls, option_maxload, option_minmemfree, and totalcalls.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
05744 { 05745 int failed = 0; 05746 double curloadavg; 05747 #if defined(HAVE_SYSINFO) 05748 long curfreemem; 05749 struct sysinfo sys_info; 05750 #endif 05751 05752 ast_mutex_lock(&maxcalllock); 05753 if (option_maxcalls) { 05754 if (countcalls >= option_maxcalls) { 05755 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 05756 failed = -1; 05757 } 05758 } 05759 if (option_maxload) { 05760 getloadavg(&curloadavg, 1); 05761 if (curloadavg >= option_maxload) { 05762 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 05763 failed = -1; 05764 } 05765 } 05766 #if defined(HAVE_SYSINFO) 05767 if (option_minmemfree) { 05768 if (!sysinfo(&sys_info)) { 05769 /* make sure that the free system memory is above the configured low watermark 05770 * convert the amount of freeram from mem_units to MB */ 05771 curfreemem = sys_info.freeram * sys_info.mem_unit; 05772 curfreemem /= 1024 * 1024; 05773 if (curfreemem < option_minmemfree) { 05774 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 05775 failed = -1; 05776 } 05777 } 05778 } 05779 #endif 05780 05781 if (!failed) { 05782 countcalls++; 05783 totalcalls++; 05784 } 05785 ast_mutex_unlock(&maxcalllock); 05786 05787 return failed; 05788 }
| static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
| struct match_char * | node | |||
| ) | [static] |
Definition at line 1941 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01942 { 01943 struct match_char *curr, *lcurr; 01944 01945 /* insert node into the tree at "current", so the alt_char list from current is 01946 sorted in increasing value as you go to the leaves */ 01947 if (!(*parent_ptr)) { 01948 *parent_ptr = node; 01949 return; 01950 } 01951 01952 if ((*parent_ptr)->specificity > node->specificity) { 01953 /* insert at head */ 01954 node->alt_char = (*parent_ptr); 01955 *parent_ptr = node; 01956 return; 01957 } 01958 01959 lcurr = *parent_ptr; 01960 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01961 if (curr->specificity > node->specificity) { 01962 node->alt_char = curr; 01963 lcurr->alt_char = node; 01964 break; 01965 } 01966 lcurr = curr; 01967 } 01968 01969 if (!curr) { 01970 lcurr->alt_char = node; 01971 } 01972 01973 }
| static int is_read_allowed | ( | struct ast_custom_function * | acfptr | ) | [static] |
Determines whether execution of a custom function's read function is allowed.
| acfptr | Custom function to check |
Definition at line 4076 of file pbx.c.
References ast_debug, ast_custom_function::name, read_escalates(), and thread_inhibits_escalations().
Referenced by ast_func_read(), and ast_func_read2().
04077 { 04078 if (!acfptr) { 04079 return 1; 04080 } 04081 04082 if (!read_escalates(acfptr)) { 04083 return 1; 04084 } 04085 04086 if (!thread_inhibits_escalations()) { 04087 return 1; 04088 } 04089 04090 if (live_dangerously) { 04091 /* Global setting overrides the thread's preference */ 04092 ast_debug(2, "Reading %s from a dangerous context\n", 04093 acfptr->name); 04094 return 1; 04095 } 04096 04097 /* We have no reason to allow this function to execute */ 04098 return 0; 04099 }
| static int is_write_allowed | ( | struct ast_custom_function * | acfptr | ) | [static] |
Determines whether execution of a custom function's write function is allowed.
| acfptr | Custom function to check |
Definition at line 4109 of file pbx.c.
References ast_debug, ast_custom_function::name, thread_inhibits_escalations(), and write_escalates().
Referenced by ast_func_write().
04110 { 04111 if (!acfptr) { 04112 return 1; 04113 } 04114 04115 if (!write_escalates(acfptr)) { 04116 return 1; 04117 } 04118 04119 if (!thread_inhibits_escalations()) { 04120 return 1; 04121 } 04122 04123 if (live_dangerously) { 04124 /* Global setting overrides the thread's preference */ 04125 ast_debug(2, "Writing %s from a dangerous context\n", 04126 acfptr->name); 04127 return 1; 04128 } 04129 04130 /* We have no reason to allow this function to execute */ 04131 return 0; 04132 }
| int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 10824 of file pbx.c.
References __ast_custom_function_register(), ARRAY_LEN, ast_cli_register_multiple(), ast_data_register_multiple_core, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register_xml, ast_register_application2(), ast_register_atexit(), ast_taskprocessor_get(), ast_verb, builtins, device_state_cb(), device_state_sub, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), pbx_cli, pbx_data_providers, testtime_function, and unload_pbx().
Referenced by main().
10825 { 10826 int x; 10827 10828 ast_register_atexit(unload_pbx); 10829 10830 /* Initialize the PBX */ 10831 ast_verb(1, "Asterisk PBX Core Initializing\n"); 10832 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 10833 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 10834 } 10835 10836 ast_verb(1, "Registering builtin applications:\n"); 10837 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10838 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 10839 __ast_custom_function_register(&exception_function, NULL); 10840 __ast_custom_function_register(&testtime_function, NULL); 10841 10842 /* Register builtin applications */ 10843 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10844 ast_verb(1, "[%s]\n", builtins[x].name); 10845 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 10846 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 10847 return -1; 10848 } 10849 } 10850 10851 /* Register manager application */ 10852 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 10853 10854 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 10855 AST_EVENT_IE_END))) { 10856 return -1; 10857 } 10858 10859 return 0; 10860 }
| static int lookup_name | ( | const char * | s, | |
| const char *const | names[], | |||
| int | max | |||
| ) | [static] |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
Definition at line 8082 of file pbx.c.
Referenced by get_range().
08083 { 08084 int i; 08085 08086 if (names && *s > '9') { 08087 for (i = 0; names[i]; i++) { 08088 if (!strcasecmp(s, names[i])) { 08089 return i; 08090 } 08091 } 08092 } 08093 08094 /* Allow months and weekdays to be specified as numbers, as well */ 08095 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 08096 /* What the array offset would have been: "1" would be at offset 0 */ 08097 return i - 1; 08098 } 08099 return -1; /* error return */ 08100 }
| static void manager_dpsendack | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Send ack once.
Definition at line 7190 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().
07191 { 07192 astman_send_listack(s, m, "DialPlan list will follow", "start"); 07193 }
| static int manager_show_dialplan | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager listing of dial plan.
Definition at line 7335 of file pbx.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, manager_dpsendack(), manager_show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.
Referenced by load_pbx().
07336 { 07337 const char *exten, *context; 07338 const char *id = astman_get_header(m, "ActionID"); 07339 char idtext[256]; 07340 07341 /* Variables used for different counters */ 07342 struct dialplan_counters counters; 07343 07344 if (!ast_strlen_zero(id)) 07345 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 07346 else 07347 idtext[0] = '\0'; 07348 07349 memset(&counters, 0, sizeof(counters)); 07350 07351 exten = astman_get_header(m, "Extension"); 07352 context = astman_get_header(m, "Context"); 07353 07354 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 07355 07356 if (!ast_strlen_zero(context) && !counters.context_existence) { 07357 char errorbuf[BUFSIZ]; 07358 07359 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 07360 astman_send_error(s, m, errorbuf); 07361 return 0; 07362 } 07363 if (!ast_strlen_zero(exten) && !counters.extension_existence) { 07364 char errorbuf[BUFSIZ]; 07365 07366 if (!ast_strlen_zero(context)) 07367 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 07368 else 07369 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 07370 astman_send_error(s, m, errorbuf); 07371 return 0; 07372 } 07373 07374 if (!counters.total_items) { 07375 manager_dpsendack(s, m); 07376 } 07377 07378 astman_append(s, "Event: ShowDialPlanComplete\r\n" 07379 "EventList: Complete\r\n" 07380 "ListItems: %d\r\n" 07381 "ListExtensions: %d\r\n" 07382 "ListPriorities: %d\r\n" 07383 "ListContexts: %d\r\n" 07384 "%s" 07385 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 07386 07387 /* everything ok */ 07388 return 0; 07389 }
| static int manager_show_dialplan_helper | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| const char * | actionidtext, | |||
| const char * | context, | |||
| const char * | exten, | |||
| struct dialplan_counters * | dpc, | |||
| struct ast_include * | rinclude | |||
| ) | [static] |
Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not.
Definition at line 7199 of file pbx.c.
References ast_debug, ast_extension_match(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log(), AST_MAX_EXTENSION, ast_rdlock_context(), ast_rdlock_contexts(), ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), astman_append(), astman_send_error(), dialplan_counters::context_existence, dialplan_counters::extension_existence, LOG_WARNING, manager_dpsendack(), PRIORITY_HINT, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.
Referenced by manager_show_dialplan().
07203 { 07204 struct ast_context *c; 07205 int res = 0, old_total_exten = dpc->total_exten; 07206 07207 if (ast_strlen_zero(exten)) 07208 exten = NULL; 07209 if (ast_strlen_zero(context)) 07210 context = NULL; 07211 07212 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 07213 07214 /* try to lock contexts */ 07215 if (ast_rdlock_contexts()) { 07216 astman_send_error(s, m, "Failed to lock contexts"); 07217 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 07218 return -1; 07219 } 07220 07221 c = NULL; /* walk all contexts ... */ 07222 while ( (c = ast_walk_contexts(c)) ) { 07223 struct ast_exten *e; 07224 struct ast_include *i; 07225 struct ast_ignorepat *ip; 07226 07227 if (context && strcmp(ast_get_context_name(c), context) != 0) 07228 continue; /* not the name we want */ 07229 07230 dpc->context_existence = 1; 07231 dpc->total_context++; 07232 07233 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 07234 07235 if (ast_rdlock_context(c)) { /* failed to lock */ 07236 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 07237 continue; 07238 } 07239 07240 /* XXX note- an empty context is not printed */ 07241 e = NULL; /* walk extensions in context */ 07242 while ( (e = ast_walk_context_extensions(c, e)) ) { 07243 struct ast_exten *p; 07244 07245 /* looking for extension? is this our extension? */ 07246 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 07247 /* not the one we are looking for, continue */ 07248 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 07249 continue; 07250 } 07251 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 07252 07253 dpc->extension_existence = 1; 07254 07255 dpc->total_exten++; 07256 07257 p = NULL; /* walk next extension peers */ 07258 while ( (p = ast_walk_extension_priorities(e, p)) ) { 07259 int prio = ast_get_extension_priority(p); 07260 07261 dpc->total_prio++; 07262 if (!dpc->total_items++) 07263 manager_dpsendack(s, m); 07264 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07265 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 07266 07267 /* XXX maybe make this conditional, if p != e ? */ 07268 if (ast_get_extension_label(p)) 07269 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 07270 07271 if (prio == PRIORITY_HINT) { 07272 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 07273 } else { 07274 astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p)); 07275 } 07276 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 07277 } 07278 } 07279 07280 i = NULL; /* walk included and write info ... */ 07281 while ( (i = ast_walk_context_includes(c, i)) ) { 07282 if (exten) { 07283 /* Check all includes for the requested extension */ 07284 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 07285 } else { 07286 if (!dpc->total_items++) 07287 manager_dpsendack(s, m); 07288 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07289 astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i)); 07290 astman_append(s, "\r\n"); 07291 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 07292 } 07293 } 07294 07295 ip = NULL; /* walk ignore patterns and write info ... */ 07296 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 07297 const char *ipname = ast_get_ignorepat_name(ip); 07298 char ignorepat[AST_MAX_EXTENSION]; 07299 07300 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 07301 if (!exten || ast_extension_match(ignorepat, exten)) { 07302 if (!dpc->total_items++) 07303 manager_dpsendack(s, m); 07304 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07305 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 07306 astman_append(s, "\r\n"); 07307 } 07308 } 07309 if (!rinclude) { 07310 struct ast_sw *sw = NULL; 07311 while ( (sw = ast_walk_context_switches(c, sw)) ) { 07312 if (!dpc->total_items++) 07313 manager_dpsendack(s, m); 07314 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07315 astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw)); 07316 astman_append(s, "\r\n"); 07317 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 07318 } 07319 } 07320 07321 ast_unlock_context(c); 07322 } 07323 ast_unlock_contexts(); 07324 07325 if (dpc->total_exten == old_total_exten) { 07326 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 07327 /* Nothing new under the sun */ 07328 return -1; 07329 } else { 07330 return res; 07331 } 07332 }
| static int matchcid | ( | const char * | cidpattern, | |
| const char * | callerid | |||
| ) | [static] |
Definition at line 2959 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02960 { 02961 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02962 failing to get a number should count as a match, otherwise not */ 02963 02964 if (ast_strlen_zero(callerid)) { 02965 return ast_strlen_zero(cidpattern) ? 1 : 0; 02966 } 02967 02968 return ast_extension_match(cidpattern, callerid); 02969 }
| static void new_find_extension | ( | const char * | str, | |
| struct scoreboard * | score, | |||
| struct match_char * | tree, | |||
| int | length, | |||
| int | spec, | |||
| const char * | callerid, | |||
| const char * | label, | |||
| enum ext_match_t | action | |||
| ) | [static] |
Definition at line 1765 of file pbx.c.
References match_char::alt_char, ast_debug, ast_log(), scoreboard::canmatch, match_char::deleted, E_CANMATCH, E_MATCHMORE, ast_exten::exten, scoreboard::exten, match_char::exten, match_char::is_pattern, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, NEW_MATCHER_RECURSE, match_char::next_char, match_char::specificity, update_scoreboard(), and match_char::x.
Referenced by pbx_find_extension().
01766 { 01767 struct match_char *p; /* note minimal stack storage requirements */ 01768 struct ast_exten pattern = { .label = label }; 01769 #ifdef DEBUG_THIS 01770 if (tree) 01771 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01772 else 01773 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01774 #endif 01775 for (p = tree; p; p = p->alt_char) { 01776 if (p->is_pattern) { 01777 if (p->x[0] == 'N') { 01778 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01779 #define NEW_MATCHER_CHK_MATCH \ 01780 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01781 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01782 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01783 if (!p->deleted) { \ 01784 if (action == E_FINDLABEL) { \ 01785 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01786 ast_debug(4, "Found label in preferred extension\n"); \ 01787 return; \ 01788 } \ 01789 } else { \ 01790 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01791 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01792 } \ 01793 } \ 01794 } \ 01795 } 01796 01797 #define NEW_MATCHER_RECURSE \ 01798 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01799 || p->next_char->x[0] == '!')) { \ 01800 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01801 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01802 if (score->exten) { \ 01803 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01804 return; /* the first match is all we need */ \ 01805 } \ 01806 } else { \ 01807 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01808 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01809 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01810 "NULL"); \ 01811 return; /* the first match is all we need */ \ 01812 } \ 01813 } \ 01814 } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \ 01815 score->canmatch = 1; \ 01816 score->canmatch_exten = get_canmatch_exten(p); \ 01817 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01818 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01819 return; \ 01820 } \ 01821 } 01822 01823 NEW_MATCHER_CHK_MATCH; 01824 NEW_MATCHER_RECURSE; 01825 } 01826 } else if (p->x[0] == 'Z') { 01827 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01828 NEW_MATCHER_CHK_MATCH; 01829 NEW_MATCHER_RECURSE; 01830 } 01831 } else if (p->x[0] == 'X') { 01832 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01833 NEW_MATCHER_CHK_MATCH; 01834 NEW_MATCHER_RECURSE; 01835 } 01836 } else if (p->x[0] == '.' && p->x[1] == 0) { 01837 /* how many chars will the . match against? */ 01838 int i = 0; 01839 const char *str2 = str; 01840 while (*str2 && *str2 != '/') { 01841 str2++; 01842 i++; 01843 } 01844 if (p->exten && *str2 != '/') { 01845 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01846 if (score->exten) { 01847 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01848 return; /* the first match is all we need */ 01849 } 01850 } 01851 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01852 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01853 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01854 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01855 return; /* the first match is all we need */ 01856 } 01857 } 01858 } else if (p->x[0] == '!' && p->x[1] == 0) { 01859 /* how many chars will the . match against? */ 01860 int i = 1; 01861 const char *str2 = str; 01862 while (*str2 && *str2 != '/') { 01863 str2++; 01864 i++; 01865 } 01866 if (p->exten && *str2 != '/') { 01867 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01868 if (score->exten) { 01869 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01870 return; /* the first match is all we need */ 01871 } 01872 } 01873 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01874 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01875 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01876 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01877 return; /* the first match is all we need */ 01878 } 01879 } 01880 } else if (p->x[0] == '/' && p->x[1] == 0) { 01881 /* the pattern in the tree includes the cid match! */ 01882 if (p->next_char && callerid && *callerid) { 01883 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01884 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01885 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01886 return; /* the first match is all we need */ 01887 } 01888 } 01889 } else if (strchr(p->x, *str)) { 01890 ast_debug(4, "Nothing strange about this match\n"); 01891 NEW_MATCHER_CHK_MATCH; 01892 NEW_MATCHER_RECURSE; 01893 } 01894 } else if (strchr(p->x, *str)) { 01895 ast_debug(4, "Nothing strange about this match\n"); 01896 NEW_MATCHER_CHK_MATCH; 01897 NEW_MATCHER_RECURSE; 01898 } 01899 } 01900 ast_debug(4, "return at end of func\n"); 01901 }
| static int parse_variable_name | ( | char * | var, | |
| int * | offset, | |||
| int * | length, | |||
| int * | isfunc | |||
| ) | [static] |
extract offset:length from variable name.
Definition at line 3269 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
03270 { 03271 int parens = 0; 03272 03273 *offset = 0; 03274 *length = INT_MAX; 03275 *isfunc = 0; 03276 for (; *var; var++) { 03277 if (*var == '(') { 03278 (*isfunc)++; 03279 parens++; 03280 } else if (*var == ')') { 03281 parens--; 03282 } else if (*var == ':' && parens == 0) { 03283 *var++ = '\0'; 03284 sscanf(var, "%30d:%30d", offset, length); 03285 return 1; /* offset:length valid */ 03286 } 03287 } 03288 return 0; 03289 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10632 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), pbx_shutdown(), and reload().
10633 { 10634 struct ast_var_t *vardata; 10635 10636 ast_rwlock_wrlock(&globalslock); 10637 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10638 ast_var_delete(vardata); 10639 ast_rwlock_unlock(&globalslock); 10640 }
| const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name | |||
| ) |
Return a pointer to the value of the corresponding channel variable.
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 10398 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_exec(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
10399 { 10400 struct ast_var_t *variables; 10401 const char *ret = NULL; 10402 int i; 10403 struct varshead *places[2] = { NULL, &globals }; 10404 10405 if (!name) 10406 return NULL; 10407 10408 if (chan) { 10409 ast_channel_lock(chan); 10410 places[0] = &chan->varshead; 10411 } 10412 10413 for (i = 0; i < 2; i++) { 10414 if (!places[i]) 10415 continue; 10416 if (places[i] == &globals) 10417 ast_rwlock_rdlock(&globalslock); 10418 AST_LIST_TRAVERSE(places[i], variables, entries) { 10419 if (!strcmp(name, ast_var_name(variables))) { 10420 ret = ast_var_value(variables); 10421 break; 10422 } 10423 } 10424 if (places[i] == &globals) 10425 ast_rwlock_unlock(&globalslock); 10426 if (ret) 10427 break; 10428 } 10429 10430 if (chan) 10431 ast_channel_unlock(chan); 10432 10433 return ret; 10434 }
| static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10654 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), and pbx_checkcondition().
10655 { 10656 char *condition, *branch1, *branch2, *branch; 10657 char *stringp; 10658 10659 if (ast_strlen_zero(data)) { 10660 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 10661 return 0; 10662 } 10663 10664 stringp = ast_strdupa(data); 10665 condition = strsep(&stringp,"?"); 10666 branch1 = strsep(&stringp,":"); 10667 branch2 = strsep(&stringp,""); 10668 branch = pbx_checkcondition(condition) ? branch1 : branch2; 10669 10670 if (ast_strlen_zero(branch)) { 10671 ast_debug(1, "Not taking any branch\n"); 10672 return 0; 10673 } 10674 10675 return pbx_builtin_goto(chan, branch); 10676 }
| int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10592 of file pbx.c.
References ast_alloca, ast_channel_get_by_name(), ast_channel_unref, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), value, and VAR_BUF_SIZE.
10593 { 10594 char *name; 10595 char *value; 10596 char *channel; 10597 char tmp[VAR_BUF_SIZE]; 10598 static int deprecation_warning = 0; 10599 10600 if (ast_strlen_zero(data)) { 10601 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 10602 return 0; 10603 } 10604 tmp[0] = 0; 10605 if (!deprecation_warning) { 10606 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 10607 deprecation_warning = 1; 10608 } 10609 10610 value = ast_strdupa(data); 10611 name = strsep(&value,"="); 10612 channel = strsep(&value,","); 10613 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 10614 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 10615 if (chan2) { 10616 char *s = ast_alloca(strlen(value) + 4); 10617 sprintf(s, "${%s}", value); 10618 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 10619 chan2 = ast_channel_unref(chan2); 10620 } 10621 pbx_builtin_setvar_helper(chan, name, tmp); 10622 } 10623 10624 return(0); 10625 }
| static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 9919 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_CONTROL_INCOMPLETE, ast_indicate(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
09920 { 09921 const char *options = data; 09922 int answer = 1; 09923 09924 /* Some channels can receive DTMF in unanswered state; some cannot */ 09925 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 09926 answer = 0; 09927 } 09928 09929 /* If the channel is hungup, stop waiting */ 09930 if (ast_check_hangup(chan)) { 09931 return -1; 09932 } else if (chan->_state != AST_STATE_UP && answer) { 09933 __ast_answer(chan, 0, 1); 09934 } 09935 09936 ast_indicate(chan, AST_CONTROL_INCOMPLETE); 09937 09938 return AST_PBX_INCOMPLETE; 09939 }
| static int pbx_builtin_noop | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
| 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 10436 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().
10437 { 10438 struct ast_var_t *newvariable; 10439 struct varshead *headp; 10440 10441 if (name[strlen(name)-1] == ')') { 10442 char *function = ast_strdupa(name); 10443 10444 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10445 ast_func_write(chan, function, value); 10446 return; 10447 } 10448 10449 if (chan) { 10450 ast_channel_lock(chan); 10451 headp = &chan->varshead; 10452 } else { 10453 ast_rwlock_wrlock(&globalslock); 10454 headp = &globals; 10455 } 10456 10457 if (value && (newvariable = ast_var_assign(name, value))) { 10458 if (headp == &globals) 10459 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10460 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10461 } 10462 10463 if (chan) 10464 ast_channel_unlock(chan); 10465 else 10466 ast_rwlock_unlock(&globalslock); 10467 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| const char * | reason | |||
| ) |
Definition at line 3578 of file pbx.c.
References raise_exception().
03579 { 03580 /* Priority will become 1, next time through the AUTOLOOP */ 03581 return raise_exception(chan, reason, 0); 03582 }
| static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10715 of file pbx.c.
References ast_say_character_str().
10716 { 10717 int res = 0; 10718 10719 if (data) 10720 res = ast_say_character_str(chan, data, "", chan->language); 10721 return res; 10722 }
| static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10706 of file pbx.c.
References ast_say_digit_str().
10707 { 10708 int res = 0; 10709 10710 if (data) 10711 res = ast_say_digit_str(chan, data, "", chan->language); 10712 return res; 10713 }
| static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10678 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), and LOG_WARNING.
10679 { 10680 char tmp[256]; 10681 char *number = tmp; 10682 char *options; 10683 10684 if (ast_strlen_zero(data)) { 10685 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 10686 return -1; 10687 } 10688 ast_copy_string(tmp, data, sizeof(tmp)); 10689 strsep(&number, ","); 10690 options = strsep(&number, ","); 10691 if (options) { 10692 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 10693 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 10694 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 10695 return -1; 10696 } 10697 } 10698 10699 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 10700 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 10701 } 10702 10703 return 0; 10704 }
| static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10724 of file pbx.c.
References ast_say_phonetic_str().
10725 { 10726 int res = 0; 10727 10728 if (data) 10729 res = ast_say_phonetic_str(chan, data, "", chan->language); 10730 return res; 10731 }
| 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 10367 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
10368 { 10369 struct ast_var_t *variables; 10370 const char *var, *val; 10371 int total = 0; 10372 10373 if (!chan) 10374 return 0; 10375 10376 ast_str_reset(*buf); 10377 10378 ast_channel_lock(chan); 10379 10380 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10381 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10382 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10383 ) { 10384 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10385 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10386 break; 10387 } else 10388 total++; 10389 } else 10390 break; 10391 } 10392 10393 ast_channel_unlock(chan); 10394 10395 return total; 10396 }
| 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 10526 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), and value.
Referenced by ast_compile_ael2().
10527 { 10528 char *name, *value, *mydata; 10529 10530 if (ast_compat_app_set) { 10531 return pbx_builtin_setvar_multiple(chan, data); 10532 } 10533 10534 if (ast_strlen_zero(data)) { 10535 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10536 return 0; 10537 } 10538 10539 mydata = ast_strdupa(data); 10540 name = strsep(&mydata, "="); 10541 value = mydata; 10542 if (!value) { 10543 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10544 return 0; 10545 } 10546 10547 if (strchr(name, ' ')) { 10548 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10549 } 10550 10551 pbx_builtin_setvar_helper(chan, name, value); 10552 10553 return 0; 10554 }
| 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 10469 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), 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(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
10470 { 10471 struct ast_var_t *newvariable; 10472 struct varshead *headp; 10473 const char *nametail = name; 10474 10475 if (name[strlen(name) - 1] == ')') { 10476 char *function = ast_strdupa(name); 10477 10478 return ast_func_write(chan, function, value); 10479 } 10480 10481 if (chan) { 10482 ast_channel_lock(chan); 10483 headp = &chan->varshead; 10484 } else { 10485 ast_rwlock_wrlock(&globalslock); 10486 headp = &globals; 10487 } 10488 10489 /* For comparison purposes, we have to strip leading underscores */ 10490 if (*nametail == '_') { 10491 nametail++; 10492 if (*nametail == '_') 10493 nametail++; 10494 } 10495 10496 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10497 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10498 /* there is already such a variable, delete it */ 10499 AST_LIST_REMOVE_CURRENT(entries); 10500 ast_var_delete(newvariable); 10501 break; 10502 } 10503 } 10504 AST_LIST_TRAVERSE_SAFE_END; 10505 10506 if (value && (newvariable = ast_var_assign(name, value))) { 10507 if (headp == &globals) 10508 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10509 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10510 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10511 "Channel: %s\r\n" 10512 "Variable: %s\r\n" 10513 "Value: %s\r\n" 10514 "Uniqueid: %s\r\n", 10515 chan ? chan->name : "none", name, value, 10516 chan ? chan->uniqueid : "none"); 10517 } 10518 10519 if (chan) 10520 ast_channel_unlock(chan); 10521 else 10522 ast_rwlock_unlock(&globalslock); 10523 return 0; 10524 }
| 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 10556 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().
10557 { 10558 char *data; 10559 int x; 10560 AST_DECLARE_APP_ARGS(args, 10561 AST_APP_ARG(pair)[24]; 10562 ); 10563 AST_DECLARE_APP_ARGS(pair, 10564 AST_APP_ARG(name); 10565 AST_APP_ARG(value); 10566 ); 10567 10568 if (ast_strlen_zero(vdata)) { 10569 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10570 return 0; 10571 } 10572 10573 data = ast_strdupa(vdata); 10574 AST_STANDARD_APP_ARGS(args, data); 10575 10576 for (x = 0; x < args.argc; x++) { 10577 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10578 if (pair.argc == 2) { 10579 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10580 if (strchr(pair.name, ' ')) 10581 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); 10582 } else if (!chan) { 10583 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10584 } else { 10585 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10586 } 10587 } 10588 10589 return 0; 10590 }
| 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 10642 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().
10643 { 10644 int res; 10645 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10646 return 0; 10647 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10648 return res; 10649 } else { /* Strings are true */ 10650 return 1; 10651 } 10652 }
| static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 1531 of file pbx.c.
References ast_free.
Referenced by __ast_pbx_run().
01532 { 01533 ast_free(p); 01534 }
| int pbx_exec | ( | struct ast_channel * | c, | |
| struct ast_app * | app, | |||
| const char * | data | |||
| ) |
Execute an application.
| c | channel to execute on | |
| app | which app to execute | |
| data | the data passed into the app |
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.
| 0 | success | |
| -1 | failure |
| c | Channel | |
| app | Application | |
| data | Data for execution |
Definition at line 1451 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(), try_calling(), and tryexec_exec().
01454 { 01455 int res; 01456 struct ast_module_user *u = NULL; 01457 const char *saved_c_appl; 01458 const char *saved_c_data; 01459 01460 if (c->cdr && !ast_check_hangup(c)) 01461 ast_cdr_setapp(c->cdr, app->name, data); 01462 01463 /* save channel values */ 01464 saved_c_appl= c->appl; 01465 saved_c_data= c->data; 01466 01467 c->appl = app->name; 01468 c->data = data; 01469 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01470 01471 if (app->module) 01472 u = __ast_module_user_add(app->module, c); 01473 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01474 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01475 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01476 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01477 app->name, (char *) data); 01478 } 01479 res = app->execute(c, S_OR(data, "")); 01480 if (app->module && u) 01481 __ast_module_user_remove(app->module, u); 01482 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01483 /* restore channel values */ 01484 c->appl = saved_c_appl; 01485 c->data = saved_c_data; 01486 return res; 01487 }
| static int pbx_extension_helper | ( | struct ast_channel * | c, | |
| struct ast_context * | con, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| enum ext_match_t | action, | |||
| int * | found, | |||
| int | combined_find_spawn | |||
| ) | [static] |
The return value depends on the action:.
E_MATCH, E_CANMATCH, E_MATCHMORE require a real match, and return 0 on failure, -1 on match; E_FINDLABEL maps the label to a priority, and returns the priority on success, ... XXX E_SPAWN, spawn an application,
| 0 | on success. | |
| -1 | on failure. |
Definition at line 4663 of file pbx.c.
References ast_exten::app, app, ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_strdupa, ast_strlen_zero(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, ast_exten::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_DIALPLAN, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, manager_event, ast_switch::name, ast_app::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables_helper(), ast_channel::priority, ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), and VERBOSITY_ATLEAST.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
04666 { 04667 struct ast_exten *e; 04668 struct ast_app *app; 04669 char *substitute = NULL; 04670 int res; 04671 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04672 char passdata[EXT_DATA_SIZE]; 04673 04674 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04675 04676 ast_rdlock_contexts(); 04677 if (found) 04678 *found = 0; 04679 04680 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04681 if (e) { 04682 if (found) 04683 *found = 1; 04684 if (matching_action) { 04685 ast_unlock_contexts(); 04686 return -1; /* success, we found it */ 04687 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04688 res = e->priority; 04689 ast_unlock_contexts(); 04690 return res; /* the priority we were looking for */ 04691 } else { /* spawn */ 04692 if (!e->cached_app) 04693 e->cached_app = pbx_findapp(e->app); 04694 app = e->cached_app; 04695 if (ast_strlen_zero(e->data)) { 04696 *passdata = '\0'; 04697 } else { 04698 const char *tmp; 04699 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 04700 /* no variables to substitute, copy on through */ 04701 ast_copy_string(passdata, e->data, sizeof(passdata)); 04702 } else { 04703 /* save e->data on stack for later processing after lock released */ 04704 substitute = ast_strdupa(e->data); 04705 } 04706 } 04707 ast_unlock_contexts(); 04708 if (!app) { 04709 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04710 return -1; 04711 } 04712 if (c->context != context) 04713 ast_copy_string(c->context, context, sizeof(c->context)); 04714 if (c->exten != exten) 04715 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04716 c->priority = priority; 04717 if (substitute) { 04718 pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1); 04719 } 04720 #ifdef CHANNEL_TRACE 04721 ast_channel_trace_update(c); 04722 #endif 04723 ast_debug(1, "Launching '%s'\n", app->name); 04724 if (VERBOSITY_ATLEAST(3)) { 04725 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04726 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04727 exten, context, priority, 04728 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04729 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04730 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04731 "in new stack"); 04732 } 04733 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04734 "Channel: %s\r\n" 04735 "Context: %s\r\n" 04736 "Extension: %s\r\n" 04737 "Priority: %d\r\n" 04738 "Application: %s\r\n" 04739 "AppData: %s\r\n" 04740 "Uniqueid: %s\r\n", 04741 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 04742 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04743 } 04744 } else if (q.swo) { /* not found here, but in another switch */ 04745 if (found) 04746 *found = 1; 04747 ast_unlock_contexts(); 04748 if (matching_action) { 04749 return -1; 04750 } else { 04751 if (!q.swo->exec) { 04752 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04753 res = -1; 04754 } 04755 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04756 } 04757 } else { /* not found anywhere, see what happened */ 04758 ast_unlock_contexts(); 04759 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04760 switch (q.status) { 04761 case STATUS_NO_CONTEXT: 04762 if (!matching_action && !combined_find_spawn) 04763 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04764 break; 04765 case STATUS_NO_EXTENSION: 04766 if (!matching_action && !combined_find_spawn) 04767 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04768 break; 04769 case STATUS_NO_PRIORITY: 04770 if (!matching_action && !combined_find_spawn) 04771 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04772 break; 04773 case STATUS_NO_LABEL: 04774 if (context && !combined_find_spawn) 04775 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04776 break; 04777 default: 04778 ast_debug(1, "Shouldn't happen!\n"); 04779 } 04780 04781 return (matching_action) ? 0 : -1; 04782 } 04783 }
| 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 2971 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().
02975 { 02976 int x, res; 02977 struct ast_context *tmp = NULL; 02978 struct ast_exten *e = NULL, *eroot = NULL; 02979 struct ast_include *i = NULL; 02980 struct ast_sw *sw = NULL; 02981 struct ast_exten pattern = {NULL, }; 02982 struct scoreboard score = {0, }; 02983 struct ast_str *tmpdata = NULL; 02984 02985 pattern.label = label; 02986 pattern.priority = priority; 02987 #ifdef NEED_DEBUG_HERE 02988 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02989 #endif 02990 02991 /* Initialize status if appropriate */ 02992 if (q->stacklen == 0) { 02993 q->status = STATUS_NO_CONTEXT; 02994 q->swo = NULL; 02995 q->data = NULL; 02996 q->foundcontext = NULL; 02997 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02998 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02999 return NULL; 03000 } 03001 03002 /* Check first to see if we've already been checked */ 03003 for (x = 0; x < q->stacklen; x++) { 03004 if (!strcasecmp(q->incstack[x], context)) 03005 return NULL; 03006 } 03007 03008 if (bypass) { /* bypass means we only look there */ 03009 tmp = bypass; 03010 } else { /* look in contexts */ 03011 tmp = find_context(context); 03012 if (!tmp) { 03013 return NULL; 03014 } 03015 } 03016 03017 if (q->status < STATUS_NO_EXTENSION) 03018 q->status = STATUS_NO_EXTENSION; 03019 03020 /* Do a search for matching extension */ 03021 03022 eroot = NULL; 03023 score.total_specificity = 0; 03024 score.exten = 0; 03025 score.total_length = 0; 03026 if (!tmp->pattern_tree && tmp->root_table) { 03027 create_match_char_tree(tmp); 03028 #ifdef NEED_DEBUG 03029 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 03030 log_match_char_tree(tmp->pattern_tree," "); 03031 #endif 03032 } 03033 #ifdef NEED_DEBUG 03034 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03035 log_match_char_tree(tmp->pattern_tree, ":: "); 03036 #endif 03037 03038 do { 03039 if (!ast_strlen_zero(overrideswitch)) { 03040 char *osw = ast_strdupa(overrideswitch), *name; 03041 struct ast_switch *asw; 03042 ast_switch_f *aswf = NULL; 03043 char *datap; 03044 int eval = 0; 03045 03046 name = strsep(&osw, "/"); 03047 asw = pbx_findswitch(name); 03048 03049 if (!asw) { 03050 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03051 break; 03052 } 03053 03054 if (osw && strchr(osw, '$')) { 03055 eval = 1; 03056 } 03057 03058 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03059 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03060 break; 03061 } else if (eval) { 03062 /* Substitute variables now */ 03063 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03064 datap = ast_str_buffer(tmpdata); 03065 } else { 03066 datap = osw; 03067 } 03068 03069 /* equivalent of extension_match_core() at the switch level */ 03070 if (action == E_CANMATCH) 03071 aswf = asw->canmatch; 03072 else if (action == E_MATCHMORE) 03073 aswf = asw->matchmore; 03074 else /* action == E_MATCH */ 03075 aswf = asw->exists; 03076 if (!aswf) { 03077 res = 0; 03078 } else { 03079 if (chan) { 03080 ast_autoservice_start(chan); 03081 } 03082 res = aswf(chan, context, exten, priority, callerid, datap); 03083 if (chan) { 03084 ast_autoservice_stop(chan); 03085 } 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 } while (0); 03096 03097 if (extenpatternmatchnew) { 03098 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03099 eroot = score.exten; 03100 03101 if (score.last_char == '!' && action == E_MATCHMORE) { 03102 /* We match an extension ending in '!'. 03103 * The decision in this case is final and is NULL (no match). 03104 */ 03105 #ifdef NEED_DEBUG_HERE 03106 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03107 #endif 03108 return NULL; 03109 } 03110 03111 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03112 q->status = STATUS_SUCCESS; 03113 #ifdef NEED_DEBUG_HERE 03114 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03115 #endif 03116 return score.canmatch_exten; 03117 } 03118 03119 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03120 if (score.node) { 03121 struct ast_exten *z = trie_find_next_match(score.node); 03122 if (z) { 03123 #ifdef NEED_DEBUG_HERE 03124 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03125 #endif 03126 } else { 03127 if (score.canmatch_exten) { 03128 #ifdef NEED_DEBUG_HERE 03129 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03130 #endif 03131 return score.canmatch_exten; 03132 } else { 03133 #ifdef NEED_DEBUG_HERE 03134 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03135 #endif 03136 } 03137 } 03138 return z; 03139 } 03140 #ifdef NEED_DEBUG_HERE 03141 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03142 #endif 03143 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03144 } 03145 03146 if (eroot) { 03147 /* found entry, now look for the right priority */ 03148 if (q->status < STATUS_NO_PRIORITY) 03149 q->status = STATUS_NO_PRIORITY; 03150 e = NULL; 03151 if (action == E_FINDLABEL && label ) { 03152 if (q->status < STATUS_NO_LABEL) 03153 q->status = STATUS_NO_LABEL; 03154 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03155 } else { 03156 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03157 } 03158 if (e) { /* found a valid match */ 03159 q->status = STATUS_SUCCESS; 03160 q->foundcontext = context; 03161 #ifdef NEED_DEBUG_HERE 03162 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03163 #endif 03164 return e; 03165 } 03166 } 03167 } else { /* the old/current default exten pattern match algorithm */ 03168 03169 /* scan the list trying to match extension and CID */ 03170 eroot = NULL; 03171 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03172 int match = extension_match_core(eroot->exten, exten, action); 03173 /* 0 on fail, 1 on match, 2 on earlymatch */ 03174 03175 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03176 continue; /* keep trying */ 03177 if (match == 2 && action == E_MATCHMORE) { 03178 /* We match an extension ending in '!'. 03179 * The decision in this case is final and is NULL (no match). 03180 */ 03181 return NULL; 03182 } 03183 /* found entry, now look for the right priority */ 03184 if (q->status < STATUS_NO_PRIORITY) 03185 q->status = STATUS_NO_PRIORITY; 03186 e = NULL; 03187 if (action == E_FINDLABEL && label ) { 03188 if (q->status < STATUS_NO_LABEL) 03189 q->status = STATUS_NO_LABEL; 03190 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03191 } else { 03192 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03193 } 03194 if (e) { /* found a valid match */ 03195 q->status = STATUS_SUCCESS; 03196 q->foundcontext = context; 03197 return e; 03198 } 03199 } 03200 } 03201 03202 /* Check alternative switches */ 03203 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03204 struct ast_switch *asw = pbx_findswitch(sw->name); 03205 ast_switch_f *aswf = NULL; 03206 char *datap; 03207 03208 if (!asw) { 03209 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03210 continue; 03211 } 03212 03213 /* Substitute variables now */ 03214 if (sw->eval) { 03215 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03216 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03217 continue; 03218 } 03219 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03220 } 03221 03222 /* equivalent of extension_match_core() at the switch level */ 03223 if (action == E_CANMATCH) 03224 aswf = asw->canmatch; 03225 else if (action == E_MATCHMORE) 03226 aswf = asw->matchmore; 03227 else /* action == E_MATCH */ 03228 aswf = asw->exists; 03229 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03230 if (!aswf) 03231 res = 0; 03232 else { 03233 if (chan) 03234 ast_autoservice_start(chan); 03235 res = aswf(chan, context, exten, priority, callerid, datap); 03236 if (chan) 03237 ast_autoservice_stop(chan); 03238 } 03239 if (res) { /* Got a match */ 03240 q->swo = asw; 03241 q->data = datap; 03242 q->foundcontext = context; 03243 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03244 return NULL; 03245 } 03246 } 03247 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03248 /* Now try any includes we have in this context */ 03249 for (i = tmp->includes; i; i = i->next) { 03250 if (include_valid(i)) { 03251 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03252 #ifdef NEED_DEBUG_HERE 03253 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03254 #endif 03255 return e; 03256 } 03257 if (q->swo) 03258 return NULL; 03259 } 03260 } 03261 return NULL; 03262 }
| struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 1495 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(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01496 { 01497 struct ast_app *tmp; 01498 01499 AST_RWLIST_RDLOCK(&apps); 01500 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01501 if (!strcasecmp(tmp->name, app)) 01502 break; 01503 } 01504 AST_RWLIST_UNLOCK(&apps); 01505 01506 return tmp; 01507 }
| static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 1509 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
01510 { 01511 struct ast_switch *asw; 01512 01513 AST_RWLIST_RDLOCK(&switches); 01514 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01515 if (!strcasecmp(asw->name, sw)) 01516 break; 01517 } 01518 AST_RWLIST_UNLOCK(&switches); 01519 01520 return asw; 01521 }
| void pbx_live_dangerously | ( | int | new_live_dangerously | ) |
Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).
These dialplan functions (such as SHELL) provide an opportunity for privilege escalation. They are okay to invoke from the dialplan, but external protocols with permission controls should not normally invoke them.
This function can globally enable/disable the execution of dangerous functions from external protocols.
| new_live_dangerously | If true, enable the execution of escalating functions from external protocols. |
Definition at line 4016 of file pbx.c.
References ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by ast_readconfig().
04017 { 04018 if (new_live_dangerously && !live_dangerously) { 04019 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n" 04020 "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n"); 04021 } 04022 04023 if (!new_live_dangerously && live_dangerously) { 04024 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n"); 04025 } 04026 live_dangerously = new_live_dangerously; 04027 }
| static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string, | |||
| int | async | |||
| ) | [static] |
Definition at line 11099 of file pbx.c.
References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_party_id::number, ast_channel::priority, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
11100 { 11101 char *exten, *pri, *context; 11102 char *stringp; 11103 int ipri; 11104 int mode = 0; 11105 11106 if (ast_strlen_zero(goto_string)) { 11107 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 11108 return -1; 11109 } 11110 stringp = ast_strdupa(goto_string); 11111 context = strsep(&stringp, ","); /* guaranteed non-null */ 11112 exten = strsep(&stringp, ","); 11113 pri = strsep(&stringp, ","); 11114 if (!exten) { /* Only a priority in this one */ 11115 pri = context; 11116 exten = NULL; 11117 context = NULL; 11118 } else if (!pri) { /* Only an extension and priority in this one */ 11119 pri = exten; 11120 exten = context; 11121 context = NULL; 11122 } 11123 if (*pri == '+') { 11124 mode = 1; 11125 pri++; 11126 } else if (*pri == '-') { 11127 mode = -1; 11128 pri++; 11129 } 11130 if (sscanf(pri, "%30d", &ipri) != 1) { 11131 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 11132 exten ? exten : chan->exten, pri, 11133 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 11134 if (ipri < 1) { 11135 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 11136 return -1; 11137 } else 11138 mode = 0; 11139 } 11140 /* At this point we have a priority and maybe an extension and a context */ 11141 11142 if (mode) 11143 ipri = chan->priority + (ipri * mode); 11144 11145 if (async) 11146 ast_async_goto(chan, context, exten, ipri); 11147 else 11148 ast_explicit_goto(chan, context, exten, ipri); 11149 11150 return 0; 11151 11152 }
| void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
| const char * | var, | |||
| char ** | ret, | |||
| char * | workspace, | |||
| int | workspacelen, | |||
| struct varshead * | headp | |||
| ) |
Support for Asterisk built-in variables in the dialplan.
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 3392 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().
03393 { 03394 struct ast_str *str = ast_str_create(16); 03395 const char *cret; 03396 03397 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03398 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03399 *ret = cret ? workspace : NULL; 03400 ast_free(str); 03401 }
| 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 5894 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05895 { 05896 int oldval = autofallthrough; 05897 autofallthrough = newval; 05898 return oldval; 05899 }
| 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 5901 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05902 { 05903 int oldval = extenpatternmatchnew; 05904 extenpatternmatchnew = newval; 05905 return oldval; 05906 }
| 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 5908 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05909 { 05910 if (overrideswitch) { 05911 ast_free(overrideswitch); 05912 } 05913 if (!ast_strlen_zero(newval)) { 05914 overrideswitch = ast_strdup(newval); 05915 } else { 05916 overrideswitch = NULL; 05917 } 05918 }
| static void pbx_shutdown | ( | void | ) | [static] |
Definition at line 11219 of file pbx.c.
References ao2_ref, ast_hashtab_destroy(), contexts_table, hints, pbx_builtin_clear_globals(), and statecbs.
Referenced by ast_pbx_init().
11220 { 11221 if (hints) { 11222 ao2_ref(hints, -1); 11223 hints = NULL; 11224 } 11225 if (statecbs) { 11226 ao2_ref(statecbs, -1); 11227 statecbs = NULL; 11228 } 11229 if (contexts_table) { 11230 ast_hashtab_destroy(contexts_table, NULL); 11231 } 11232 pbx_builtin_clear_globals(); 11233 }
| void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 4633 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_extension_helper(), pbx_find_extension(), pbx_load_config(), realtime_exec(), rotate_file(), substituted(), try_calling(), and write_cdr().
04634 { 04635 size_t used; 04636 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04637 }
| void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
| struct varshead * | headp, | |||
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count, | |||
| size_t * | used | |||
| ) |
Definition at line 4437 of file pbx.c.
References ast_alloca, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
04438 { 04439 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04440 char *cp4 = NULL; 04441 const char *tmp, *whereweare, *orig_cp2 = cp2; 04442 int length, offset, offset2, isfunction; 04443 char *workspace = NULL; 04444 char *ltmp = NULL, *var = NULL; 04445 char *nextvar, *nextexp, *nextthing; 04446 char *vars, *vare; 04447 int pos, brackets, needsub, len; 04448 04449 *cp2 = 0; /* just in case nothing ends up there */ 04450 whereweare=tmp=cp1; 04451 while (!ast_strlen_zero(whereweare) && count) { 04452 /* Assume we're copying the whole remaining string */ 04453 pos = strlen(whereweare); 04454 nextvar = NULL; 04455 nextexp = NULL; 04456 nextthing = strchr(whereweare, '$'); 04457 if (nextthing) { 04458 switch (nextthing[1]) { 04459 case '{': 04460 nextvar = nextthing; 04461 pos = nextvar - whereweare; 04462 break; 04463 case '[': 04464 nextexp = nextthing; 04465 pos = nextexp - whereweare; 04466 break; 04467 default: 04468 pos = 1; 04469 } 04470 } 04471 04472 if (pos) { 04473 /* Can't copy more than 'count' bytes */ 04474 if (pos > count) 04475 pos = count; 04476 04477 /* Copy that many bytes */ 04478 memcpy(cp2, whereweare, pos); 04479 04480 count -= pos; 04481 cp2 += pos; 04482 whereweare += pos; 04483 *cp2 = 0; 04484 } 04485 04486 if (nextvar) { 04487 /* We have a variable. Find the start and end, and determine 04488 if we are going to have to recursively call ourselves on the 04489 contents */ 04490 vars = vare = nextvar + 2; 04491 brackets = 1; 04492 needsub = 0; 04493 04494 /* Find the end of it */ 04495 while (brackets && *vare) { 04496 if ((vare[0] == '$') && (vare[1] == '{')) { 04497 needsub++; 04498 } else if (vare[0] == '{') { 04499 brackets++; 04500 } else if (vare[0] == '}') { 04501 brackets--; 04502 } else if ((vare[0] == '$') && (vare[1] == '[')) 04503 needsub++; 04504 vare++; 04505 } 04506 if (brackets) 04507 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04508 len = vare - vars - 1; 04509 04510 /* Skip totally over variable string */ 04511 whereweare += (len + 3); 04512 04513 if (!var) 04514 var = ast_alloca(VAR_BUF_SIZE); 04515 04516 /* Store variable name (and truncate) */ 04517 ast_copy_string(var, vars, len + 1); 04518 04519 /* Substitute if necessary */ 04520 if (needsub) { 04521 size_t used; 04522 if (!ltmp) 04523 ltmp = ast_alloca(VAR_BUF_SIZE); 04524 04525 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04526 vars = ltmp; 04527 } else { 04528 vars = var; 04529 } 04530 04531 if (!workspace) 04532 workspace = ast_alloca(VAR_BUF_SIZE); 04533 04534 workspace[0] = '\0'; 04535 04536 parse_variable_name(vars, &offset, &offset2, &isfunction); 04537 if (isfunction) { 04538 /* Evaluate function */ 04539 if (c || !headp) 04540 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04541 else { 04542 struct varshead old; 04543 struct ast_channel *c = ast_dummy_channel_alloc(); 04544 if (c) { 04545 memcpy(&old, &c->varshead, sizeof(old)); 04546 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04547 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04548 /* Don't deallocate the varshead that was passed in */ 04549 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04550 c = ast_channel_unref(c); 04551 } else { 04552 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04553 } 04554 } 04555 ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)"); 04556 } else { 04557 /* Retrieve variable value */ 04558 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04559 } 04560 if (cp4) { 04561 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04562 04563 length = strlen(cp4); 04564 if (length > count) 04565 length = count; 04566 memcpy(cp2, cp4, length); 04567 count -= length; 04568 cp2 += length; 04569 *cp2 = 0; 04570 } 04571 } else if (nextexp) { 04572 /* We have an expression. Find the start and end, and determine 04573 if we are going to have to recursively call ourselves on the 04574 contents */ 04575 vars = vare = nextexp + 2; 04576 brackets = 1; 04577 needsub = 0; 04578 04579 /* Find the end of it */ 04580 while (brackets && *vare) { 04581 if ((vare[0] == '$') && (vare[1] == '[')) { 04582 needsub++; 04583 brackets++; 04584 vare++; 04585 } else if (vare[0] == '[') { 04586 brackets++; 04587 } else if (vare[0] == ']') { 04588 brackets--; 04589 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04590 needsub++; 04591 vare++; 04592 } 04593 vare++; 04594 } 04595 if (brackets) 04596 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04597 len = vare - vars - 1; 04598 04599 /* Skip totally over expression */ 04600 whereweare += (len + 3); 04601 04602 if (!var) 04603 var = ast_alloca(VAR_BUF_SIZE); 04604 04605 /* Store variable name (and truncate) */ 04606 ast_copy_string(var, vars, len + 1); 04607 04608 /* Substitute if necessary */ 04609 if (needsub) { 04610 size_t used; 04611 if (!ltmp) 04612 ltmp = ast_alloca(VAR_BUF_SIZE); 04613 04614 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04615 vars = ltmp; 04616 } else { 04617 vars = var; 04618 } 04619 04620 length = ast_expr(vars, cp2, count, c); 04621 04622 if (length) { 04623 ast_debug(1, "Expression result is '%s'\n", cp2); 04624 count -= length; 04625 cp2 += length; 04626 *cp2 = 0; 04627 } 04628 } 04629 } 04630 *used = cp2 - orig_cp2; 04631 }
| void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 4639 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04640 { 04641 size_t used; 04642 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04643 }
| static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5812 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05813 { 05814 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05815 answer this channel and get it going. 05816 */ 05817 /* NOTE: 05818 The launcher of this function _MUST_ increment 'countcalls' 05819 before invoking the function; it will be decremented when the 05820 PBX has finished running on the channel 05821 */ 05822 struct ast_channel *c = data; 05823 05824 __ast_pbx_run(c, NULL); 05825 decrease_call_count(); 05826 05827 pthread_exit(NULL); 05828 05829 return NULL; 05830 }
| static void print_app_docs | ( | struct ast_app * | aa, | |
| int | fd | |||
| ) | [static] |
Definition at line 6421 of file pbx.c.
References ast_app::arguments, ast_cli(), ast_free, ast_malloc, AST_MAX_APP, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), COLOR_CYAN, COLOR_MAGENTA, ast_app::description, ast_switch::description, ast_app::docsrc, ast_app::name, S_OR, ast_app::seealso, ast_app::synopsis, synopsis, ast_app::syntax, and term_color().
Referenced by handle_show_application().
06422 { 06423 /* Maximum number of characters added by terminal coloring is 22 */ 06424 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 06425 char seealsotitle[40]; 06426 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 06427 char *seealso = NULL; 06428 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 06429 06430 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 06431 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 06432 06433 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 06434 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 06435 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 06436 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 06437 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 06438 06439 #ifdef AST_XML_DOCS 06440 if (aa->docsrc == AST_XML_DOC) { 06441 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 06442 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 06443 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 06444 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 06445 06446 if (!synopsis || !description || !arguments || !seealso) { 06447 goto return_cleanup; 06448 } 06449 } else 06450 #endif 06451 { 06452 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06453 synopsis = ast_malloc(synopsis_size); 06454 06455 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06456 description = ast_malloc(description_size); 06457 06458 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06459 arguments = ast_malloc(arguments_size); 06460 06461 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06462 seealso = ast_malloc(seealso_size); 06463 06464 if (!synopsis || !description || !arguments || !seealso) { 06465 goto return_cleanup; 06466 } 06467 06468 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 06469 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 06470 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 06471 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 06472 } 06473 06474 /* Handle the syntax the same for both XML and raw docs */ 06475 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06476 if (!(syntax = ast_malloc(syntax_size))) { 06477 goto return_cleanup; 06478 } 06479 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 06480 06481 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 06482 infotitle, syntitle, synopsis, destitle, description, 06483 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 06484 06485 return_cleanup: 06486 ast_free(description); 06487 ast_free(arguments); 06488 ast_free(synopsis); 06489 ast_free(seealso); 06490 ast_free(syntax); 06491 }
| static void print_ext | ( | struct ast_exten * | e, | |
| char * | buf, | |||
| int | buflen | |||
| ) | [static] |
helper function to print an extension
Definition at line 6847 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_priority(), ast_strlen_zero(), and PRIORITY_HINT.
Referenced by show_dialplan_helper().
06848 { 06849 int prio = ast_get_extension_priority(e); 06850 if (prio == PRIORITY_HINT) { 06851 snprintf(buf, buflen, "hint: %s", 06852 ast_get_extension_app(e)); 06853 } else { 06854 snprintf(buf, buflen, "%d. %s(%s)", 06855 prio, ast_get_extension_app(e), 06856 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06857 } 06858 }
| static int raise_exception | ( | struct ast_channel * | chan, | |
| const char * | reason, | |||
| int | priority | |||
| ) | [static] |
Definition at line 3552 of file pbx.c.
References ast_calloc_with_stringfields, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run(), pbx_builtin_raise_exception(), and pbx_builtin_waitexten().
03553 { 03554 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03555 struct pbx_exception *exception = NULL; 03556 03557 if (!ds) { 03558 ds = ast_datastore_alloc(&exception_store_info, NULL); 03559 if (!ds) 03560 return -1; 03561 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03562 ast_datastore_free(ds); 03563 return -1; 03564 } 03565 ds->data = exception; 03566 ast_channel_datastore_add(chan, ds); 03567 } else 03568 exception = ds->data; 03569 03570 ast_string_field_set(exception, reason, reason); 03571 ast_string_field_set(exception, context, chan->context); 03572 ast_string_field_set(exception, exten, chan->exten); 03573 exception->priority = chan->priority; 03574 set_ext_pri(chan, "e", priority); 03575 return 0; 03576 }
| static int read_escalates | ( | const struct ast_custom_function * | acf | ) | [static] |
Returns true if given custom function escalates privileges on read.
| acf | Custom function to query. |
Definition at line 3813 of file pbx.c.
References ast_custom_escalating_function::acf, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_escalating_function::read_escalates.
Referenced by is_read_allowed().
03813 { 03814 int res = 0; 03815 struct ast_custom_escalating_function *cur_escalation; 03816 03817 AST_RWLIST_RDLOCK(&escalation_root); 03818 AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) { 03819 if (cur_escalation->acf == acf) { 03820 res = cur_escalation->read_escalates; 03821 break; 03822 } 03823 } 03824 AST_RWLIST_UNLOCK(&escalation_root); 03825 return res; 03826 }
| static void set_ext_pri | ( | struct ast_channel * | c, | |
| const char * | exten, | |||
| int | pri | |||
| ) | [static] |
helper function to set extension and priority
Definition at line 5384 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_channel::exten, and ast_channel::priority.
Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten(), pbx_builtin_waitexten(), and raise_exception().
05385 { 05386 ast_channel_lock(c); 05387 ast_copy_string(c->exten, exten, sizeof(c->exten)); 05388 c->priority = pri; 05389 ast_channel_unlock(c); 05390 }
| static int show_debug_helper | ( | int | fd, | |
| const char * | context, | |||
| const char * | exten, | |||
| struct dialplan_counters * | dpc, | |||
| struct ast_include * | rinclude, | |||
| int | includecount, | |||
| const char * | includes[] | |||
| ) | [static] |
Definition at line 7012 of file pbx.c.
References ast_cli(), ast_exists_extension(), ast_get_context_name(), ast_get_context_registrar(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_contexts(), cli_match_char_tree(), dialplan_counters::context_existence, ast_context::name, ast_context::pattern_tree, dialplan_counters::total_context, and dialplan_counters::total_exten.
Referenced by handle_debug_dialplan().
07013 { 07014 struct ast_context *c = NULL; 07015 int res = 0, old_total_exten = dpc->total_exten; 07016 07017 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 07018 07019 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 07020 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 07021 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 07022 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 07023 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 07024 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 07025 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 07026 ast_rdlock_contexts(); 07027 07028 /* walk all contexts ... */ 07029 while ( (c = ast_walk_contexts(c)) ) { 07030 int context_info_printed = 0; 07031 07032 if (context && strcmp(ast_get_context_name(c), context)) 07033 continue; /* skip this one, name doesn't match */ 07034 07035 dpc->context_existence = 1; 07036 07037 if (!c->pattern_tree) { 07038 /* Ignore check_return warning from Coverity for ast_exists_extension below */ 07039 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 07040 } 07041 07042 ast_rdlock_context(c); 07043 07044 dpc->total_context++; 07045 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 07046 ast_get_context_name(c), ast_get_context_registrar(c)); 07047 context_info_printed = 1; 07048 07049 if (c->pattern_tree) 07050 { 07051 cli_match_char_tree(c->pattern_tree, " ", fd); 07052 } else { 07053 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 07054 } 07055 07056 ast_unlock_context(c); 07057 07058 /* if we print something in context, make an empty line */ 07059 if (context_info_printed) 07060 ast_cli(fd, "\n"); 07061 } 07062 ast_unlock_contexts(); 07063 07064 return (dpc->total_exten == old_total_exten) ? -1 : res; 07065 }
| static int show_dialplan_helper | ( | int | fd, | |
| const char * | context, | |||
| const char * | exten, | |||
| struct dialplan_counters * | dpc, | |||
| struct ast_include * | rinclude, | |||
| int | includecount, | |||
| const char * | includes[] | |||
| ) | [static] |
Definition at line 6861 of file pbx.c.
References ast_cli(), AST_EXT_MATCHCID_ON, ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
06862 { 06863 struct ast_context *c = NULL; 06864 int res = 0, old_total_exten = dpc->total_exten; 06865 06866 ast_rdlock_contexts(); 06867 06868 /* walk all contexts ... */ 06869 while ( (c = ast_walk_contexts(c)) ) { 06870 struct ast_exten *e; 06871 struct ast_include *i; 06872 struct ast_ignorepat *ip; 06873 char buf[256], buf2[256]; 06874 int context_info_printed = 0; 06875 06876 if (context && strcmp(ast_get_context_name(c), context)) 06877 continue; /* skip this one, name doesn't match */ 06878 06879 dpc->context_existence = 1; 06880 06881 ast_rdlock_context(c); 06882 06883 /* are we looking for exten too? if yes, we print context 06884 * only if we find our extension. 06885 * Otherwise print context even if empty ? 06886 * XXX i am not sure how the rinclude is handled. 06887 * I think it ought to go inside. 06888 */ 06889 if (!exten) { 06890 dpc->total_context++; 06891 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06892 ast_get_context_name(c), ast_get_context_registrar(c)); 06893 context_info_printed = 1; 06894 } 06895 06896 /* walk extensions ... */ 06897 e = NULL; 06898 while ( (e = ast_walk_context_extensions(c, e)) ) { 06899 struct ast_exten *p; 06900 06901 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06902 continue; /* skip, extension match failed */ 06903 06904 dpc->extension_existence = 1; 06905 06906 /* may we print context info? */ 06907 if (!context_info_printed) { 06908 dpc->total_context++; 06909 if (rinclude) { /* TODO Print more info about rinclude */ 06910 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06911 ast_get_context_name(c), ast_get_context_registrar(c)); 06912 } else { 06913 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06914 ast_get_context_name(c), ast_get_context_registrar(c)); 06915 } 06916 context_info_printed = 1; 06917 } 06918 dpc->total_prio++; 06919 06920 /* write extension name and first peer */ 06921 if (e->matchcid == AST_EXT_MATCHCID_ON) 06922 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06923 else 06924 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06925 06926 print_ext(e, buf2, sizeof(buf2)); 06927 06928 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06929 ast_get_extension_registrar(e)); 06930 06931 dpc->total_exten++; 06932 /* walk next extension peers */ 06933 p = e; /* skip the first one, we already got it */ 06934 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06935 const char *el = ast_get_extension_label(p); 06936 dpc->total_prio++; 06937 if (el) 06938 snprintf(buf, sizeof(buf), " [%s]", el); 06939 else 06940 buf[0] = '\0'; 06941 print_ext(p, buf2, sizeof(buf2)); 06942 06943 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 06944 ast_get_extension_registrar(p)); 06945 } 06946 } 06947 06948 /* walk included and write info ... */ 06949 i = NULL; 06950 while ( (i = ast_walk_context_includes(c, i)) ) { 06951 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 06952 if (exten) { 06953 /* Check all includes for the requested extension */ 06954 if (includecount >= AST_PBX_MAX_STACK) { 06955 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 06956 } else { 06957 int dupe = 0; 06958 int x; 06959 for (x = 0; x < includecount; x++) { 06960 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 06961 dupe++; 06962 break; 06963 } 06964 } 06965 if (!dupe) { 06966 includes[includecount] = ast_get_include_name(i); 06967 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 06968 } else { 06969 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 06970 } 06971 } 06972 } else { 06973 ast_cli(fd, " Include => %-45s [%s]\n", 06974 buf, ast_get_include_registrar(i)); 06975 } 06976 } 06977 06978 /* walk ignore patterns and write info ... */ 06979 ip = NULL; 06980 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06981 const char *ipname = ast_get_ignorepat_name(ip); 06982 char ignorepat[AST_MAX_EXTENSION]; 06983 snprintf(buf, sizeof(buf), "'%s'", ipname); 06984 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06985 if (!exten || ast_extension_match(ignorepat, exten)) { 06986 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 06987 buf, ast_get_ignorepat_registrar(ip)); 06988 } 06989 } 06990 if (!rinclude) { 06991 struct ast_sw *sw = NULL; 06992 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06993 snprintf(buf, sizeof(buf), "'%s/%s'", 06994 ast_get_switch_name(sw), 06995 ast_get_switch_data(sw)); 06996 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 06997 buf, ast_get_switch_registrar(sw)); 06998 } 06999 } 07000 07001 ast_unlock_context(c); 07002 07003 /* if we print something in context, make an empty line */ 07004 if (context_info_printed) 07005 ast_cli(fd, "\n"); 07006 } 07007 ast_unlock_contexts(); 07008 07009 return (dpc->total_exten == old_total_exten) ? -1 : res; 07010 }
| static int statecbs_cmp | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 11211 of file pbx.c.
References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
11212 { 11213 const struct ast_state_cb *state_cb = obj; 11214 ast_state_cb_type change_cb = arg; 11215 11216 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; 11217 }
| static char* substring | ( | const char * | value, | |
| int | offset, | |||
| int | length, | |||
| char * | workspace, | |||
| size_t | workspace_len | |||
| ) | [static] |
takes a substring. It is ok to call with value == workspace.
| value | ||
| offset | < 0 means start from the end of the string and set the beginning to be that many characters back. | |
| length | is the length of the substring, a value less than 0 means to leave that many off the end. | |
| workspace | ||
| workspace_len | Always return a copy in workspace. |
Definition at line 3302 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
03303 { 03304 char *ret = workspace; 03305 int lr; /* length of the input string after the copy */ 03306 03307 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 03308 03309 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 03310 03311 /* Quick check if no need to do anything */ 03312 if (offset == 0 && length >= lr) /* take the whole string */ 03313 return ret; 03314 03315 if (offset < 0) { /* translate negative offset into positive ones */ 03316 offset = lr + offset; 03317 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03318 offset = 0; 03319 } 03320 03321 /* too large offset result in empty string so we know what to return */ 03322 if (offset >= lr) 03323 return ret + lr; /* the final '\0' */ 03324 03325 ret += offset; /* move to the start position */ 03326 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 03327 ret[length] = '\0'; 03328 else if (length < 0) { 03329 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 03330 ret[lr + length - offset] = '\0'; 03331 else 03332 ret[0] = '\0'; 03333 } 03334 03335 return ret; 03336 }
| static int thread_inhibits_escalations | ( | void | ) | [static] |
Indicates whether the current thread inhibits the execution of dangerous functions.
Definition at line 4052 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by is_read_allowed(), and is_write_allowed().
04053 { 04054 int *thread_inhibit_escalations; 04055 04056 thread_inhibit_escalations = ast_threadstorage_get( 04057 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04058 04059 if (thread_inhibit_escalations == NULL) { 04060 ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n"); 04061 /* On error, assume that we are inhibiting */ 04062 return 1; 04063 } 04064 04065 return *thread_inhibit_escalations; 04066 }
| static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1706 of file pbx.c.
References match_char::alt_char, match_char::exten, match_char::next_char, and match_char::x.
Referenced by pbx_find_extension().
01707 { 01708 struct match_char *m3; 01709 struct match_char *m4; 01710 struct ast_exten *e3; 01711 01712 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01713 return node->exten; 01714 } 01715 01716 if (node && node->x[0] == '!' && !node->x[1]) { 01717 return node->exten; 01718 } 01719 01720 if (!node || !node->next_char) { 01721 return NULL; 01722 } 01723 01724 m3 = node->next_char; 01725 01726 if (m3->exten) { 01727 return m3->exten; 01728 } 01729 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01730 if (m4->exten) { 01731 return m4->exten; 01732 } 01733 } 01734 for (m4 = m3; m4; m4 = m4->alt_char) { 01735 e3 = trie_find_next_match(m3); 01736 if (e3) { 01737 return e3; 01738 } 01739 } 01740 01741 return NULL; 01742 }
| static void unload_pbx | ( | void | ) | [static] |
Definition at line 10801 of file pbx.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_event_unsubscribe(), ast_manager_unregister(), ast_taskprocessor_unreference(), ast_unregister_application(), builtins, device_state_sub, exception_function, pbx_cli, and testtime_function.
Referenced by load_pbx().
10802 { 10803 int x; 10804 10805 if (device_state_sub) { 10806 device_state_sub = ast_event_unsubscribe(device_state_sub); 10807 } 10808 if (device_state_tps) { 10809 ast_taskprocessor_unreference(device_state_tps); 10810 device_state_tps = NULL; 10811 } 10812 10813 /* Unregister builtin applications */ 10814 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10815 ast_unregister_application(builtins[x].name); 10816 } 10817 ast_manager_unregister("ShowDialPlan"); 10818 ast_cli_unregister_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10819 ast_custom_function_unregister(&exception_function); 10820 ast_custom_function_unregister(&testtime_function); 10821 ast_data_unregister(NULL); 10822 }
| static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 7624 of file pbx.c.
References ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), and ast_walk_extension_priorities().
Referenced by ast_unregister_application().
07625 { 07626 struct ast_context *context = NULL; 07627 struct ast_exten *eroot = NULL, *e = NULL; 07628 07629 ast_rdlock_contexts(); 07630 while ((context = ast_walk_contexts(context))) { 07631 while ((eroot = ast_walk_context_extensions(context, eroot))) { 07632 while ((e = ast_walk_extension_priorities(eroot, e))) { 07633 if (e->cached_app == app) 07634 e->cached_app = NULL; 07635 } 07636 } 07637 } 07638 ast_unlock_contexts(); 07639 07640 return; 07641 }
| static void update_scoreboard | ( | struct scoreboard * | board, | |
| int | length, | |||
| int | spec, | |||
| struct ast_exten * | exten, | |||
| char | last, | |||
| const char * | callerid, | |||
| int | deleted, | |||
| struct match_char * | node | |||
| ) | [static] |
Definition at line 1610 of file pbx.c.
References ast_log(), ast_exten::exten, scoreboard::exten, scoreboard::last_char, LOG_NOTICE, scoreboard::node, scoreboard::total_length, and scoreboard::total_specificity.
Referenced by new_find_extension().
01611 { 01612 /* if this extension is marked as deleted, then skip this -- if it never shows 01613 on the scoreboard, it will never be found, nor will halt the traversal. */ 01614 if (deleted) 01615 return; 01616 board->total_specificity = spec; 01617 board->total_length = length; 01618 board->exten = exten; 01619 board->last_char = last; 01620 board->node = node; 01621 #ifdef NEED_DEBUG_HERE 01622 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01623 #endif 01624 }
| static void wait_for_hangup | ( | struct ast_channel * | chan, | |
| const void * | data | |||
| ) | [static] |
Definition at line 9805 of file pbx.c.
References ast_frfree, ast_read(), ast_safe_sleep(), ast_strlen_zero(), ast_waitfor(), and f.
Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().
09806 { 09807 int res; 09808 struct ast_frame *f; 09809 double waitsec; 09810 int waittime; 09811 09812 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 09813 waitsec = -1; 09814 if (waitsec > -1) { 09815 waittime = waitsec * 1000.0; 09816 ast_safe_sleep(chan, waittime); 09817 } else do { 09818 res = ast_waitfor(chan, -1); 09819 if (res < 0) 09820 return; 09821 f = ast_read(chan); 09822 if (f) 09823 ast_frfree(f); 09824 } while(f); 09825 }
| static int write_escalates | ( | const struct ast_custom_function * | acf | ) | [static] |
Returns true if given custom function escalates privileges on write.
| acf | Custom function to query. |
Definition at line 3835 of file pbx.c.
References ast_custom_escalating_function::acf, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_escalating_function::write_escalates.
Referenced by is_write_allowed().
03835 { 03836 int res = 0; 03837 struct ast_custom_escalating_function *cur_escalation; 03838 03839 AST_RWLIST_RDLOCK(&escalation_root); 03840 AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) { 03841 if (cur_escalation->acf == acf) { 03842 res = cur_escalation->write_escalates; 03843 break; 03844 } 03845 } 03846 AST_RWLIST_UNLOCK(&escalation_root); 03847 return res; 03848 }
int autofallthrough = 1 [static] |
Definition at line 1176 of file pbx.c.
Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().
struct ast_app_option background_opts[128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} [static] |
Definition at line 807 of file pbx.c.
Referenced by pbx_builtin_background().
struct pbx_builtin builtins[] [static] |
Declaration of builtin applications.
Referenced by load_pbx(), and unload_pbx().
ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock for the ast_context list.
Definition at line 1248 of file pbx.c.
Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().
ast_mutex_t context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition at line 1253 of file pbx.c.
Referenced by ast_merge_contexts_and_delete(), and handle_statechange().
struct ast_context* contexts [static] |
Definition at line 1239 of file pbx.c.
Referenced by __ast_context_destroy(), ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and ast_walk_contexts().
struct ast_hashtab* contexts_table = NULL [static] |
Definition at line 1240 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), find_context(), find_context_locked(), and pbx_shutdown().
int countcalls [static] |
Definition at line 1184 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
const char* const days[] [static] |
Definition at line 8208 of file pbx.c.
Referenced by ast_build_timing().
struct ast_event_sub* device_state_sub [static] |
Subscription for device state change events.
Definition at line 1181 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
{
.name = "EXCEPTION",
.read = acf_exception_read,
}
Definition at line 3604 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_datastore_info exception_store_info [static] |
{
.type = "EXCEPTION",
.destroy = exception_store_free,
}
Definition at line 3536 of file pbx.c.
Referenced by acf_exception_read(), and raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1177 of file pbx.c.
Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } [static] |
Definition at line 823 of file pbx.c.
Referenced by ast_extension_state2().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
Definition at line 1174 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [static] |
Definition at line 1173 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
struct ao2_container* hints [static] |
Definition at line 1268 of file pbx.c.
Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add_destroy(), ast_extension_state_del(), ast_merge_contexts_and_delete(), ast_pbx_init(), ast_remove_hint(), complete_core_show_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), and pbx_shutdown().
struct ast_data_handler hints_data_provider [static] |
{
.version = AST_DATA_HANDLER_VERSION,
.get = hints_data_provider_get
}
int live_dangerously [static] |
Set to true (non-zero) to globally allow all dangerous dialplan functions to run.
Definition at line 828 of file pbx.c.
Referenced by ast_readconfig().
ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 1183 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
const char* const months[] [static] |
Definition at line 8220 of file pbx.c.
Referenced by ast_build_timing().
char* overrideswitch = NULL [static] |
Definition at line 1178 of file pbx.c.
Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().
struct ast_cli_entry pbx_cli[] [static] |
Definition at line 7603 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_data_entry pbx_data_providers[] [static] |
{
AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider),
}
Definition at line 10795 of file pbx.c.
Referenced by load_pbx().
struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} [static] |
Definition at line 9946 of file pbx.c.
Referenced by pbx_builtin_resetcdr().
struct ao2_container* statecbs [static] |
Definition at line 1270 of file pbx.c.
Referenced by ast_extension_state_add_destroy(), ast_extension_state_del(), ast_pbx_init(), handle_statechange(), and pbx_shutdown().
int stateid = 1 [static] |
Definition at line 1259 of file pbx.c.
Referenced by ast_extension_state_add_destroy().
struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } [static] |
Definition at line 822 of file pbx.c.
Referenced by pbx_find_extension().
struct ast_custom_function testtime_function [static] |
{
.name = "TESTTIME",
.write = testtime_write,
}
Definition at line 10037 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_threadstorage thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , } [static] |
Definition at line 828 of file pbx.c.
Referenced by ast_thread_inhibit_escalations(), and thread_inhibits_escalations().
int totalcalls [static] |
Definition at line 1185 of file pbx.c.
Referenced by ast_processed_calls(), increase_call_count(), and timing_read().
struct ast_app_option waitexten_opts[128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} [static] |
Definition at line 815 of file pbx.c.
Referenced by pbx_builtin_waitexten().
1.6.1