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/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"
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_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 | fake_context |
| struct | hints |
| struct | match_char |
| match_char: forms a syntax tree for quick matching of extension patterns More... | |
| struct | pbx_builtin |
| Declaration of builtin applications. More... | |
| struct | pbx_exception |
| struct | scoreboard |
| struct | statecbs |
| 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 | EXT_DATA_SIZE 8192 |
| #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. | |
| 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 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, char *pattern, int is_pattern, int already, int specificity, struct match_char **parent) |
| static int | add_pri (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 int | add_pri_lockopt (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace, int lockhints) |
| add the extension in the priority chain. | |
| static struct match_char * | already_in_tree (struct match_char *current, char *pat) |
| 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 lockconts, int lockhints) |
| Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held. | |
| 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. | |
| static int | ast_add_hint_nolock (struct ast_exten *e) |
| Add hint to hint list, check initial extension state; the hints had better be WRLOCKED already! | |
| 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_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. | |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
| Add watcher for extension states. | |
| int | ast_extension_state_del (int id, ast_state_cb_type callback) |
| 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_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_outgoing_app (const char *type, int 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, int 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 () |
| Read locks the context list. | |
| int | ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, void *), 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_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts () |
| 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 () |
| Write locks the context list. | |
| int | ast_wrlock_contexts_version (void) |
| 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_pattern_tree (struct match_char *pattern_tree) |
| 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 *a, const char *b) |
| the full routine to compare extensions in rules. | |
| static int | ext_cmp1 (const char **p, unsigned char *bitwise) |
| helper functions to sort extensions and 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 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 unsigned | get_range (char *src, int max, 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 | 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) |
| int | load_pbx (void) |
| void | log_match_char_tree (struct match_char *node, char *prefix) |
| static int | lookup_name (const char *s, 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 *, void *) |
| static int | pbx_builtin_background (struct ast_channel *, void *) |
| static int | pbx_builtin_busy (struct ast_channel *, void *) |
| void | pbx_builtin_clear_globals (void) |
| static int | pbx_builtin_congestion (struct ast_channel *, void *) |
| static int | pbx_builtin_execiftime (struct ast_channel *, void *) |
| const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
| Return a pointer to the value of the corresponding channel variable. | |
| static int | pbx_builtin_goto (struct ast_channel *, void *) |
| static int | pbx_builtin_gotoif (struct ast_channel *, void *) |
| static int | pbx_builtin_gotoiftime (struct ast_channel *, void *) |
| static int | pbx_builtin_hangup (struct ast_channel *, void *) |
| static int | pbx_builtin_importvar (struct ast_channel *, void *) |
| static int | pbx_builtin_incomplete (struct ast_channel *, void *) |
| static int | pbx_builtin_noop (struct ast_channel *, void *) |
| static int | pbx_builtin_proceeding (struct ast_channel *, void *) |
| static int | pbx_builtin_progress (struct ast_channel *, void *) |
| void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, without removing any previously set value. | |
| int | pbx_builtin_raise_exception (struct ast_channel *chan, void *vreason) |
| static int | pbx_builtin_resetcdr (struct ast_channel *, void *) |
| static int | pbx_builtin_ringing (struct ast_channel *, void *) |
| static int | pbx_builtin_saycharacters (struct ast_channel *, void *) |
| static int | pbx_builtin_saydigits (struct ast_channel *, void *) |
| static int | pbx_builtin_saynumber (struct ast_channel *, void *) |
| static int | pbx_builtin_sayphonetic (struct ast_channel *, void *) |
| 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 *, void *) |
| int | pbx_builtin_setvar (struct ast_channel *, void *) |
| Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
| void | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
| int | pbx_builtin_setvar_multiple (struct ast_channel *, void *) |
| 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 *, void *) |
| static int | pbx_builtin_waitexten (struct ast_channel *, void *) |
| 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, void *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) |
| 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_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) |
| 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 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 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 struct ast_exten * | trie_find_next_match (struct match_char *node) |
| 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, void *data) |
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_rwlock_t | conlock = PTHREAD_RWLOCK_INITIALIZER |
| static int | conlock_wrlock_version = 0 |
| static struct ast_context * | contexts |
| static struct ast_hashtab * | contexts_table = NULL |
| static int | countcalls |
| static char * | 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 |
| static char | mandescr_show_dialplan [] |
| static ast_mutex_t | maxcalllock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static char * | months [] |
| static char * | overrideswitch = NULL |
| static struct ast_cli_entry | pbx_cli [] |
| static struct ast_app_option | resetcdr_opts [128] = { [ 'w' ] = { .flag = (1 << 1) }, [ 'a' ] = { .flag = (1 << 2) }, [ 'v' ] = { .flag = (1 << 0) }, [ 'e' ] = { .flag = (1 << 10) },} |
| static int | stateid = 1 |
| static struct ast_threadstorage | switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .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 737 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_NOANSWER (1 << 1) |
Definition at line 736 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_PLAYBACK (1 << 3) |
Definition at line 738 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_SKIP (1 << 0) |
Definition at line 735 of file pbx.c.
Referenced by pbx_builtin_background().
| #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 724 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
| #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 729 of file pbx.c.
Referenced by add_user_extension(), ast_add_extension2_lockopt(), build_user_routes(), pbx_builtin_importvar(), pbx_substitute_variables_helper_full(), phoneprov_callback(), pp_each_extension_exec(), and pp_each_user_exec().
| #define WAITEXTEN_DIALTONE (1 << 1) |
Definition at line 748 of file pbx.c.
Referenced by pbx_builtin_waitexten().
| #define WAITEXTEN_MOH (1 << 0) |
Definition at line 747 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 8276 of file pbx.c.
References __ast_internal_context_destroy(), ast_context::alts, ast_context_remove_extension_callerid2(), 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_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ast_context::ignorepats, ast_context::includes, 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().
08277 { 08278 struct ast_context *tmp, *tmpl=NULL; 08279 struct ast_exten *exten_item, *prio_item; 08280 08281 for (tmp = list; tmp; ) { 08282 struct ast_context *next = NULL; /* next starting point */ 08283 /* The following code used to skip forward to the next 08284 context with matching registrar, but this didn't 08285 make sense; individual priorities registrar'd to 08286 the matching registrar could occur in any context! */ 08287 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 08288 if (con) { 08289 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 08290 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 08291 if ( !strcasecmp(tmp->name, con->name) ) { 08292 break; /* found it */ 08293 } 08294 } 08295 } 08296 08297 if (!tmp) /* not found, we are done */ 08298 break; 08299 ast_wrlock_context(tmp); 08300 08301 if (registrar) { 08302 /* then search thru and remove any extens that match registrar. */ 08303 struct ast_hashtab_iter *exten_iter; 08304 struct ast_hashtab_iter *prio_iter; 08305 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 08306 struct ast_include *i, *pi = NULL, *ni = NULL; 08307 struct ast_sw *sw = NULL; 08308 08309 /* remove any ignorepats whose registrar matches */ 08310 for (ip = tmp->ignorepats; ip; ip = ipn) { 08311 ipn = ip->next; 08312 if (!strcmp(ip->registrar, registrar)) { 08313 if (ipl) { 08314 ipl->next = ip->next; 08315 ast_free(ip); 08316 continue; /* don't change ipl */ 08317 } else { 08318 tmp->ignorepats = ip->next; 08319 ast_free(ip); 08320 continue; /* don't change ipl */ 08321 } 08322 } 08323 ipl = ip; 08324 } 08325 /* remove any includes whose registrar matches */ 08326 for (i = tmp->includes; i; i = ni) { 08327 ni = i->next; 08328 if (strcmp(i->registrar, registrar) == 0) { 08329 /* remove from list */ 08330 if (pi) { 08331 pi->next = i->next; 08332 /* free include */ 08333 ast_free(i); 08334 continue; /* don't change pi */ 08335 } else { 08336 tmp->includes = i->next; 08337 /* free include */ 08338 ast_free(i); 08339 continue; /* don't change pi */ 08340 } 08341 } 08342 pi = i; 08343 } 08344 /* remove any switches whose registrar matches */ 08345 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 08346 if (strcmp(sw->registrar,registrar) == 0) { 08347 AST_LIST_REMOVE_CURRENT(list); 08348 ast_free(sw); 08349 } 08350 } 08351 AST_LIST_TRAVERSE_SAFE_END; 08352 08353 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 08354 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 08355 while ((exten_item=ast_hashtab_next(exten_iter))) { 08356 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 08357 while ((prio_item=ast_hashtab_next(prio_iter))) { 08358 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 08359 continue; 08360 } 08361 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 08362 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 08363 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 08364 ast_context_remove_extension_callerid2(tmp, prio_item->exten, prio_item->priority, prio_item->cidmatch, 1, NULL, 1); 08365 } 08366 ast_hashtab_end_traversal(prio_iter); 08367 } 08368 ast_hashtab_end_traversal(exten_iter); 08369 } 08370 08371 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 08372 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 08373 another registrar. It's not empty if there are any extensions */ 08374 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 08375 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 08376 ast_hashtab_remove_this_object(contexttab, tmp); 08377 08378 next = tmp->next; 08379 if (tmpl) 08380 tmpl->next = next; 08381 else 08382 contexts = next; 08383 /* Okay, now we're safe to let it go -- in a sense, we were 08384 ready to let it go as soon as we locked it. */ 08385 ast_unlock_context(tmp); 08386 __ast_internal_context_destroy(tmp); 08387 } else { 08388 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 08389 tmp->refcount, tmp->root); 08390 ast_unlock_context(tmp); 08391 next = tmp->next; 08392 tmpl = tmp; 08393 } 08394 } else if (con) { 08395 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 08396 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 08397 ast_hashtab_remove_this_object(contexttab, tmp); 08398 08399 next = tmp->next; 08400 if (tmpl) 08401 tmpl->next = next; 08402 else 08403 contexts = next; 08404 /* Okay, now we're safe to let it go -- in a sense, we were 08405 ready to let it go as soon as we locked it. */ 08406 ast_unlock_context(tmp); 08407 __ast_internal_context_destroy(tmp); 08408 } 08409 08410 /* if we have a specific match, we are done, otherwise continue */ 08411 tmp = con ? NULL : next; 08412 } 08413 }
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 3289 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by load_pbx().
03290 { 03291 struct ast_custom_function *cur; 03292 char tmps[80]; 03293 03294 if (!acf) { 03295 return -1; 03296 } 03297 03298 acf->mod = mod; 03299 acf->docsrc = AST_STATIC_DOC; 03300 03301 if (acf_retrieve_docs(acf)) { 03302 return -1; 03303 } 03304 03305 AST_RWLIST_WRLOCK(&acf_root); 03306 03307 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03308 if (!strcmp(acf->name, cur->name)) { 03309 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03310 AST_RWLIST_UNLOCK(&acf_root); 03311 return -1; 03312 } 03313 } 03314 03315 /* Store in alphabetical order */ 03316 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03317 if (strcasecmp(acf->name, cur->name) < 0) { 03318 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03319 break; 03320 } 03321 } 03322 AST_RWLIST_TRAVERSE_SAFE_END; 03323 03324 if (!cur) { 03325 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03326 } 03327 03328 AST_RWLIST_UNLOCK(&acf_root); 03329 03330 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03331 03332 return 0; 03333 }
| static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int | async | |||
| ) | [static] |
Definition at line 9551 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, and ast_channel::exten.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
09552 { 09553 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 09554 09555 if (!chan) 09556 return -2; 09557 09558 if (context == NULL) 09559 context = chan->context; 09560 if (exten == NULL) 09561 exten = chan->exten; 09562 09563 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 09564 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 09565 return goto_func(chan, context, exten, priority); 09566 else 09567 return -3; 09568 }
| static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 8229 of file pbx.c.
References ast_context::alts, ast_free, ast_hashtab_destroy(), AST_LIST_REMOVE_HEAD, ast_rwlock_destroy(), destroy_exten(), destroy_pattern_tree(), el, ast_context::ignorepats, ast_context::includes, ast_context::lock, 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().
08230 { 08231 struct ast_include *tmpi; 08232 struct ast_sw *sw; 08233 struct ast_exten *e, *el, *en; 08234 struct ast_ignorepat *ipi; 08235 struct ast_context *tmp = con; 08236 08237 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 08238 struct ast_include *tmpil = tmpi; 08239 tmpi = tmpi->next; 08240 ast_free(tmpil); 08241 } 08242 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 08243 struct ast_ignorepat *ipl = ipi; 08244 ipi = ipi->next; 08245 ast_free(ipl); 08246 } 08247 if (tmp->registrar) 08248 ast_free(tmp->registrar); 08249 08250 /* destroy the hash tabs */ 08251 if (tmp->root_table) { 08252 ast_hashtab_destroy(tmp->root_table, 0); 08253 } 08254 /* and destroy the pattern tree */ 08255 if (tmp->pattern_tree) 08256 destroy_pattern_tree(tmp->pattern_tree); 08257 08258 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 08259 ast_free(sw); 08260 for (e = tmp->root; e;) { 08261 for (en = e->peer; en;) { 08262 el = en; 08263 en = en->peer; 08264 destroy_exten(el); 08265 } 08266 el = e; 08267 e = e->next; 08268 destroy_exten(el); 08269 } 08270 tmp->root = NULL; 08271 ast_rwlock_destroy(&tmp->lock); 08272 ast_free(tmp); 08273 }
| static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) | [static] |
Definition at line 4214 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), 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::cdr, ast_channel::cid, ast_callerid::cid_num, collect_digits(), ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_pbx_args::no_hangup_chan, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_raise_exception(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, ast_pbx::rtimeoutms, set_ext_pri(), status, and ast_channel::whentohangup.
Referenced by ast_pbx_run_args(), and pbx_thread().
04216 { 04217 int found = 0; /* set if we find at least one match */ 04218 int res = 0; 04219 int autoloopflag; 04220 int error = 0; /* set an error conditions */ 04221 04222 /* A little initial setup here */ 04223 if (c->pbx) { 04224 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 04225 /* XXX and now what ? */ 04226 ast_free(c->pbx); 04227 } 04228 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 04229 return -1; 04230 /* Set reasonable defaults */ 04231 c->pbx->rtimeoutms = 10000; 04232 c->pbx->dtimeoutms = 5000; 04233 04234 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 04235 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 04236 04237 /* Start by trying whatever the channel is set to */ 04238 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 04239 /* If not successful fall back to 's' */ 04240 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); 04241 /* XXX the original code used the existing priority in the call to 04242 * ast_exists_extension(), and reset it to 1 afterwards. 04243 * I believe the correct thing is to set it to 1 immediately. 04244 */ 04245 set_ext_pri(c, "s", 1); 04246 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 04247 /* JK02: And finally back to default if everything else failed */ 04248 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); 04249 ast_copy_string(c->context, "default", sizeof(c->context)); 04250 } 04251 } 04252 if (c->cdr) { 04253 /* allow CDR variables that have been collected after channel was created to be visible during call */ 04254 ast_cdr_update(c); 04255 } 04256 for (;;) { 04257 char dst_exten[256]; /* buffer to accumulate digits */ 04258 int pos = 0; /* XXX should check bounds */ 04259 int digit = 0; 04260 int invalid = 0; 04261 int timeout = 0; 04262 04263 /* loop on priorities in this context/exten */ 04264 while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) { 04265 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 04266 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 04267 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04268 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04269 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 04270 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 04271 pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT"); 04272 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04273 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04274 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 04275 } else if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 04276 c->_softhangup = 0; 04277 continue; 04278 } else if (ast_check_hangup(c)) { 04279 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 04280 c->exten, c->priority); 04281 error = 1; 04282 break; 04283 } 04284 c->priority++; 04285 } /* end while - from here on we can use 'break' to go out */ 04286 if (found && res) { 04287 /* Something bad happened, or a hangup has been requested. */ 04288 if (strchr("0123456789ABCDEF*#", res)) { 04289 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 04290 pos = 0; 04291 dst_exten[pos++] = digit = res; 04292 dst_exten[pos] = '\0'; 04293 } else if (res == AST_PBX_INCOMPLETE) { 04294 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 04295 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 04296 04297 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 04298 if (!ast_matchmore_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 04299 invalid = 1; 04300 } else { 04301 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 04302 digit = 1; 04303 pos = strlen(dst_exten); 04304 } 04305 } else { 04306 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04307 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04308 04309 if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 04310 /* if we are already on the 'e' exten, don't jump to it again */ 04311 if (!strcmp(c->exten, "e")) { 04312 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); 04313 error = 1; 04314 } else { 04315 pbx_builtin_raise_exception(c, "ERROR"); 04316 continue; 04317 } 04318 } 04319 04320 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 04321 c->_softhangup = 0; 04322 continue; 04323 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 04324 set_ext_pri(c, "T", 1); 04325 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04326 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04327 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 04328 continue; 04329 } else { 04330 if (c->cdr) 04331 ast_cdr_update(c); 04332 error = 1; 04333 break; 04334 } 04335 } 04336 } 04337 if (error) 04338 break; 04339 04340 /*!\note 04341 * We get here on a failure of some kind: non-existing extension or 04342 * hangup. We have options, here. We can either catch the failure 04343 * and continue, or we can drop out entirely. */ 04344 04345 if (invalid || !ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 04346 /*!\note 04347 * If there is no match at priority 1, it is not a valid extension anymore. 04348 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 04349 * neither exist. 04350 */ 04351 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 04352 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 04353 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 04354 set_ext_pri(c, "i", 1); 04355 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 04356 pbx_builtin_raise_exception(c, "INVALID"); 04357 } else { 04358 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 04359 c->name, c->exten, c->context); 04360 error = 1; /* we know what to do with it */ 04361 break; 04362 } 04363 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 04364 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 04365 c->_softhangup = 0; 04366 } else { /* keypress received, get more digits for a full extension */ 04367 int waittime = 0; 04368 if (digit) 04369 waittime = c->pbx->dtimeoutms; 04370 else if (!autofallthrough) 04371 waittime = c->pbx->rtimeoutms; 04372 if (!waittime) { 04373 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 04374 if (!status) 04375 status = "UNKNOWN"; 04376 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 04377 if (!strcasecmp(status, "CONGESTION")) 04378 res = pbx_builtin_congestion(c, "10"); 04379 else if (!strcasecmp(status, "CHANUNAVAIL")) 04380 res = pbx_builtin_congestion(c, "10"); 04381 else if (!strcasecmp(status, "BUSY")) 04382 res = pbx_builtin_busy(c, "10"); 04383 error = 1; /* XXX disable message */ 04384 break; /* exit from the 'for' loop */ 04385 } 04386 04387 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 04388 break; 04389 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 04390 timeout = 1; 04391 if (!timeout && ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 04392 set_ext_pri(c, dst_exten, 1); 04393 else { 04394 /* No such extension */ 04395 if (!timeout && !ast_strlen_zero(dst_exten)) { 04396 /* An invalid extension */ 04397 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 04398 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 04399 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 04400 set_ext_pri(c, "i", 1); 04401 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 04402 pbx_builtin_raise_exception(c, "INVALID"); 04403 } else { 04404 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 04405 found = 1; /* XXX disable message */ 04406 break; 04407 } 04408 } else { 04409 /* A simple timeout */ 04410 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 04411 ast_verb(3, "Timeout on %s\n", c->name); 04412 set_ext_pri(c, "t", 1); 04413 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 04414 pbx_builtin_raise_exception(c, "RESPONSETIMEOUT"); 04415 } else { 04416 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 04417 found = 1; /* XXX disable message */ 04418 break; 04419 } 04420 } 04421 } 04422 if (c->cdr) { 04423 ast_verb(2, "CDR updated on %s\n",c->name); 04424 ast_cdr_update(c); 04425 } 04426 } 04427 } 04428 04429 if (!found && !error) { 04430 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 04431 } 04432 04433 if (!args || !args->no_hangup_chan) { 04434 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 04435 } 04436 04437 if ((!args || !args->no_hangup_chan) && 04438 !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && 04439 ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 04440 set_ext_pri(c, "h", 1); 04441 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 04442 ast_cdr_end(c->cdr); 04443 } 04444 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) { 04445 c->priority++; 04446 } 04447 if (found && res) { 04448 /* Something bad happened, or a hangup has been requested. */ 04449 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04450 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04451 } 04452 } 04453 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 04454 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 04455 pbx_destroy(c->pbx); 04456 c->pbx = NULL; 04457 04458 if (!args || !args->no_hangup_chan) { 04459 ast_hangup(c); 04460 } 04461 04462 return 0; 04463 }
| static void __init_extensionstate_buf | ( | void | ) | [static] |
| static void __init_switch_data | ( | void | ) | [static] |
| static int _extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 2226 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02227 { 02228 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02229 02230 #ifdef NEED_DEBUG_HERE 02231 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02232 #endif 02233 02234 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 02235 #ifdef NEED_DEBUG_HERE 02236 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02237 #endif 02238 return 1; 02239 } 02240 02241 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02242 int ld = strlen(data), lp = strlen(pattern); 02243 02244 if (lp < ld) { /* pattern too short, cannot match */ 02245 #ifdef NEED_DEBUG_HERE 02246 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02247 #endif 02248 return 0; 02249 } 02250 /* depending on the mode, accept full or partial match or both */ 02251 if (mode == E_MATCH) { 02252 #ifdef NEED_DEBUG_HERE 02253 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 02254 #endif 02255 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 02256 } 02257 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 02258 #ifdef NEED_DEBUG_HERE 02259 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02260 #endif 02261 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02262 } else { 02263 #ifdef NEED_DEBUG_HERE 02264 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02265 #endif 02266 return 0; 02267 } 02268 } 02269 pattern++; /* skip leading _ */ 02270 /* 02271 * XXX below we stop at '/' which is a separator for the CID info. However we should 02272 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02273 */ 02274 while (*data && *pattern && *pattern != '/') { 02275 const char *end; 02276 02277 if (*data == '-') { /* skip '-' in data (just a separator) */ 02278 data++; 02279 continue; 02280 } 02281 switch (toupper(*pattern)) { 02282 case '[': /* a range */ 02283 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 02284 if (end == NULL) { 02285 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02286 return 0; /* unconditional failure */ 02287 } 02288 for (pattern++; pattern != end; pattern++) { 02289 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02290 if (*data >= pattern[0] && *data <= pattern[2]) 02291 break; /* match found */ 02292 else { 02293 pattern += 2; /* skip a total of 3 chars */ 02294 continue; 02295 } 02296 } else if (*data == pattern[0]) 02297 break; /* match found */ 02298 } 02299 if (pattern == end) { 02300 #ifdef NEED_DEBUG_HERE 02301 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 02302 #endif 02303 return 0; 02304 } 02305 pattern = end; /* skip and continue */ 02306 break; 02307 case 'N': 02308 if (*data < '2' || *data > '9') { 02309 #ifdef NEED_DEBUG_HERE 02310 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 02311 #endif 02312 return 0; 02313 } 02314 break; 02315 case 'X': 02316 if (*data < '0' || *data > '9') { 02317 #ifdef NEED_DEBUG_HERE 02318 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 02319 #endif 02320 return 0; 02321 } 02322 break; 02323 case 'Z': 02324 if (*data < '1' || *data > '9') { 02325 #ifdef NEED_DEBUG_HERE 02326 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 02327 #endif 02328 return 0; 02329 } 02330 break; 02331 case '.': /* Must match, even with more digits */ 02332 #ifdef NEED_DEBUG_HERE 02333 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02334 #endif 02335 return 1; 02336 case '!': /* Early match */ 02337 #ifdef NEED_DEBUG_HERE 02338 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02339 #endif 02340 return 2; 02341 case ' ': 02342 case '-': /* Ignore these in patterns */ 02343 data--; /* compensate the final data++ */ 02344 break; 02345 default: 02346 if (*data != *pattern) { 02347 #ifdef NEED_DEBUG_HERE 02348 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02349 #endif 02350 return 0; 02351 } 02352 } 02353 data++; 02354 pattern++; 02355 } 02356 if (*data) /* data longer than pattern, no match */ { 02357 #ifdef NEED_DEBUG_HERE 02358 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02359 #endif 02360 return 0; 02361 } 02362 02363 /* 02364 * match so far, but ran off the end of the data. 02365 * Depending on what is next, determine match or not. 02366 */ 02367 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02368 #ifdef NEED_DEBUG_HERE 02369 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02370 #endif 02371 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02372 } else if (*pattern == '!') { /* early match */ 02373 #ifdef NEED_DEBUG_HERE 02374 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02375 #endif 02376 return 2; 02377 } else { /* partial match */ 02378 #ifdef NEED_DEBUG_HERE 02379 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02380 #endif 02381 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02382 } 02383 }
| static int acf_exception_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 3028 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.
03029 { 03030 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03031 struct pbx_exception *exception = NULL; 03032 if (!ds || !ds->data) 03033 return -1; 03034 exception = ds->data; 03035 if (!strcasecmp(data, "REASON")) 03036 ast_copy_string(buf, exception->reason, buflen); 03037 else if (!strcasecmp(data, "CONTEXT")) 03038 ast_copy_string(buf, exception->context, buflen); 03039 else if (!strncasecmp(data, "EXTEN", 5)) 03040 ast_copy_string(buf, exception->exten, buflen); 03041 else if (!strcasecmp(data, "PRIORITY")) 03042 snprintf(buf, buflen, "%d", exception->priority); 03043 else 03044 return -1; 03045 return 0; 03046 }
| static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3244 of file pbx.c.
References ast_custom_function::arguments, ast_free, 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::desc, ast_custom_function::docsrc, ast_custom_function::name, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, and ast_custom_function::syntax.
Referenced by __ast_custom_function_register().
03245 { 03246 #ifdef AST_XML_DOCS 03247 char *tmpxml; 03248 03249 /* Let's try to find it in the Documentation XML */ 03250 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03251 return 0; 03252 } 03253 03254 if (ast_string_field_init(acf, 128)) { 03255 return -1; 03256 } 03257 03258 /* load synopsis */ 03259 tmpxml = ast_xmldoc_build_synopsis("function", acf->name); 03260 ast_string_field_set(acf, synopsis, tmpxml); 03261 ast_free(tmpxml); 03262 03263 /* load description */ 03264 tmpxml = ast_xmldoc_build_description("function", acf->name); 03265 ast_string_field_set(acf, desc, tmpxml); 03266 ast_free(tmpxml); 03267 03268 /* load syntax */ 03269 tmpxml = ast_xmldoc_build_syntax("function", acf->name); 03270 ast_string_field_set(acf, syntax, tmpxml); 03271 ast_free(tmpxml); 03272 03273 /* load arguments */ 03274 tmpxml = ast_xmldoc_build_arguments("function", acf->name); 03275 ast_string_field_set(acf, arguments, tmpxml); 03276 ast_free(tmpxml); 03277 03278 /* load seealso */ 03279 tmpxml = ast_xmldoc_build_seealso("function", acf->name); 03280 ast_string_field_set(acf, seealso, tmpxml); 03281 ast_free(tmpxml); 03282 03283 acf->docsrc = AST_XML_DOC; 03284 #endif 03285 03286 return 0; 03287 }
| static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
| struct ast_exten * | e1, | |||
| int | findonly | |||
| ) | [static, read] |
Definition at line 1873 of file pbx.c.
References add_pattern_node(), already_in_tree(), ast_copy_string(), ast_log(), buf, ast_exten::cidmatch, compare_char(), match_char::deleted, match_char::exten, ast_exten::exten, LOG_DEBUG, LOG_ERROR, LOG_WARNING, m1, m2, ast_exten::matchcid, match_char::next_char, and ast_context::pattern_tree.
Referenced by add_pri_lockopt(), ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().
01874 { 01875 struct match_char *m1 = NULL, *m2 = NULL, **m0; 01876 int specif; 01877 int already; 01878 int pattern = 0; 01879 char buf[256]; 01880 char extenbuf[512]; 01881 char *s1 = extenbuf; 01882 int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2; 01883 01884 01885 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 01886 01887 if (e1->matchcid && l1 <= sizeof(extenbuf)) { 01888 strcat(extenbuf, "/"); 01889 strcat(extenbuf, e1->cidmatch); 01890 } else if (l1 > sizeof(extenbuf)) { 01891 ast_log(LOG_ERROR, "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch); 01892 return 0; 01893 } 01894 #ifdef NEED_DEBUG 01895 ast_log(LOG_DEBUG, "Adding exten %s%c%s to tree\n", s1, e1->matchcid ? '/' : ' ', e1->matchcid ? e1->cidmatch : ""); 01896 #endif 01897 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 01898 m0 = &con->pattern_tree; 01899 already = 1; 01900 01901 if ( *s1 == '_') { 01902 pattern = 1; 01903 s1++; 01904 } 01905 while( *s1 ) { 01906 if (pattern && *s1 == '[' && *(s1-1) != '\\') { 01907 char *s2 = buf; 01908 buf[0] = 0; 01909 s1++; /* get past the '[' */ 01910 while (*s1 != ']' && *(s1 - 1) != '\\' ) { 01911 if (*s1 == '\\') { 01912 if (*(s1 + 1) == ']') { 01913 *s2++ = ']'; 01914 s1++; s1++; 01915 } else if (*(s1 + 1) == '\\') { 01916 *s2++ = '\\'; 01917 s1++; s1++; 01918 } else if (*(s1 + 1) == '-') { 01919 *s2++ = '-'; 01920 s1++; s1++; 01921 } else if (*(s1 + 1) == '[') { 01922 *s2++ = '['; 01923 s1++; s1++; 01924 } 01925 } else if (*s1 == '-') { /* remember to add some error checking to all this! */ 01926 char s3 = *(s1 - 1); 01927 char s4 = *(s1 + 1); 01928 for (s3++; s3 <= s4; s3++) { 01929 *s2++ = s3; 01930 } 01931 s1++; s1++; 01932 } else if (*s1 == '\0') { 01933 ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf); 01934 break; 01935 } else { 01936 *s2++ = *s1++; 01937 } 01938 } 01939 *s2 = 0; /* null terminate the exploded range */ 01940 /* sort the characters */ 01941 01942 specif = strlen(buf); 01943 qsort(buf, specif, 1, compare_char); 01944 specif <<= 8; 01945 specif += buf[0]; 01946 } else { 01947 01948 if (*s1 == '\\') { 01949 s1++; 01950 buf[0] = *s1; 01951 } else { 01952 if (pattern) { 01953 if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */ 01954 *s1 = 'N'; 01955 else if (*s1 == 'x') 01956 *s1 = 'X'; 01957 else if (*s1 == 'z') 01958 *s1 = 'Z'; 01959 } 01960 buf[0] = *s1; 01961 } 01962 buf[1] = 0; 01963 specif = 1; 01964 } 01965 m2 = 0; 01966 if (already && (m2 = already_in_tree(m1,buf)) && m2->next_char) { 01967 if (!(*(s1 + 1))) { /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten... 01968 * a shorter pattern might win if the longer one doesn't match */ 01969 m2->exten = e1; 01970 m2->deleted = 0; 01971 } 01972 m1 = m2->next_char; /* m1 points to the node to compare against */ 01973 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 01974 } else { /* not already OR not m2 OR nor m2->next_char */ 01975 if (m2) { 01976 if (findonly) { 01977 return m2; 01978 } 01979 m1 = m2; /* while m0 stays the same */ 01980 } else { 01981 if (findonly) { 01982 return m1; 01983 } 01984 m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0); /* m1 is the node just added */ 01985 m0 = &m1->next_char; 01986 } 01987 01988 if (!(*(s1 + 1))) { 01989 m1->deleted = 0; 01990 m1->exten = e1; 01991 } 01992 01993 already = 0; 01994 } 01995 s1++; /* advance to next char */ 01996 } 01997 return m1; 01998 }
| static struct match_char * add_pattern_node | ( | struct ast_context * | con, | |
| struct match_char * | current, | |||
| char * | pattern, | |||
| int | is_pattern, | |||
| int | already, | |||
| int | specificity, | |||
| struct match_char ** | parent | |||
| ) | [static, read] |
Definition at line 1831 of file pbx.c.
References ast_calloc, ast_free, ast_strdup, insert_in_next_chars_alt_char_list(), match_char::is_pattern, match_char::next_char, ast_context::pattern_tree, match_char::specificity, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01832 { 01833 struct match_char *m; 01834 01835 if (!(m = ast_calloc(1, sizeof(*m)))) { 01836 return NULL; 01837 } 01838 01839 if (!(m->x = ast_strdup(pattern))) { 01840 ast_free(m); 01841 return NULL; 01842 } 01843 01844 /* the specificity scores are the same as used in the old 01845 pattern matcher. */ 01846 m->is_pattern = is_pattern; 01847 if (specificity == 1 && is_pattern && pattern[0] == 'N') 01848 m->specificity = 0x0802; 01849 else if (specificity == 1 && is_pattern && pattern[0] == 'Z') 01850 m->specificity = 0x0901; 01851 else if (specificity == 1 && is_pattern && pattern[0] == 'X') 01852 m->specificity = 0x0a00; 01853 else if (specificity == 1 && is_pattern && pattern[0] == '.') 01854 m->specificity = 0x10000; 01855 else if (specificity == 1 && is_pattern && pattern[0] == '!') 01856 m->specificity = 0x20000; 01857 else 01858 m->specificity = specificity; 01859 01860 if (!con->pattern_tree) { 01861 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01862 } else { 01863 if (already) { /* switch to the new regime (traversing vs appending)*/ 01864 insert_in_next_chars_alt_char_list(nextcharptr, m); 01865 } else { 01866 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01867 } 01868 } 01869 01870 return m; 01871 }
| static int add_pri | ( | 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 7440 of file pbx.c.
References add_pri_lockopt().
Referenced by ast_add_extension2_lockopt().
07442 { 07443 return add_pri_lockopt(con, tmp, el, e, replace, 1); 07444 }
| static int add_pri_lockopt | ( | struct ast_context * | con, | |
| struct ast_exten * | tmp, | |||
| struct ast_exten * | el, | |||
| struct ast_exten * | e, | |||
| int | replace, | |||
| int | lockhints | |||
| ) | [static] |
add the extension in the priority chain.
| 0 | on success. | |
| -1 | on failure. |
Definition at line 7451 of file pbx.c.
References add_exten_to_pattern_tree(), ast_add_hint(), ast_add_hint_nolock(), 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 add_pri().
07453 { 07454 struct ast_exten *ep; 07455 struct ast_exten *eh=e; 07456 07457 for (ep = NULL; e ; ep = e, e = e->peer) { 07458 if (e->priority >= tmp->priority) 07459 break; 07460 } 07461 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 07462 ast_hashtab_insert_safe(eh->peer_table, tmp); 07463 07464 if (tmp->label) { 07465 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 07466 } 07467 ep->peer = tmp; 07468 return 0; /* success */ 07469 } 07470 if (e->priority == tmp->priority) { 07471 /* Can't have something exactly the same. Is this a 07472 replacement? If so, replace, otherwise, bonk. */ 07473 if (!replace) { 07474 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 07475 if (tmp->datad) { 07476 tmp->datad(tmp->data); 07477 /* if you free this, null it out */ 07478 tmp->data = NULL; 07479 } 07480 07481 ast_free(tmp); 07482 return -1; 07483 } 07484 /* we are replacing e, so copy the link fields and then update 07485 * whoever pointed to e to point to us 07486 */ 07487 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 07488 tmp->peer = e->peer; /* always meaningful */ 07489 if (ep) { /* We're in the peer list, just insert ourselves */ 07490 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 07491 07492 if (e->label) { 07493 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 07494 } 07495 07496 ast_hashtab_insert_safe(eh->peer_table,tmp); 07497 if (tmp->label) { 07498 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 07499 } 07500 07501 ep->peer = tmp; 07502 } else if (el) { /* We're the first extension. Take over e's functions */ 07503 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 07504 tmp->peer_table = e->peer_table; 07505 tmp->peer_label_table = e->peer_label_table; 07506 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 07507 ast_hashtab_insert_safe(tmp->peer_table,tmp); 07508 if (e->label) { 07509 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 07510 } 07511 if (tmp->label) { 07512 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07513 } 07514 07515 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07516 ast_hashtab_insert_safe(con->root_table, tmp); 07517 el->next = tmp; 07518 /* The pattern trie points to this exten; replace the pointer, 07519 and all will be well */ 07520 if (x) { /* if the trie isn't formed yet, don't sweat this */ 07521 if (x->exten) { /* this test for safety purposes */ 07522 x->exten = tmp; /* replace what would become a bad pointer */ 07523 } else { 07524 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 07525 } 07526 } 07527 } else { /* We're the very first extension. */ 07528 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 07529 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07530 ast_hashtab_insert_safe(con->root_table, tmp); 07531 tmp->peer_table = e->peer_table; 07532 tmp->peer_label_table = e->peer_label_table; 07533 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 07534 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07535 if (e->label) { 07536 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 07537 } 07538 if (tmp->label) { 07539 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07540 } 07541 07542 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07543 ast_hashtab_insert_safe(con->root_table, tmp); 07544 con->root = tmp; 07545 /* The pattern trie points to this exten; replace the pointer, 07546 and all will be well */ 07547 if (x) { /* if the trie isn't formed yet; no problem */ 07548 if (x->exten) { /* this test for safety purposes */ 07549 x->exten = tmp; /* replace what would become a bad pointer */ 07550 } else { 07551 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 07552 } 07553 } 07554 } 07555 if (tmp->priority == PRIORITY_HINT) 07556 ast_change_hint(e,tmp); 07557 /* Destroy the old one */ 07558 if (e->datad) 07559 e->datad(e->data); 07560 ast_free(e); 07561 } else { /* Slip ourselves in just before e */ 07562 tmp->peer = e; 07563 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 07564 if (ep) { /* Easy enough, we're just in the peer list */ 07565 if (tmp->label) { 07566 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 07567 } 07568 ast_hashtab_insert_safe(eh->peer_table, tmp); 07569 ep->peer = tmp; 07570 } else { /* we are the first in some peer list, so link in the ext list */ 07571 tmp->peer_table = e->peer_table; 07572 tmp->peer_label_table = e->peer_label_table; 07573 e->peer_table = 0; 07574 e->peer_label_table = 0; 07575 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07576 if (tmp->label) { 07577 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07578 } 07579 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07580 ast_hashtab_insert_safe(con->root_table, tmp); 07581 if (el) 07582 el->next = tmp; /* in the middle... */ 07583 else 07584 con->root = tmp; /* ... or at the head */ 07585 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 07586 } 07587 /* And immediately return success. */ 07588 if (tmp->priority == PRIORITY_HINT) { 07589 if (lockhints) { 07590 ast_add_hint(tmp); 07591 } else { 07592 ast_add_hint_nolock(tmp); 07593 } 07594 } 07595 } 07596 return 0; 07597 }
| static struct match_char * already_in_tree | ( | struct match_char * | current, | |
| char * | pat | |||
| ) | [static, read] |
Definition at line 1778 of file pbx.c.
References match_char::alt_char, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01779 { 01780 struct match_char *t; 01781 01782 if (!current) { 01783 return 0; 01784 } 01785 01786 for (t = current; t; t = t->alt_char) { 01787 if (!strcmp(pat, t->x)) { /* uh, we may want to sort exploded [] contents to make matching easy */ 01788 return t; 01789 } 01790 } 01791 01792 return 0; 01793 }
| int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 4601 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
04602 { 04603 return countcalls; 04604 }
| int ast_add_extension | ( | const char * | context, | |
| int | replace, | |||
| const char * | extension, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| const char * | application, | |||
| void * | data, | |||
| void(*)(void *) | datad, | |||
| const char * | registrar | |||
| ) |
Add and extension to an extension context.
| context | context to add the extension to | |
| replace | ||
| extension | extension to add | |
| priority | priority level of extension addition | |
| label | extension label | |
| callerid | pattern to match CallerID, or NULL to match any CallerID | |
| application | application to run on the extension with that priority level | |
| data | data to pass to the application | |
| datad | ||
| registrar | who registered the extension |
| 0 | success | |
| -1 | failure |
Definition at line 7305 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state_add(), handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().
07308 { 07309 int ret = -1; 07310 struct ast_context *c = find_context_locked(context); 07311 07312 if (c) { 07313 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 07314 application, data, datad, registrar); 07315 ast_unlock_contexts(); 07316 } 07317 07318 return ret; 07319 }
| int ast_add_extension2 | ( | struct ast_context * | con, | |
| int | replace, | |||
| const char * | extension, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| const char * | application, | |||
| void * | data, | |||
| void(*)(void *) | datad, | |||
| const char * | registrar | |||
| ) |
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 7624 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), build_parkinglot(), context_merge(), load_config(), load_module(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
07628 { 07629 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 07630 }
| 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 | lockconts, | |||
| int | lockhints | |||
| ) | [static] |
Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held.
Definition at line 7637 of file pbx.c.
References add_exten_to_pattern_tree(), add_pri(), ast_exten::app, ast_add_hint(), ast_add_hint_nolock(), ast_calloc, ast_copy_string(), ast_debug, 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().
07641 { 07642 /* 07643 * Sort extensions (or patterns) according to the rules indicated above. 07644 * These are implemented by the function ext_cmp()). 07645 * All priorities for the same ext/pattern/cid are kept in a list, 07646 * using the 'peer' field as a link field.. 07647 */ 07648 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 07649 int res; 07650 int length; 07651 char *p; 07652 char expand_buf[VAR_BUF_SIZE]; 07653 struct ast_exten dummy_exten = {0}; 07654 char dummy_name[1024]; 07655 07656 if (ast_strlen_zero(extension)) { 07657 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", 07658 con->name); 07659 return -1; 07660 } 07661 07662 /* If we are adding a hint evalulate in variables and global variables */ 07663 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 07664 struct ast_channel c = {0, }; 07665 07666 ast_copy_string(c.exten, extension, sizeof(c.exten)); 07667 ast_copy_string(c.context, con->name, sizeof(c.context)); 07668 pbx_substitute_variables_helper(&c, application, expand_buf, sizeof(expand_buf)); 07669 application = expand_buf; 07670 } 07671 07672 length = sizeof(struct ast_exten); 07673 length += strlen(extension) + 1; 07674 length += strlen(application) + 1; 07675 if (label) 07676 length += strlen(label) + 1; 07677 if (callerid) 07678 length += strlen(callerid) + 1; 07679 else 07680 length ++; /* just the '\0' */ 07681 07682 /* Be optimistic: Build the extension structure first */ 07683 if (!(tmp = ast_calloc(1, length))) 07684 return -1; 07685 07686 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 07687 label = 0; 07688 07689 /* use p as dst in assignments, as the fields are const char * */ 07690 p = tmp->stuff; 07691 if (label) { 07692 tmp->label = p; 07693 strcpy(p, label); 07694 p += strlen(label) + 1; 07695 } 07696 tmp->exten = p; 07697 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 07698 tmp->priority = priority; 07699 tmp->cidmatch = p; /* but use p for assignments below */ 07700 07701 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 07702 if (callerid) { 07703 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 07704 tmp->matchcid = 1; 07705 } else { 07706 *p++ = '\0'; 07707 tmp->matchcid = 0; 07708 } 07709 tmp->app = p; 07710 strcpy(p, application); 07711 tmp->parent = con; 07712 tmp->data = data; 07713 tmp->datad = datad; 07714 tmp->registrar = registrar; 07715 07716 if (lockconts) { 07717 ast_wrlock_context(con); 07718 } 07719 07720 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 07721 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 07722 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 07723 dummy_exten.exten = dummy_name; 07724 dummy_exten.matchcid = 0; 07725 dummy_exten.cidmatch = 0; 07726 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 07727 if (!tmp2) { 07728 /* hmmm, not in the trie; */ 07729 add_exten_to_pattern_tree(con, tmp, 0); 07730 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 07731 } 07732 } 07733 res = 0; /* some compilers will think it is uninitialized otherwise */ 07734 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 07735 res = ext_cmp(e->exten, tmp->exten); 07736 if (res == 0) { /* extension match, now look at cidmatch */ 07737 if (!e->matchcid && !tmp->matchcid) 07738 res = 0; 07739 else if (tmp->matchcid && !e->matchcid) 07740 res = 1; 07741 else if (e->matchcid && !tmp->matchcid) 07742 res = -1; 07743 else 07744 res = ext_cmp(e->cidmatch, tmp->cidmatch); 07745 } 07746 if (res >= 0) 07747 break; 07748 } 07749 if (e && res == 0) { /* exact match, insert in the pri chain */ 07750 res = add_pri(con, tmp, el, e, replace); 07751 if (lockconts) { 07752 ast_unlock_context(con); 07753 } 07754 if (res < 0) { 07755 errno = EEXIST; /* XXX do we care ? */ 07756 return 0; /* XXX should we return -1 maybe ? */ 07757 } 07758 } else { 07759 /* 07760 * not an exact match, this is the first entry with this pattern, 07761 * so insert in the main list right before 'e' (if any) 07762 */ 07763 tmp->next = e; 07764 if (el) { /* there is another exten already in this context */ 07765 el->next = tmp; 07766 tmp->peer_table = ast_hashtab_create(13, 07767 hashtab_compare_exten_numbers, 07768 ast_hashtab_resize_java, 07769 ast_hashtab_newsize_java, 07770 hashtab_hash_priority, 07771 0); 07772 tmp->peer_label_table = ast_hashtab_create(7, 07773 hashtab_compare_exten_labels, 07774 ast_hashtab_resize_java, 07775 ast_hashtab_newsize_java, 07776 hashtab_hash_labels, 07777 0); 07778 if (label) { 07779 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07780 } 07781 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07782 } else { /* this is the first exten in this context */ 07783 if (!con->root_table) 07784 con->root_table = ast_hashtab_create(27, 07785 hashtab_compare_extens, 07786 ast_hashtab_resize_java, 07787 ast_hashtab_newsize_java, 07788 hashtab_hash_extens, 07789 0); 07790 con->root = tmp; 07791 con->root->peer_table = ast_hashtab_create(13, 07792 hashtab_compare_exten_numbers, 07793 ast_hashtab_resize_java, 07794 ast_hashtab_newsize_java, 07795 hashtab_hash_priority, 07796 0); 07797 con->root->peer_label_table = ast_hashtab_create(7, 07798 hashtab_compare_exten_labels, 07799 ast_hashtab_resize_java, 07800 ast_hashtab_newsize_java, 07801 hashtab_hash_labels, 07802 0); 07803 if (label) { 07804 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 07805 } 07806 ast_hashtab_insert_safe(con->root->peer_table, tmp); 07807 07808 } 07809 ast_hashtab_insert_safe(con->root_table, tmp); 07810 if (lockconts) { 07811 ast_unlock_context(con); 07812 } 07813 if (tmp->priority == PRIORITY_HINT) { 07814 if (lockhints) { 07815 ast_add_hint(tmp); 07816 } else { 07817 ast_add_hint_nolock(tmp); 07818 } 07819 } 07820 } 07821 if (option_debug) { 07822 if (tmp->matchcid) { 07823 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 07824 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 07825 } else { 07826 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 07827 tmp->exten, tmp->priority, con->name, con); 07828 } 07829 } 07830 07831 if (tmp->matchcid) { 07832 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 07833 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 07834 } else { 07835 ast_verb(3, "Added extension '%s' priority %d to %s (%p)\n", 07836 tmp->exten, tmp->priority, con->name, con); 07837 } 07838 07839 return 0; 07840 }
| 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 7286 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
07289 { 07290 int ret = -1; 07291 struct ast_context *c = find_context(context); 07292 07293 if (c) { 07294 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 07295 application, data, datad, registrar, 0, 0); 07296 } 07297 07298 return ret; 07299 }
| static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 4060 of file pbx.c.
References ast_add_hint_nolock(), AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by add_pri_lockopt(), and ast_add_extension2_lockopt().
04061 { 04062 int ret; 04063 04064 AST_RWLIST_WRLOCK(&hints); 04065 ret = ast_add_hint_nolock(e); 04066 AST_RWLIST_UNLOCK(&hints); 04067 04068 return ret; 04069 }
| static int ast_add_hint_nolock | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state; the hints had better be WRLOCKED already!
Definition at line 4031 of file pbx.c.
References ast_calloc, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, ast_hint::exten, and ast_hint::laststate.
Referenced by add_pri_lockopt(), ast_add_extension2_lockopt(), and ast_add_hint().
04032 { 04033 struct ast_hint *hint; 04034 04035 if (!e) 04036 return -1; 04037 04038 /* Search if hint exists, do nothing */ 04039 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04040 if (hint->exten == e) { 04041 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 04042 return -1; 04043 } 04044 } 04045 04046 ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 04047 04048 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 04049 return -1; 04050 } 04051 /* Initialize and insert new item at the top */ 04052 hint->exten = e; 04053 hint->laststate = ast_extension_state2(e); 04054 AST_RWLIST_INSERT_HEAD(&hints, hint, list); 04055 04056 return 0; 04057 }
| int ast_async_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Set the channel to next execute the specified dialplan location.
Definition at line 7344 of file pbx.c.
References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmfup(), handle_request_bye(), handle_request_refer(), pbx_parseable_goto(), process_ast_dsp(), sip_read(), and socket_process().
07345 { 07346 int res = 0; 07347 07348 ast_channel_lock(chan); 07349 07350 if (chan->pbx) { /* This channel is currently in the PBX */ 07351 ast_explicit_goto(chan, context, exten, priority + 1); 07352 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 07353 } else { 07354 /* In order to do it when the channel doesn't really exist within 07355 the PBX, we have to make a new channel, masquerade, and start the PBX 07356 at the new location */ 07357 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 07358 if (!tmpchan) { 07359 res = -1; 07360 } else { 07361 if (chan->cdr) { 07362 ast_cdr_discard(tmpchan->cdr); 07363 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 07364 } 07365 /* Make formats okay */ 07366 tmpchan->readformat = chan->readformat; 07367 tmpchan->writeformat = chan->writeformat; 07368 /* Setup proper location */ 07369 ast_explicit_goto(tmpchan, 07370 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 07371 07372 /* Masquerade into temp channel */ 07373 if (ast_channel_masquerade(tmpchan, chan)) { 07374 /* Failed to set up the masquerade. It's probably chan_local 07375 * in the middle of optimizing itself out. Sad. :( */ 07376 ast_hangup(tmpchan); 07377 tmpchan = NULL; 07378 res = -1; 07379 } else { 07380 /* Grab the locks and get going */ 07381 ast_channel_lock(tmpchan); 07382 ast_do_masquerade(tmpchan); 07383 ast_channel_unlock(tmpchan); 07384 /* Start the PBX going on our stolen channel */ 07385 if (ast_pbx_start(tmpchan)) { 07386 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 07387 ast_hangup(tmpchan); 07388 res = -1; 07389 } 07390 } 07391 } 07392 } 07393 ast_channel_unlock(chan); 07394 return res; 07395 }
| int ast_async_goto_by_name | ( | const char * | channame, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Set the channel to next execute the specified dialplan location.
Definition at line 7397 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
07398 { 07399 struct ast_channel *chan; 07400 int res = -1; 07401 07402 chan = ast_get_channel_by_name_locked(channame); 07403 if (chan) { 07404 res = ast_async_goto(chan, context, exten, priority); 07405 ast_channel_unlock(chan); 07406 } 07407 return res; 07408 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 9575 of file pbx.c.
References __ast_goto_if_exists().
09576 { 09577 return __ast_goto_if_exists(chan, context, exten, priority, 1); 09578 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9638 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
09639 { 09640 return pbx_parseable_goto(chan, goto_string, 1); 09641 }
| int ast_build_timing | ( | struct ast_timing * | i, | |
| const char * | info | |||
| ) |
Construct a timing bitmap, for use in time-based conditionals.
| i | Pointer to an ast_timing structure. | |
| info | Standard string containing a timerange, weekday range, monthday range, and month range, as well as an optional timezone. |
| Returns | 1 on success or 0 on failure. |
Definition at line 6939 of file pbx.c.
References ast_strdup, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
06940 { 06941 char *info_save, *info; 06942 int j, num_fields, last_sep = -1; 06943 06944 /* Check for empty just in case */ 06945 if (ast_strlen_zero(info_in)) { 06946 return 0; 06947 } 06948 06949 /* make a copy just in case we were passed a static string */ 06950 info_save = info = ast_strdupa(info_in); 06951 06952 /* count the number of fields in the timespec */ 06953 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 06954 if (info[j] == ',') { 06955 last_sep = j; 06956 num_fields++; 06957 } 06958 } 06959 06960 /* save the timezone, if it is specified */ 06961 if (num_fields == 5) { 06962 i->timezone = ast_strdup(info + last_sep + 1); 06963 } else { 06964 i->timezone = NULL; 06965 } 06966 06967 /* Assume everything except time */ 06968 i->monthmask = 0xfff; /* 12 bits */ 06969 i->daymask = 0x7fffffffU; /* 31 bits */ 06970 i->dowmask = 0x7f; /* 7 bits */ 06971 /* on each call, use strsep() to move info to the next argument */ 06972 get_timerange(i, strsep(&info, "|,")); 06973 if (info) 06974 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 06975 if (info) 06976 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 06977 if (info) 06978 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 06979 return 1; 06980 }
| int ast_canmatch_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid | |||
| ) |
Looks for a valid matching extension.
| c | not really important | |
| context | context to serach within | |
| exten | extension to check | |
| priority | priority of extension path | |
| callerid | callerid of extension being searched for |
Definition at line 4158 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), pri_dchannel(), skinny_ss(), ss_thread(), and valid_exit().
04159 { 04160 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04161 }
Change hint for an extension.
Definition at line 4072 of file pbx.c.
References AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_hint::exten.
Referenced by add_pri_lockopt().
04073 { 04074 struct ast_hint *hint; 04075 int res = -1; 04076 04077 AST_RWLIST_WRLOCK(&hints); 04078 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04079 if (hint->exten == oe) { 04080 hint->exten = ne; 04081 res = 0; 04082 break; 04083 } 04084 } 04085 AST_RWLIST_UNLOCK(&hints); 04086 04087 return res; 04088 }
| int ast_check_timing | ( | const struct ast_timing * | i | ) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
| i | Pointer to an ast_timing structure. |
| Returns | 1, if the time matches or 0, if the current time falls outside of the specified range. |
Definition at line 6982 of file pbx.c.
References ast_localtime(), ast_log(), ast_tvnow(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
06983 { 06984 struct ast_tm tm; 06985 struct timeval now = ast_tvnow(); 06986 06987 ast_localtime(&now, &tm, i->timezone); 06988 06989 /* If it's not the right month, return */ 06990 if (!(i->monthmask & (1 << tm.tm_mon))) 06991 return 0; 06992 06993 /* If it's not that time of the month.... */ 06994 /* Warning, tm_mday has range 1..31! */ 06995 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 06996 return 0; 06997 06998 /* If it's not the right day of the week */ 06999 if (!(i->dowmask & (1 << tm.tm_wday))) 07000 return 0; 07001 07002 /* Sanity check the hour just to be safe */ 07003 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07004 ast_log(LOG_WARNING, "Insane time...\n"); 07005 return 0; 07006 } 07007 07008 /* Now the tough part, we calculate if it fits 07009 in the right time based on min/hour */ 07010 if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min)))) 07011 return 0; 07012 07013 /* If we got this far, then we're good */ 07014 return 1; 07015 }
| int ast_context_add_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Add an ignorepat.
| context | which context to add the ignorpattern to | |
| ignorepat | ignorepattern to set up for the extension | |
| registrar | registrar of the ignore pattern |
Adds an ignore pattern to a particular context.
| 0 | on success | |
| -1 | on failure |
Definition at line 7217 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
07218 { 07219 int ret = -1; 07220 struct ast_context *c = find_context_locked(context); 07221 07222 if (c) { 07223 ret = ast_context_add_ignorepat2(c, value, registrar); 07224 ast_unlock_contexts(); 07225 } 07226 return ret; 07227 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | value, | |||
| const char * | registrar | |||
| ) |
Definition at line 7229 of file pbx.c.
References ast_calloc, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
07230 { 07231 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 07232 int length; 07233 char *pattern; 07234 length = sizeof(struct ast_ignorepat); 07235 length += strlen(value) + 1; 07236 if (!(ignorepat = ast_calloc(1, length))) 07237 return -1; 07238 /* The cast to char * is because we need to write the initial value. 07239 * The field is not supposed to be modified otherwise. Also, gcc 4.2 07240 * sees the cast as dereferencing a type-punned pointer and warns about 07241 * it. This is the workaround (we're telling gcc, yes, that's really 07242 * what we wanted to do). 07243 */ 07244 pattern = (char *) ignorepat->pattern; 07245 strcpy(pattern, value); 07246 ignorepat->next = NULL; 07247 ignorepat->registrar = registrar; 07248 ast_wrlock_context(con); 07249 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 07250 ignorepatl = ignorepatc; 07251 if (!strcasecmp(ignorepatc->pattern, value)) { 07252 /* Already there */ 07253 ast_unlock_context(con); 07254 errno = EEXIST; 07255 return -1; 07256 } 07257 } 07258 if (ignorepatl) 07259 ignorepatl->next = ignorepat; 07260 else 07261 con->ignorepats = ignorepat; 07262 ast_unlock_context(con); 07263 return 0; 07264 07265 }
| int ast_context_add_include | ( | const char * | context, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| context | context to add include to | |
| include | new include to add | |
| registrar | who's registering it |
Adds an include taking a char * string as the context parameter
| 0 | on success | |
| -1 | on error |
Definition at line 6768 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
06769 { 06770 int ret = -1; 06771 struct ast_context *c = find_context_locked(context); 06772 06773 if (c) { 06774 ret = ast_context_add_include2(c, include, registrar); 06775 ast_unlock_contexts(); 06776 } 06777 return ret; 06778 }
| int ast_context_add_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Add a context include.
| con | context to add the include to | |
| include | include to add | |
| registrar | who registered the context |
Adds an include taking a struct ast_context as the first parameter
| 0 | on success | |
| -1 | on failure |
Definition at line 7032 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.
Referenced by ast_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
07034 { 07035 struct ast_include *new_include; 07036 char *c; 07037 struct ast_include *i, *il = NULL; /* include, include_last */ 07038 int length; 07039 char *p; 07040 07041 length = sizeof(struct ast_include); 07042 length += 2 * (strlen(value) + 1); 07043 07044 /* allocate new include structure ... */ 07045 if (!(new_include = ast_calloc(1, length))) 07046 return -1; 07047 /* Fill in this structure. Use 'p' for assignments, as the fields 07048 * in the structure are 'const char *' 07049 */ 07050 p = new_include->stuff; 07051 new_include->name = p; 07052 strcpy(p, value); 07053 p += strlen(value) + 1; 07054 new_include->rname = p; 07055 strcpy(p, value); 07056 /* Strip off timing info, and process if it is there */ 07057 if ( (c = strchr(p, ',')) ) { 07058 *c++ = '\0'; 07059 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07060 } 07061 new_include->next = NULL; 07062 new_include->registrar = registrar; 07063 07064 ast_wrlock_context(con); 07065 07066 /* ... go to last include and check if context is already included too... */ 07067 for (i = con->includes; i; i = i->next) { 07068 if (!strcasecmp(i->name, new_include->name)) { 07069 ast_destroy_timing(&(new_include->timing)); 07070 ast_free(new_include); 07071 ast_unlock_context(con); 07072 errno = EEXIST; 07073 return -1; 07074 } 07075 il = i; 07076 } 07077 07078 /* ... include new context into context list, unlock, return */ 07079 if (il) 07080 il->next = new_include; 07081 else 07082 con->includes = new_include; 07083 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07084 07085 ast_unlock_context(con); 07086 07087 return 0; 07088 }
| int ast_context_add_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| int | eval, | |||
| const char * | registrar | |||
| ) |
Add a switch.
| context | context to which to add the switch | |
| sw | switch to add | |
| data | data to pass to switch | |
| eval | whether to evaluate variables when running switch | |
| registrar | whoever registered the switch |
This function registers a switch with the asterisk switch architecture
| 0 | on success | |
| -1 | on failure |
Definition at line 7095 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07096 { 07097 int ret = -1; 07098 struct ast_context *c = find_context_locked(context); 07099 07100 if (c) { /* found, add switch to this context */ 07101 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07102 ast_unlock_contexts(); 07103 } 07104 return ret; 07105 }
| int ast_context_add_switch2 | ( | struct ast_context * | con, | |
| const char * | sw, | |||
| const char * | data, | |||
| int | eval, | |||
| const char * | registrar | |||
| ) |
Adds a switch (first param is a ast_context).
Definition at line 7114 of file pbx.c.
References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_compile_ael2(), ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
07116 { 07117 struct ast_sw *new_sw; 07118 struct ast_sw *i; 07119 int length; 07120 char *p; 07121 07122 length = sizeof(struct ast_sw); 07123 length += strlen(value) + 1; 07124 if (data) 07125 length += strlen(data); 07126 length++; 07127 07128 /* allocate new sw structure ... */ 07129 if (!(new_sw = ast_calloc(1, length))) 07130 return -1; 07131 /* ... fill in this structure ... */ 07132 p = new_sw->stuff; 07133 new_sw->name = p; 07134 strcpy(new_sw->name, value); 07135 p += strlen(value) + 1; 07136 new_sw->data = p; 07137 if (data) { 07138 strcpy(new_sw->data, data); 07139 p += strlen(data) + 1; 07140 } else { 07141 strcpy(new_sw->data, ""); 07142 p++; 07143 } 07144 new_sw->eval = eval; 07145 new_sw->registrar = registrar; 07146 07147 /* ... try to lock this context ... */ 07148 ast_wrlock_context(con); 07149 07150 /* ... go to last sw and check if context is already swd too... */ 07151 AST_LIST_TRAVERSE(&con->alts, i, list) { 07152 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07153 ast_free(new_sw); 07154 ast_unlock_context(con); 07155 errno = EEXIST; 07156 return -1; 07157 } 07158 } 07159 07160 /* ... sw new context into context list, unlock, return */ 07161 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07162 07163 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07164 07165 ast_unlock_context(con); 07166 07167 return 0; 07168 }
| void ast_context_destroy | ( | struct ast_context * | con, | |
| const char * | registrar | |||
| ) |
Destroy a context (matches the specified context (or ANY context if NULL).
| con | context to destroy | |
| registrar | who registered it |
You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.
Definition at line 8415 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), sla_destroy(), and unload_module().
08416 { 08417 ast_wrlock_contexts(); 08418 __ast_context_destroy(contexts, contexts_table, con,registrar); 08419 ast_unlock_contexts(); 08420 }
| struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
| name | name of the context to find |
Will search for the context with the given name.
Definition at line 2430 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), load_config(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
02431 { 02432 struct ast_context *tmp = NULL; 02433 struct fake_context item; 02434 02435 ast_copy_string(item.name, name, sizeof(item.name)); 02436 02437 ast_rdlock_contexts(); 02438 if( contexts_table ) { 02439 tmp = ast_hashtab_lookup(contexts_table,&item); 02440 } else { 02441 while ( (tmp = ast_walk_contexts(tmp)) ) { 02442 if (!name || !strcasecmp(name, tmp->name)) { 02443 break; 02444 } 02445 } 02446 } 02447 ast_unlock_contexts(); 02448 return tmp; 02449 }
| struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| const char * | name, | |||
| const char * | registrar | |||
| ) | [read] |
Register a new context or find an existing one.
| extcontexts | pointer to the ast_context structure pointer | |
| exttable | pointer to the hashtable that contains all the elements in extcontexts | |
| name | name of the new context | |
| registrar | registrar of the context |
This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.
Definition at line 6424 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init(), ast_rdlock_contexts(), ast_rwlock_init(), ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), build_parkinglot(), config_parse_variables(), context_merge(), load_config(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
06425 { 06426 struct ast_context *tmp, **local_contexts; 06427 struct fake_context search; 06428 int length = sizeof(struct ast_context) + strlen(name) + 1; 06429 06430 if (!contexts_table) { 06431 contexts_table = ast_hashtab_create(17, 06432 ast_hashtab_compare_contexts, 06433 ast_hashtab_resize_java, 06434 ast_hashtab_newsize_java, 06435 ast_hashtab_hash_contexts, 06436 0); 06437 } 06438 06439 ast_copy_string(search.name, name, sizeof(search.name)); 06440 if (!extcontexts) { 06441 ast_rdlock_contexts(); 06442 local_contexts = &contexts; 06443 tmp = ast_hashtab_lookup(contexts_table, &search); 06444 ast_unlock_contexts(); 06445 if (tmp) { 06446 tmp->refcount++; 06447 return tmp; 06448 } 06449 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 06450 local_contexts = extcontexts; 06451 tmp = ast_hashtab_lookup(exttable, &search); 06452 if (tmp) { 06453 tmp->refcount++; 06454 return tmp; 06455 } 06456 } 06457 06458 if ((tmp = ast_calloc(1, length))) { 06459 ast_rwlock_init(&tmp->lock); 06460 ast_mutex_init(&tmp->macrolock); 06461 strcpy(tmp->name, name); 06462 tmp->root = NULL; 06463 tmp->root_table = NULL; 06464 tmp->registrar = ast_strdup(registrar); 06465 tmp->includes = NULL; 06466 tmp->ignorepats = NULL; 06467 tmp->refcount = 1; 06468 } else { 06469 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 06470 return NULL; 06471 } 06472 06473 if (!extcontexts) { 06474 ast_wrlock_contexts(); 06475 tmp->next = *local_contexts; 06476 *local_contexts = tmp; 06477 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 06478 ast_unlock_contexts(); 06479 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06480 ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06481 } else { 06482 tmp->next = *local_contexts; 06483 if (exttable) 06484 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 06485 06486 *local_contexts = tmp; 06487 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06488 ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06489 } 06490 return tmp; 06491 }
| int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 4988 of file pbx.c.
References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
04989 { 04990 struct ast_context *c = NULL; 04991 int ret = -1; 04992 struct fake_context item; 04993 04994 ast_rdlock_contexts(); 04995 04996 ast_copy_string(item.name, context, sizeof(item.name)); 04997 04998 c = ast_hashtab_lookup(contexts_table,&item); 04999 if (c) 05000 ret = 0; 05001 05002 05003 #ifdef NOTNOW 05004 05005 while ((c = ast_walk_contexts(c))) { 05006 if (!strcmp(ast_get_context_name(c), context)) { 05007 ret = 0; 05008 break; 05009 } 05010 } 05011 05012 #endif 05013 ast_unlock_contexts(); 05014 05015 /* if we found context, lock macrolock */ 05016 if (ret == 0) { 05017 ret = ast_mutex_lock(&c->macrolock); 05018 } 05019 05020 return ret; 05021 }
| int ast_context_remove_extension | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar | |||
| ) |
Simply remove extension from context.
| context | context to remove extension from | |
| extension | which extension to remove | |
| priority | priority of extension to remove (0 to remove all) | |
| callerid | NULL to remove all; non-NULL to match a single record per priority | |
| matchcid | non-zero to match callerid element (if non-NULL); 0 to match default case | |
| registrar | registrar of the extension |
This function removes an extension from a given context.
| 0 | on success | |
| -1 | on failure |
Definition at line 4796 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
04797 { 04798 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 04799 }
| int ast_context_remove_extension2 | ( | struct ast_context * | con, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar, | |||
| int | already_locked | |||
| ) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
Definition at line 4823 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by load_config(), manage_parkinglot(), park_exec_full(), and unload_module().
04824 { 04825 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 04826 }
| int ast_context_remove_extension_callerid | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | callerid, | |||
| int | matchcallerid, | |||
| const char * | registrar | |||
| ) |
Definition at line 4801 of file pbx.c.
References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_context_remove_extension(), and handle_cli_dialplan_remove_extension().
04802 { 04803 int ret = -1; /* default error return */ 04804 struct ast_context *c = find_context_locked(context); 04805 04806 if (c) { /* ... remove extension ... */ 04807 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 04808 ast_unlock_contexts(); 04809 } 04810 return ret; 04811 }
| int ast_context_remove_extension_callerid2 | ( | struct ast_context * | con, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | callerid, | |||
| int | matchcallerid, | |||
| const char * | registrar, | |||
| int | already_locked | |||
| ) |
Definition at line 4828 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
04829 { 04830 struct ast_exten *exten, *prev_exten = NULL; 04831 struct ast_exten *peer; 04832 struct ast_exten ex, *exten2, *exten3; 04833 char dummy_name[1024]; 04834 struct ast_exten *previous_peer = NULL; 04835 struct ast_exten *next_peer = NULL; 04836 int found = 0; 04837 04838 if (!already_locked) 04839 ast_wrlock_context(con); 04840 04841 /* Handle this is in the new world */ 04842 04843 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 04844 * peers, not just those matching the callerid. */ 04845 #ifdef NEED_DEBUG 04846 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 04847 #endif 04848 #ifdef CONTEXT_DEBUG 04849 check_contexts(__FILE__, __LINE__); 04850 #endif 04851 /* find this particular extension */ 04852 ex.exten = dummy_name; 04853 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 04854 ex.cidmatch = callerid; 04855 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 04856 exten = ast_hashtab_lookup(con->root_table, &ex); 04857 if (exten) { 04858 if (priority == 0) { 04859 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04860 if (!exten2) 04861 ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name); 04862 if (con->pattern_tree) { 04863 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04864 04865 if (x->exten) { /* this test for safety purposes */ 04866 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04867 x->exten = 0; /* get rid of what will become a bad pointer */ 04868 } else { 04869 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 04870 } 04871 } 04872 } else { 04873 ex.priority = priority; 04874 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 04875 if (exten2) { 04876 04877 if (exten2->label) { /* if this exten has a label, remove that, too */ 04878 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 04879 if (!exten3) 04880 ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten); 04881 } 04882 04883 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 04884 if (!exten3) 04885 ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten); 04886 if (exten2 == exten && exten2->peer) { 04887 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04888 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 04889 } 04890 if (ast_hashtab_size(exten->peer_table) == 0) { 04891 /* well, if the last priority of an exten is to be removed, 04892 then, the extension is removed, too! */ 04893 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 04894 if (!exten3) 04895 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 04896 if (con->pattern_tree) { 04897 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04898 if (x->exten) { /* this test for safety purposes */ 04899 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04900 x->exten = 0; /* get rid of what will become a bad pointer */ 04901 } 04902 } 04903 } 04904 } else { 04905 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 04906 priority, exten->exten, con->name); 04907 } 04908 } 04909 } else { 04910 /* hmmm? this exten is not in this pattern tree? */ 04911 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 04912 extension, con->name); 04913 } 04914 #ifdef NEED_DEBUG 04915 if (con->pattern_tree) { 04916 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 04917 log_match_char_tree(con->pattern_tree, " "); 04918 } 04919 #endif 04920 04921 /* scan the extension list to find first matching extension-registrar */ 04922 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 04923 if (!strcmp(exten->exten, extension) && 04924 (!registrar || !strcmp(exten->registrar, registrar)) && 04925 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 04926 break; 04927 } 04928 if (!exten) { 04929 /* we can't find right extension */ 04930 if (!already_locked) 04931 ast_unlock_context(con); 04932 return -1; 04933 } 04934 04935 /* scan the priority list to remove extension with exten->priority == priority */ 04936 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 04937 peer && !strcmp(peer->exten, extension) && (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch))); 04938 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 04939 if ((priority == 0 || peer->priority == priority) && 04940 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 04941 (!registrar || !strcmp(peer->registrar, registrar) )) { 04942 found = 1; 04943 04944 /* we are first priority extension? */ 04945 if (!previous_peer) { 04946 /* 04947 * We are first in the priority chain, so must update the extension chain. 04948 * The next node is either the next priority or the next extension 04949 */ 04950 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 04951 if (peer->peer) { 04952 /* move the peer_table and peer_label_table down to the next peer, if 04953 it is there */ 04954 peer->peer->peer_table = peer->peer_table; 04955 peer->peer->peer_label_table = peer->peer_label_table; 04956 peer->peer_table = NULL; 04957 peer->peer_label_table = NULL; 04958 } 04959 if (!prev_exten) { /* change the root... */ 04960 con->root = next_node; 04961 } else { 04962 prev_exten->next = next_node; /* unlink */ 04963 } 04964 if (peer->peer) { /* update the new head of the pri list */ 04965 peer->peer->next = peer->next; 04966 } 04967 } else { /* easy, we are not first priority in extension */ 04968 previous_peer->peer = peer->peer; 04969 } 04970 04971 /* now, free whole priority extension */ 04972 destroy_exten(peer); 04973 } else { 04974 previous_peer = peer; 04975 } 04976 } 04977 if (!already_locked) 04978 ast_unlock_context(con); 04979 return found ? 0 : -1; 04980 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 7174 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07175 { 07176 int ret = -1; 07177 struct ast_context *c = find_context_locked(context); 07178 07179 if (c) { 07180 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 07181 ast_unlock_contexts(); 07182 } 07183 return ret; 07184 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 7186 of file pbx.c.
References ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_remove_ignorepat().
07187 { 07188 struct ast_ignorepat *ip, *ipl = NULL; 07189 07190 ast_wrlock_context(con); 07191 07192 for (ip = con->ignorepats; ip; ip = ip->next) { 07193 if (!strcmp(ip->pattern, ignorepat) && 07194 (!registrar || (registrar == ip->registrar))) { 07195 if (ipl) { 07196 ipl->next = ip->next; 07197 ast_free(ip); 07198 } else { 07199 con->ignorepats = ip->next; 07200 ast_free(ip); 07201 } 07202 ast_unlock_context(con); 07203 return 0; 07204 } 07205 ipl = ip; 07206 } 07207 07208 ast_unlock_context(con); 07209 errno = EINVAL; 07210 return -1; 07211 }
| int ast_context_remove_include | ( | const char * | context, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
Remove 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 4687 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
04688 { 04689 int ret = -1; 04690 struct ast_context *c = find_context_locked(context); 04691 04692 if (c) { 04693 /* found, remove include from this context ... */ 04694 ret = ast_context_remove_include2(c, include, registrar); 04695 ast_unlock_contexts(); 04696 } 04697 return ret; 04698 }
| int ast_context_remove_include2 | ( | struct ast_context * | con, | |
| const char * | include, | |||
| const char * | registrar | |||
| ) |
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 4709 of file pbx.c.
References ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, and ast_include::timing.
Referenced by ast_context_remove_include().
04710 { 04711 struct ast_include *i, *pi = NULL; 04712 int ret = -1; 04713 04714 ast_wrlock_context(con); 04715 04716 /* find our include */ 04717 for (i = con->includes; i; pi = i, i = i->next) { 04718 if (!strcmp(i->name, include) && 04719 (!registrar || !strcmp(i->registrar, registrar))) { 04720 /* remove from list */ 04721 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 04722 if (pi) 04723 pi->next = i->next; 04724 else 04725 con->includes = i->next; 04726 /* free include and return */ 04727 ast_destroy_timing(&(i->timing)); 04728 ast_free(i); 04729 ret = 0; 04730 break; 04731 } 04732 } 04733 04734 ast_unlock_context(con); 04735 04736 return ret; 04737 }
| int ast_context_remove_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
Remove a switch.
Definition at line 4744 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
04745 { 04746 int ret = -1; /* default error return */ 04747 struct ast_context *c = find_context_locked(context); 04748 04749 if (c) { 04750 /* remove switch from this context ... */ 04751 ret = ast_context_remove_switch2(c, sw, data, registrar); 04752 ast_unlock_contexts(); 04753 } 04754 return ret; 04755 }
| int ast_context_remove_switch2 | ( | struct ast_context * | con, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
This function locks given context, removes switch, unlock context and return.
Definition at line 4765 of file pbx.c.
References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
04766 { 04767 struct ast_sw *i; 04768 int ret = -1; 04769 04770 ast_wrlock_context(con); 04771 04772 /* walk switches */ 04773 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 04774 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 04775 (!registrar || !strcmp(i->registrar, registrar))) { 04776 /* found, remove from list */ 04777 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 04778 AST_LIST_REMOVE_CURRENT(list); 04779 ast_free(i); /* free switch and return */ 04780 ret = 0; 04781 break; 04782 } 04783 } 04784 AST_LIST_TRAVERSE_SAFE_END; 04785 04786 ast_unlock_context(con); 04787 04788 return ret; 04789 }
| int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5028 of file pbx.c.
References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
05029 { 05030 struct ast_context *c = NULL; 05031 int ret = -1; 05032 struct fake_context item; 05033 05034 ast_rdlock_contexts(); 05035 05036 ast_copy_string(item.name, context, sizeof(item.name)); 05037 05038 c = ast_hashtab_lookup(contexts_table,&item); 05039 if (c) 05040 ret = 0; 05041 #ifdef NOTNOW 05042 05043 while ((c = ast_walk_contexts(c))) { 05044 if (!strcmp(ast_get_context_name(c), context)) { 05045 ret = 0; 05046 break; 05047 } 05048 } 05049 05050 #endif 05051 ast_unlock_contexts(); 05052 05053 /* if we found context, unlock macrolock */ 05054 if (ret == 0) { 05055 ret = ast_mutex_unlock(&c->macrolock); 05056 } 05057 05058 return ret; 05059 }
| int ast_context_verify_includes | ( | struct ast_context * | con | ) |
Verifies includes in an ast_contect structure.
| con | context in which to verify the includes |
| 0 | if no problems found | |
| -1 | if there were any missing context |
Definition at line 9532 of file pbx.c.
References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.
Referenced by pbx_load_module().
09533 { 09534 struct ast_include *inc = NULL; 09535 int res = 0; 09536 09537 while ( (inc = ast_walk_context_includes(con, inc)) ) { 09538 if (ast_context_find(inc->rname)) 09539 continue; 09540 09541 res = -1; 09542 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 09543 ast_get_context_name(con), inc->rname); 09544 break; 09545 } 09546 09547 return res; 09548 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3202 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_func_read(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03203 { 03204 struct ast_custom_function *acf = NULL; 03205 03206 AST_RWLIST_RDLOCK(&acf_root); 03207 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03208 if (!strcmp(name, acf->name)) 03209 break; 03210 } 03211 AST_RWLIST_UNLOCK(&acf_root); 03212 03213 return acf; 03214 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3216 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by load_module(), reload(), and unload_module().
03217 { 03218 struct ast_custom_function *cur; 03219 03220 if (!acf) { 03221 return -1; 03222 } 03223 03224 AST_RWLIST_WRLOCK(&acf_root); 03225 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03226 if (cur->docsrc == AST_XML_DOC) { 03227 ast_string_field_free_memory(acf); 03228 } 03229 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03230 } 03231 AST_RWLIST_UNLOCK(&acf_root); 03232 03233 return cur ? 0 : -1; 03234 }
| int ast_destroy_timing | ( | struct ast_timing * | i | ) |
Deallocates memory structures associated with a timing bitmap.
| i | Pointer to an ast_timing structure. |
| 0 | success | |
| non-zero | failure (number suitable to pass to |
Definition at line 7017 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
| enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
| [in] | device | state |
Definition at line 3770 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.
Referenced by ast_extension_state2().
03771 { 03772 switch (devstate) { 03773 case AST_DEVICE_ONHOLD: 03774 return AST_EXTENSION_ONHOLD; 03775 case AST_DEVICE_BUSY: 03776 return AST_EXTENSION_BUSY; 03777 case AST_DEVICE_UNAVAILABLE: 03778 case AST_DEVICE_UNKNOWN: 03779 case AST_DEVICE_INVALID: 03780 return AST_EXTENSION_UNAVAILABLE; 03781 case AST_DEVICE_RINGINUSE: 03782 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 03783 case AST_DEVICE_RINGING: 03784 return AST_EXTENSION_RINGING; 03785 case AST_DEVICE_INUSE: 03786 return AST_EXTENSION_INUSE; 03787 case AST_DEVICE_NOT_INUSE: 03788 return AST_EXTENSION_NOT_INUSE; 03789 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 03790 break; 03791 } 03792 03793 return AST_EXTENSION_NOT_INUSE; 03794 }
| int ast_exists_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid | |||
| ) |
Determine whether an extension exists.
| c | this is not important | |
| context | which context to look in | |
| exten | which extension to search for | |
| priority | priority of the action within the extension | |
| callerid | callerid to search for |
Definition at line 4143 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), privacy_exec(), process_ast_dsp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_read(), skinny_ss(), socket_process(), ss7_linkset(), ss_thread(), and waitstream_core().
04144 { 04145 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04146 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 7321 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
07322 { 07323 if (!chan) 07324 return -1; 07325 07326 ast_channel_lock(chan); 07327 07328 if (!ast_strlen_zero(context)) 07329 ast_copy_string(chan->context, context, sizeof(chan->context)); 07330 if (!ast_strlen_zero(exten)) 07331 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07332 if (priority > -1) { 07333 chan->priority = priority; 07334 /* see flag description in channel.h for explanation */ 07335 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 07336 chan->priority--; 07337 } 07338 07339 ast_channel_unlock(chan); 07340 07341 return 0; 07342 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 2407 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by lua_find_extension(), and realtime_switch_common().
02408 { 02409 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02410 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02411 return extension_match_core(pattern, data, needmore); 02412 }
| int ast_extension_cmp | ( | const char * | a, | |
| const char * | b | |||
| ) |
Determine if one extension should match before another.
| a | extension to compare with b | |
| b | extension to compare with a |
Checks whether or extension a should match before extension b
| 0 | if the two extensions have equal matching priority | |
| 1 | on a > b | |
| -1 | on a < b |
Definition at line 2209 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02210 { 02211 return ext_cmp(a, b); 02212 }
| int ast_extension_match | ( | const char * | pattern, | |
| const char * | extension | |||
| ) |
Determine if a given extension matches a given pattern (in NXX format).
| pattern | pattern to match | |
| extension | extension to check against the pattern. |
Checks whether or not the given extension matches the given pattern.
| 1 | on match | |
| 0 | on failure |
Definition at line 2402 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().
02403 { 02404 return extension_match_core(pattern, data, E_MATCH); 02405 }
| int ast_extension_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 3832 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().
03833 { 03834 struct ast_exten *e; 03835 03836 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 03837 return -1; /* No hint, return -1 */ 03838 } 03839 03840 return ast_extension_state2(e); /* Check all devices in the hint */ 03841 }
| static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 3797 of file pbx.c.
References ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_get_extension_app(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), and extensionstate_buf.
Referenced by ast_add_hint_nolock(), ast_extension_state(), and handle_statechange().
03798 { 03799 struct ast_str *hint = ast_str_thread_get(&extensionstate_buf, 16); 03800 char *cur, *rest; 03801 struct ast_devstate_aggregate agg; 03802 03803 if (!e) 03804 return -1; 03805 03806 ast_devstate_aggregate_init(&agg); 03807 03808 ast_str_set(&hint, 0, "%s", ast_get_extension_app(e)); 03809 03810 rest = ast_str_buffer(hint); /* One or more devices separated with a & character */ 03811 03812 while ( (cur = strsep(&rest, "&")) ) { 03813 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 03814 } 03815 03816 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 03817 }
| 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 3820 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), and show_channels_cb().
03821 { 03822 int i; 03823 03824 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 03825 if (extension_states[i].extension_state == extension_state) 03826 return extension_states[i].text; 03827 } 03828 return "Unknown"; 03829 }
| int ast_extension_state_add | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | callback, | |||
| void * | data | |||
| ) |
Add watcher for extension states.
Registers a state change callback.
Definition at line 3896 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr(), ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_state_cb::callback, ast_hint::callbacks, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_hint::exten, ast_exten::exten, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, and stateid.
Referenced by __init_manager(), handle_request_subscribe(), and skinny_register().
03898 { 03899 struct ast_hint *hint; 03900 struct ast_state_cb *cblist; 03901 struct ast_exten *e; 03902 03903 /* If there's no context and extension: add callback to statecbs list */ 03904 if (!context && !exten) { 03905 AST_RWLIST_WRLOCK(&hints); 03906 03907 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03908 if (cblist->callback == callback) { 03909 cblist->data = data; 03910 AST_RWLIST_UNLOCK(&hints); 03911 return 0; 03912 } 03913 } 03914 03915 /* Now insert the callback */ 03916 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03917 AST_RWLIST_UNLOCK(&hints); 03918 return -1; 03919 } 03920 cblist->id = 0; 03921 cblist->callback = callback; 03922 cblist->data = data; 03923 03924 AST_LIST_INSERT_HEAD(&statecbs, cblist, entry); 03925 03926 AST_RWLIST_UNLOCK(&hints); 03927 03928 return 0; 03929 } 03930 03931 if (!context || !exten) 03932 return -1; 03933 03934 /* This callback type is for only one hint, so get the hint */ 03935 e = ast_hint_extension(NULL, context, exten); 03936 if (!e) { 03937 return -1; 03938 } 03939 03940 /* If this is a pattern, dynamically create a new extension for this 03941 * particular match. Note that this will only happen once for each 03942 * individual extension, because the pattern will no longer match first. 03943 */ 03944 if (e->exten[0] == '_') { 03945 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 03946 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 03947 e->registrar); 03948 e = ast_hint_extension(NULL, context, exten); 03949 if (!e || e->exten[0] == '_') { 03950 return -1; 03951 } 03952 } 03953 03954 /* Find the hint in the list of hints */ 03955 AST_RWLIST_WRLOCK(&hints); 03956 03957 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03958 if (hint->exten == e) 03959 break; 03960 } 03961 03962 if (!hint) { 03963 /* We have no hint, sorry */ 03964 AST_RWLIST_UNLOCK(&hints); 03965 return -1; 03966 } 03967 03968 /* Now insert the callback in the callback list */ 03969 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03970 AST_RWLIST_UNLOCK(&hints); 03971 return -1; 03972 } 03973 03974 cblist->id = stateid++; /* Unique ID for this callback */ 03975 cblist->callback = callback; /* Pointer to callback routine */ 03976 cblist->data = data; /* Data for the callback */ 03977 03978 AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry); 03979 03980 AST_RWLIST_UNLOCK(&hints); 03981 03982 return cblist->id; 03983 }
| int ast_extension_state_del | ( | int | id, | |
| ast_state_cb_type | callback | |||
| ) |
Remove a watcher from the callback list.
Deletes a registered state change callback by ID.
Definition at line 3986 of file pbx.c.
References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, ast_hint::callbacks, and ast_state_cb::id.
Referenced by dialog_unlink_all(), handle_request_subscribe(), and skinny_unregister().
03987 { 03988 struct ast_state_cb *p_cur = NULL; 03989 int ret = -1; 03990 03991 if (!id && !callback) 03992 return -1; 03993 03994 AST_RWLIST_WRLOCK(&hints); 03995 03996 if (!id) { /* id == 0 is a callback without extension */ 03997 AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) { 03998 if (p_cur->callback == callback) { 03999 AST_LIST_REMOVE_CURRENT(entry); 04000 break; 04001 } 04002 } 04003 AST_LIST_TRAVERSE_SAFE_END; 04004 } else { /* callback with extension, find the callback based on ID */ 04005 struct ast_hint *hint; 04006 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04007 AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) { 04008 if (p_cur->id == id) { 04009 AST_LIST_REMOVE_CURRENT(entry); 04010 break; 04011 } 04012 } 04013 AST_LIST_TRAVERSE_SAFE_END; 04014 04015 if (p_cur) 04016 break; 04017 } 04018 } 04019 04020 if (p_cur) { 04021 ast_free(p_cur); 04022 } 04023 04024 AST_RWLIST_UNLOCK(&hints); 04025 04026 return ret; 04027 }
| int ast_findlabel_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| const char * | label, | |||
| const char * | callerid | |||
| ) |
Find the priority of an extension that has the specified label.
| c | this is not important | |
| context | which context to look in | |
| exten | which extension to search for | |
| label | label of the action within the extension to match to priority | |
| callerid | callerid to search for |
| the | priority which matches the given label in the extension | |
| -1 | if not found. |
Definition at line 4148 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by action_originate(), action_redirect(), handle_gosub(), handle_setpriority(), isexten_function_read(), and pbx_parseable_goto().
04149 { 04150 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04151 }
| int ast_findlabel_extension2 | ( | struct ast_channel * | c, | |
| struct ast_context * | con, | |||
| const char * | exten, | |||
| const char * | label, | |||
| const char * | callerid | |||
| ) |
Find the priority of an extension that has the specified label.
Definition at line 4153 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
04154 { 04155 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04156 }
| int ast_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | workspace, | |||
| size_t | len | |||
| ) |
executes a read operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| workspace | A pointer to safe memory to use for a return value | |
| len | the number of bytes in workspace |
This application executes a function in read mode on a given channel.
| 0 | success | |
| non-zero | failure |
Definition at line 3356 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::read.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03357 { 03358 char *copy = ast_strdupa(function); 03359 char *args = func_args(copy); 03360 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03361 03362 if (acfptr == NULL) 03363 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03364 else if (!acfptr->read) 03365 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03366 else { 03367 int res; 03368 struct ast_module_user *u = NULL; 03369 if (acfptr->mod) 03370 u = __ast_module_user_add(acfptr->mod, chan); 03371 res = acfptr->read(chan, copy, args, workspace, len); 03372 if (acfptr->mod && u) 03373 __ast_module_user_remove(acfptr->mod, u); 03374 return res; 03375 } 03376 return -1; 03377 }
| int ast_func_write | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| const char * | value | |||
| ) |
executes a write operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| value | A value parameter to pass for writing |
This application executes a function in write mode on a given channel.
| 0 | success | |
| non-zero | failure |
Definition at line 3379 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by action_setvar(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03380 { 03381 char *copy = ast_strdupa(function); 03382 char *args = func_args(copy); 03383 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03384 03385 if (acfptr == NULL) 03386 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03387 else if (!acfptr->write) 03388 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03389 else { 03390 int res; 03391 struct ast_module_user *u = NULL; 03392 if (acfptr->mod) 03393 u = __ast_module_user_add(acfptr->mod, chan); 03394 res = acfptr->write(chan, copy, args, value); 03395 if (acfptr->mod && u) 03396 __ast_module_user_remove(acfptr->mod, u); 03397 return res; 03398 } 03399 03400 return -1; 03401 }
| const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 9384 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_lockmacro(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_unlockmacro(), ast_context_verify_includes(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09385 { 09386 return con ? con->name : NULL; 09387 }
| const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 9422 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
09423 { 09424 return c ? c->registrar : NULL; 09425 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 9452 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint_nolock(), ast_extension_state2(), ast_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), manager_show_dialplan_helper(), and print_ext().
09453 { 09454 return e ? e->app : NULL; 09455 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 9457 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
09458 { 09459 return e ? e->data : NULL; 09460 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 9447 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09448 { 09449 return e ? e->cidmatch : NULL; 09450 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 9389 of file pbx.c.
References ast_exten::parent.
Referenced by handle_show_hint(), and handle_show_hints().
09390 { 09391 return exten ? exten->parent : NULL; 09392 }
| const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 9399 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09400 { 09401 return exten ? exten->label : NULL; 09402 }
| int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 9442 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09443 { 09444 return e ? e->matchcid : 0; 09445 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 9394 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint_nolock(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().
09395 { 09396 return exten ? exten->exten : NULL; 09397 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 9414 of file pbx.c.
References ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
09415 { 09416 return exten ? exten->priority : -1; 09417 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 9427 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09428 { 09429 return e ? e->registrar : NULL; 09430 }
| int ast_get_hint | ( | char * | hint, | |
| int | hintsize, | |||
| char * | name, | |||
| int | namesize, | |||
| struct ast_channel * | c, | |||
| const char * | context, | |||
| const char * | exten | |||
| ) |
Get hint for channel.
If an extension hint exists, return non-zero.
Definition at line 4126 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), pbx_retrieve_variable(), skinny_extensionstate_cb(), and transmit_state_notify().
04127 { 04128 struct ast_exten *e = ast_hint_extension(c, context, exten); 04129 04130 if (e) { 04131 if (hint) 04132 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04133 if (name) { 04134 const char *tmp = ast_get_extension_app_data(e); 04135 if (tmp) 04136 ast_copy_string(name, tmp, namesize); 04137 } 04138 return -1; 04139 } 04140 return 0; 04141 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9409 of file pbx.c.
References ast_ignorepat::pattern.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
09410 { 09411 return ip ? ip->pattern : NULL; 09412 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9437 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09438 { 09439 return ip ? ip->registrar : NULL; 09440 }
| const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 9404 of file pbx.c.
References ast_include::name.
Referenced by complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
09405 { 09406 return inc ? inc->name : NULL; 09407 }
| const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 9432 of file pbx.c.
References ast_include::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09433 { 09434 return i ? i->registrar : NULL; 09435 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 9467 of file pbx.c.
References ast_sw::data.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09468 { 09469 return sw ? sw->data : NULL; 09470 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 9472 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
09473 { 09474 return sw->eval; 09475 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 9462 of file pbx.c.
References ast_sw::name.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09463 { 09464 return sw ? sw->name : NULL; 09465 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 9477 of file pbx.c.
References ast_sw::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09478 { 09479 return sw ? sw->registrar : NULL; 09480 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 9570 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), and valid_exit().
09571 { 09572 return __ast_goto_if_exists(chan, context, exten, priority, 0); 09573 }
| int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) |
hashtable functions for contexts
Definition at line 994 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
00995 { 00996 const struct ast_context *ac = ah_a; 00997 const struct ast_context *bc = ah_b; 00998 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 00999 return 1; 01000 /* assume context names are registered in a string table! */ 01001 return strcmp(ac->name, bc->name); 01002 }
| unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1037 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01038 { 01039 const struct ast_context *ac = obj; 01040 return ast_hashtab_hash_string(ac->name); 01041 }
| static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten | |||
| ) | [static, read] |
Definition at line 3761 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(), and ast_get_hint().
03762 { 03763 struct ast_exten *e; 03764 ast_rdlock_contexts(); 03765 e = ast_hint_extension_nolock(c, context, exten); 03766 ast_unlock_contexts(); 03767 return e; 03768 }
| 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 3755 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().
03756 { 03757 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 03758 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 03759 }
| int ast_ignore_pattern | ( | const char * | context, | |
| const char * | pattern | |||
| ) |
Checks to see if a number should be ignored.
| context | context to search within | |
| pattern | to check whether it should be ignored or not |
Check if a number should be ignored with respect to dialtone cancellation.
| 0 | if the pattern should not be ignored | |
| non-zero | if the pattern should be ignored |
Definition at line 7267 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().
07268 { 07269 struct ast_context *con = ast_context_find(context); 07270 if (con) { 07271 struct ast_ignorepat *pat; 07272 for (pat = con->ignorepats; pat; pat = pat->next) { 07273 if (ast_extension_match(pat->pattern, pattern)) 07274 return 1; 07275 } 07276 } 07277 07278 return 0; 07279 }
| int ast_matchmore_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid | |||
| ) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
| c | not really important XXX | |
| context | context to serach within | |
| exten | extension to check | |
| priority | priority of extension path | |
| callerid | callerid of extension being searched for |
Definition at line 4163 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __ast_pbx_run(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_dchannel(), readexten_exec(), skinny_ss(), and ss_thread().
04164 { 04165 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04166 }
| void ast_merge_contexts_and_delete | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| const char * | registrar | |||
| ) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
| extcontexts | pointer to the ast_context structure | |
| exttable | pointer to the ast_hashtab structure that contains all the elements in extcontexts | |
| registrar | of the context; if it's set the routine will delete all contexts that belong to that registrar; if NULL only the contexts that are specified in extcontexts |
Definition at line 6623 of file pbx.c.
References __ast_internal_context_destroy(), ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, ast_exten::data, E_MATCH, ast_exten::exten, ast_hint::exten, ast_hint::laststate, LOG_WARNING, ast_context::name, ast_context::next, ast_sw::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
06624 { 06625 double ft; 06626 struct ast_context *tmp, *oldcontextslist; 06627 struct ast_hashtab *oldtable; 06628 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 06629 struct store_hint *this; 06630 struct ast_hint *hint; 06631 struct ast_exten *exten; 06632 int length; 06633 struct ast_state_cb *thiscb; 06634 struct ast_hashtab_iter *iter; 06635 06636 /* it is very important that this function hold the hint list lock _and_ the conlock 06637 during its operation; not only do we need to ensure that the list of contexts 06638 and extensions does not change, but also that no hint callbacks (watchers) are 06639 added or removed during the merge/delete process 06640 06641 in addition, the locks _must_ be taken in this order, because there are already 06642 other code paths that use this order 06643 */ 06644 06645 struct timeval begintime, writelocktime, endlocktime, enddeltime; 06646 int wrlock_ver; 06647 06648 begintime = ast_tvnow(); 06649 ast_rdlock_contexts(); 06650 iter = ast_hashtab_start_traversal(contexts_table); 06651 while ((tmp = ast_hashtab_next(iter))) { 06652 context_merge(extcontexts, exttable, tmp, registrar); 06653 } 06654 ast_hashtab_end_traversal(iter); 06655 wrlock_ver = ast_wrlock_contexts_version(); 06656 06657 ast_unlock_contexts(); /* this feels real retarded, but you must do 06658 what you must do If this isn't done, the following 06659 wrlock is a guraranteed deadlock */ 06660 ast_wrlock_contexts(); 06661 if (ast_wrlock_contexts_version() > wrlock_ver+1) { 06662 ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); 06663 } 06664 06665 AST_RWLIST_WRLOCK(&hints); 06666 writelocktime = ast_tvnow(); 06667 06668 /* preserve all watchers for hints */ 06669 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06670 if (!AST_LIST_EMPTY(&hint->callbacks)) { 06671 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 06672 if (!(this = ast_calloc(1, length))) 06673 continue; 06674 /* this removes all the callbacks from the hint into this. */ 06675 AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry); 06676 this->laststate = hint->laststate; 06677 this->context = this->data; 06678 strcpy(this->data, hint->exten->parent->name); 06679 this->exten = this->data + strlen(this->context) + 1; 06680 strcpy(this->exten, hint->exten->exten); 06681 AST_LIST_INSERT_HEAD(&store, this, list); 06682 } 06683 } 06684 06685 /* save the old table and list */ 06686 oldtable = contexts_table; 06687 oldcontextslist = contexts; 06688 06689 /* move in the new table and list */ 06690 contexts_table = exttable; 06691 contexts = *extcontexts; 06692 06693 /* restore the watchers for hints that can be found; notify those that 06694 cannot be restored 06695 */ 06696 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 06697 struct pbx_find_info q = { .stacklen = 0 }; 06698 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 06699 /* If this is a pattern, dynamically create a new extension for this 06700 * particular match. Note that this will only happen once for each 06701 * individual extension, because the pattern will no longer match first. 06702 */ 06703 if (exten && exten->exten[0] == '_') { 06704 ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL, 06705 0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar); 06706 /* rwlocks are not recursive locks */ 06707 exten = ast_hint_extension_nolock(NULL, this->context, this->exten); 06708 } 06709 06710 /* Find the hint in the list of hints */ 06711 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06712 if (hint->exten == exten) 06713 break; 06714 } 06715 if (!exten || !hint) { 06716 /* this hint has been removed, notify the watchers */ 06717 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 06718 thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data); 06719 ast_free(thiscb); 06720 } 06721 } else { 06722 AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry); 06723 hint->laststate = this->laststate; 06724 } 06725 ast_free(this); 06726 } 06727 06728 AST_RWLIST_UNLOCK(&hints); 06729 ast_unlock_contexts(); 06730 endlocktime = ast_tvnow(); 06731 06732 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 06733 is now freely using the new stuff instead */ 06734 06735 ast_hashtab_destroy(oldtable, NULL); 06736 06737 for (tmp = oldcontextslist; tmp; ) { 06738 struct ast_context *next; /* next starting point */ 06739 next = tmp->next; 06740 __ast_internal_context_destroy(tmp); 06741 tmp = next; 06742 } 06743 enddeltime = ast_tvnow(); 06744 06745 ft = ast_tvdiff_us(writelocktime, begintime); 06746 ft /= 1000000.0; 06747 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 06748 06749 ft = ast_tvdiff_us(endlocktime, writelocktime); 06750 ft /= 1000000.0; 06751 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 06752 06753 ft = ast_tvdiff_us(enddeltime, endlocktime); 06754 ft /= 1000000.0; 06755 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 06756 06757 ft = ast_tvdiff_us(enddeltime, begintime); 06758 ft /= 1000000.0; 06759 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 06760 return; 06761 }
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9633 of file pbx.c.
References pbx_parseable_goto().
Referenced by _while_exec(), check_goto_on_transfer(), dial_exec_full(), gosub_exec(), ivr_dispatch(), parkandannounce_exec(), pbx_builtin_goto(), and while_continue_exec().
09634 { 09635 return pbx_parseable_goto(chan, goto_string, 0); 09636 }
| int ast_pbx_outgoing_app | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int | timeout, | |||
| const char * | app, | |||
| const char * | appdata, | |||
| int * | reason, | |||
| int | sync, | |||
| const char * | cid_num, | |||
| const char * | cid_name, | |||
| struct ast_variable * | vars, | |||
| const char * | account, | |||
| struct ast_channel ** | locked_channel | |||
| ) |
Synchronously or asynchronously make an outbound call and send it to a particular application with given extension
Definition at line 8106 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, app_tmp::data, errno, ast_channel::hangupcause, LOG_WARNING, ast_channel::name, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
08107 { 08108 struct ast_channel *chan; 08109 struct app_tmp *tmp; 08110 int res = -1, cdr_res = -1; 08111 struct outgoing_helper oh; 08112 08113 memset(&oh, 0, sizeof(oh)); 08114 oh.vars = vars; 08115 oh.account = account; 08116 08117 if (locked_channel) 08118 *locked_channel = NULL; 08119 if (ast_strlen_zero(app)) { 08120 res = -1; 08121 goto outgoing_app_cleanup; 08122 } 08123 if (synchronous) { 08124 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 08125 if (chan) { 08126 ast_set_variables(chan, vars); 08127 if (account) 08128 ast_cdr_setaccount(chan, account); 08129 if (chan->_state == AST_STATE_UP) { 08130 res = 0; 08131 ast_verb(4, "Channel %s was answered.\n", chan->name); 08132 tmp = ast_calloc(1, sizeof(*tmp)); 08133 if (!tmp) 08134 res = -1; 08135 else { 08136 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 08137 if (appdata) 08138 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 08139 tmp->chan = chan; 08140 if (synchronous > 1) { 08141 if (locked_channel) 08142 ast_channel_unlock(chan); 08143 ast_pbx_run_app(tmp); 08144 } else { 08145 if (locked_channel) 08146 ast_channel_lock(chan); 08147 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 08148 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 08149 ast_free(tmp); 08150 if (locked_channel) 08151 ast_channel_unlock(chan); 08152 ast_hangup(chan); 08153 res = -1; 08154 } else { 08155 if (locked_channel) 08156 *locked_channel = chan; 08157 } 08158 } 08159 } 08160 } else { 08161 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08162 if (chan->cdr) { /* update the cdr */ 08163 /* here we update the status of the call, which sould be busy. 08164 * if that fails then we set the status to failed */ 08165 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08166 ast_cdr_failed(chan->cdr); 08167 } 08168 ast_hangup(chan); 08169 } 08170 } 08171 08172 if (res < 0) { /* the call failed for some reason */ 08173 if (*reason == 0) { /* if the call failed (not busy or no answer) 08174 * update the cdr with the failed message */ 08175 cdr_res = ast_pbx_outgoing_cdr_failed(); 08176 if (cdr_res != 0) { 08177 res = cdr_res; 08178 goto outgoing_app_cleanup; 08179 } 08180 } 08181 } 08182 08183 } else { 08184 struct async_stat *as; 08185 if (!(as = ast_calloc(1, sizeof(*as)))) { 08186 res = -1; 08187 goto outgoing_app_cleanup; 08188 } 08189 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 08190 if (!chan) { 08191 ast_free(as); 08192 res = -1; 08193 goto outgoing_app_cleanup; 08194 } 08195 as->chan = chan; 08196 ast_copy_string(as->app, app, sizeof(as->app)); 08197 if (appdata) 08198 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 08199 as->timeout = timeout; 08200 ast_set_variables(chan, vars); 08201 if (account) 08202 ast_cdr_setaccount(chan, account); 08203 /* Start a new thread, and get something handling this channel. */ 08204 if (locked_channel) 08205 ast_channel_lock(chan); 08206 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08207 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08208 ast_free(as); 08209 if (locked_channel) 08210 ast_channel_unlock(chan); 08211 ast_hangup(chan); 08212 res = -1; 08213 goto outgoing_app_cleanup; 08214 } else { 08215 if (locked_channel) 08216 *locked_channel = chan; 08217 } 08218 res = 0; 08219 } 08220 outgoing_app_cleanup: 08221 ast_variables_destroy(vars); 08222 return res; 08223 }
| static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 7914 of file pbx.c.
References ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_alloc, ast_channel_free(), AST_STATE_DOWN, and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
07915 { 07916 /* allocate a channel */ 07917 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", ""); 07918 07919 if (!chan) 07920 return -1; /* failure */ 07921 07922 if (!chan->cdr) { 07923 /* allocation of the cdr failed */ 07924 ast_channel_free(chan); /* free the channel */ 07925 return -1; /* return failure */ 07926 } 07927 07928 /* allocation of the cdr was successful */ 07929 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 07930 ast_cdr_start(chan->cdr); /* record the start and stop time */ 07931 ast_cdr_end(chan->cdr); 07932 ast_cdr_failed(chan->cdr); /* set the status to failed */ 07933 ast_cdr_detach(chan->cdr); /* post and free the record */ 07934 chan->cdr = NULL; 07935 ast_channel_free(chan); /* free the channel */ 07936 07937 return 0; /* success */ 07938 }
| int ast_pbx_outgoing_exten | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int | timeout, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int * | reason, | |||
| int | sync, | |||
| const char * | cid_num, | |||
| const char * | cid_name, | |||
| struct ast_variable * | vars, | |||
| const char * | account, | |||
| struct ast_channel ** | locked_channel | |||
| ) |
Synchronously or asynchronously make an outbound call and send it to a particular extension
Definition at line 7940 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
07941 { 07942 struct ast_channel *chan; 07943 struct async_stat *as; 07944 int res = -1, cdr_res = -1; 07945 struct outgoing_helper oh; 07946 07947 if (synchronous) { 07948 oh.context = context; 07949 oh.exten = exten; 07950 oh.priority = priority; 07951 oh.cid_num = cid_num; 07952 oh.cid_name = cid_name; 07953 oh.account = account; 07954 oh.vars = vars; 07955 oh.parent_channel = NULL; 07956 07957 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07958 if (channel) { 07959 *channel = chan; 07960 if (chan) 07961 ast_channel_lock(chan); 07962 } 07963 if (chan) { 07964 if (chan->_state == AST_STATE_UP) { 07965 res = 0; 07966 ast_verb(4, "Channel %s was answered.\n", chan->name); 07967 07968 if (synchronous > 1) { 07969 if (channel) 07970 ast_channel_unlock(chan); 07971 if (ast_pbx_run(chan)) { 07972 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07973 if (channel) 07974 *channel = NULL; 07975 ast_hangup(chan); 07976 chan = NULL; 07977 res = -1; 07978 } 07979 } else { 07980 if (ast_pbx_start(chan)) { 07981 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 07982 if (channel) { 07983 *channel = NULL; 07984 ast_channel_unlock(chan); 07985 } 07986 ast_hangup(chan); 07987 res = -1; 07988 } 07989 chan = NULL; 07990 } 07991 } else { 07992 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07993 07994 if (chan->cdr) { /* update the cdr */ 07995 /* here we update the status of the call, which sould be busy. 07996 * if that fails then we set the status to failed */ 07997 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07998 ast_cdr_failed(chan->cdr); 07999 } 08000 08001 if (channel) { 08002 *channel = NULL; 08003 ast_channel_unlock(chan); 08004 } 08005 ast_hangup(chan); 08006 chan = NULL; 08007 } 08008 } 08009 08010 if (res < 0) { /* the call failed for some reason */ 08011 if (*reason == 0) { /* if the call failed (not busy or no answer) 08012 * update the cdr with the failed message */ 08013 cdr_res = ast_pbx_outgoing_cdr_failed(); 08014 if (cdr_res != 0) { 08015 res = cdr_res; 08016 goto outgoing_exten_cleanup; 08017 } 08018 } 08019 08020 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08021 /* check if "failed" exists */ 08022 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08023 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 08024 if (chan) { 08025 char failed_reason[4] = ""; 08026 if (!ast_strlen_zero(context)) 08027 ast_copy_string(chan->context, context, sizeof(chan->context)); 08028 set_ext_pri(chan, "failed", 1); 08029 ast_set_variables(chan, vars); 08030 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08031 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08032 if (account) 08033 ast_cdr_setaccount(chan, account); 08034 if (ast_pbx_run(chan)) { 08035 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08036 ast_hangup(chan); 08037 } 08038 chan = NULL; 08039 } 08040 } 08041 } 08042 } else { 08043 if (!(as = ast_calloc(1, sizeof(*as)))) { 08044 res = -1; 08045 goto outgoing_exten_cleanup; 08046 } 08047 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 08048 if (channel) { 08049 *channel = chan; 08050 if (chan) 08051 ast_channel_lock(chan); 08052 } 08053 if (!chan) { 08054 ast_free(as); 08055 res = -1; 08056 goto outgoing_exten_cleanup; 08057 } 08058 as->chan = chan; 08059 ast_copy_string(as->context, context, sizeof(as->context)); 08060 set_ext_pri(as->chan, exten, priority); 08061 as->timeout = timeout; 08062 ast_set_variables(chan, vars); 08063 if (account) 08064 ast_cdr_setaccount(chan, account); 08065 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08066 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08067 ast_free(as); 08068 if (channel) { 08069 *channel = NULL; 08070 ast_channel_unlock(chan); 08071 } 08072 ast_hangup(chan); 08073 res = -1; 08074 goto outgoing_exten_cleanup; 08075 } 08076 res = 0; 08077 } 08078 outgoing_exten_cleanup: 08079 ast_variables_destroy(vars); 08080 return res; 08081 }
| enum ast_pbx_result ast_pbx_run | ( | struct ast_channel * | c | ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
| Zero | on success | |
| non-zero | on failure |
Definition at line 4596 of file pbx.c.
References ast_pbx_run_args().
Referenced by ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), mgcp_ss(), skinny_newcall(), ss_thread(), and unistim_ss().
04597 { 04598 return ast_pbx_run_args(c, NULL); 04599 }
| static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 8091 of file pbx.c.
References app_tmp::app, ast_free, ast_hangup(), ast_log(), ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, ast_channel::name, pbx_exec(), and pbx_findapp().
Referenced by ast_pbx_outgoing_app().
08092 { 08093 struct app_tmp *tmp = data; 08094 struct ast_app *app; 08095 app = pbx_findapp(tmp->app); 08096 if (app) { 08097 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 08098 pbx_exec(tmp->chan, app, tmp->data); 08099 } else 08100 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 08101 ast_hangup(tmp->chan); 08102 ast_free(tmp); 08103 return NULL; 08104 }
| enum ast_pbx_result ast_pbx_run_args | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) |
Execute the PBX in the current thread.
| c | channel to run the pbx on | |
| args | options for the pbx |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
| Zero | on success | |
| non-zero | on failure |
Definition at line 4581 of file pbx.c.
References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
04582 { 04583 enum ast_pbx_result res = AST_PBX_SUCCESS; 04584 04585 if (increase_call_count(c)) { 04586 return AST_PBX_CALL_LIMIT; 04587 } 04588 04589 res = __ast_pbx_run(c, args); 04590 04591 decrease_call_count(); 04592 04593 return res; 04594 }
| enum ast_pbx_result ast_pbx_start | ( | struct ast_channel * | c | ) |
Create a new thread and start the PBX.
| c | channel to start the pbx on |
| Zero | on success | |
| non-zero | on failure |
Definition at line 4559 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parkinglot(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), pri_dchannel(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().
04560 { 04561 pthread_t t; 04562 04563 if (!c) { 04564 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 04565 return AST_PBX_FAILED; 04566 } 04567 04568 if (increase_call_count(c)) 04569 return AST_PBX_CALL_LIMIT; 04570 04571 /* Start a new thread, and get something handling this channel. */ 04572 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 04573 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 04574 decrease_call_count(); 04575 return AST_PBX_FAILED; 04576 } 04577 04578 return AST_PBX_SUCCESS; 04579 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 4606 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
04607 { 04608 return totalcalls; 04609 }
| int ast_rdlock_context | ( | struct ast_context * | con | ) |
Read locks a given context.
| con | context to lock |
| 0 | on success | |
| -1 | on failure |
Definition at line 9371 of file pbx.c.
References ast_rwlock_rdlock(), and ast_context::lock.
Referenced by _macro_exec(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09372 { 09373 return ast_rwlock_rdlock(&con->lock); 09374 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 9353 of file pbx.c.
References ast_rwlock_rdlock(), and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09354 { 09355 return ast_rwlock_rdlock(&conlock); 09356 }
| int ast_register_application2 | ( | const char * | app, | |
| int(*)(struct ast_channel *, void *) | execute, | |||
| const char * | synopsis, | |||
| const char * | description, | |||
| void * | mod | |||
| ) |
Dynamically register a new dial plan application.
Register an application.
Definition at line 5062 of file pbx.c.
References ast_app::arguments, ast_calloc, ast_free, 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_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_features_init(), and load_pbx().
05063 { 05064 struct ast_app *tmp, *cur = NULL; 05065 char tmps[80]; 05066 int length, res; 05067 #ifdef AST_XML_DOCS 05068 char *tmpxml; 05069 #endif 05070 05071 AST_RWLIST_WRLOCK(&apps); 05072 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 05073 if (!(res = strcasecmp(app, tmp->name))) { 05074 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 05075 AST_RWLIST_UNLOCK(&apps); 05076 return -1; 05077 } else if (res < 0) 05078 break; 05079 } 05080 05081 length = sizeof(*tmp) + strlen(app) + 1; 05082 05083 if (!(tmp = ast_calloc(1, length))) { 05084 AST_RWLIST_UNLOCK(&apps); 05085 return -1; 05086 } 05087 05088 if (ast_string_field_init(tmp, 128)) { 05089 AST_RWLIST_UNLOCK(&apps); 05090 ast_free(tmp); 05091 return -1; 05092 } 05093 05094 #ifdef AST_XML_DOCS 05095 /* Try to lookup the docs in our XML documentation database */ 05096 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05097 /* load synopsis */ 05098 tmpxml = ast_xmldoc_build_synopsis("application", app); 05099 ast_string_field_set(tmp, synopsis, tmpxml); 05100 ast_free(tmpxml); 05101 05102 /* load description */ 05103 tmpxml = ast_xmldoc_build_description("application", app); 05104 ast_string_field_set(tmp, description, tmpxml); 05105 ast_free(tmpxml); 05106 05107 /* load syntax */ 05108 tmpxml = ast_xmldoc_build_syntax("application", app); 05109 ast_string_field_set(tmp, syntax, tmpxml); 05110 ast_free(tmpxml); 05111 05112 /* load arguments */ 05113 tmpxml = ast_xmldoc_build_arguments("application", app); 05114 ast_string_field_set(tmp, arguments, tmpxml); 05115 ast_free(tmpxml); 05116 05117 /* load seealso */ 05118 tmpxml = ast_xmldoc_build_seealso("application", app); 05119 ast_string_field_set(tmp, seealso, tmpxml); 05120 ast_free(tmpxml); 05121 tmp->docsrc = AST_XML_DOC; 05122 } else { 05123 #endif 05124 ast_string_field_set(tmp, synopsis, synopsis); 05125 ast_string_field_set(tmp, description, description); 05126 tmp->docsrc = AST_STATIC_DOC; 05127 #ifdef AST_XML_DOCS 05128 } 05129 #endif 05130 05131 strcpy(tmp->name, app); 05132 tmp->execute = execute; 05133 tmp->module = mod; 05134 05135 /* Store in alphabetical order */ 05136 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 05137 if (strcasecmp(tmp->name, cur->name) < 0) { 05138 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 05139 break; 05140 } 05141 } 05142 AST_RWLIST_TRAVERSE_SAFE_END; 05143 if (!cur) 05144 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 05145 05146 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 05147 05148 AST_RWLIST_UNLOCK(&apps); 05149 05150 return 0; 05151 }
| int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
| sw | switch to register |
This function registers a populated ast_switch structure with the asterisk switching architecture.
| 0 | success | |
| non-zero | failure |
Definition at line 5157 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
05158 { 05159 struct ast_switch *tmp; 05160 05161 AST_RWLIST_WRLOCK(&switches); 05162 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05163 if (!strcasecmp(tmp->name, sw->name)) { 05164 AST_RWLIST_UNLOCK(&switches); 05165 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05166 return -1; 05167 } 05168 } 05169 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05170 AST_RWLIST_UNLOCK(&switches); 05171 05172 return 0; 05173 }
| static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 4091 of file pbx.c.
References AST_EXTENSION_DEACTIVATED, ast_free, AST_LIST_REMOVE_HEAD, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, ast_context::name, and ast_exten::parent.
Referenced by destroy_exten().
04092 { 04093 /* Cleanup the Notifys if hint is removed */ 04094 struct ast_hint *hint; 04095 struct ast_state_cb *cblist; 04096 int res = -1; 04097 04098 if (!e) 04099 return -1; 04100 04101 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 04102 if (hint->exten != e) 04103 continue; 04104 04105 while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) { 04106 /* Notify with -1 and remove all callbacks */ 04107 cblist->callback(hint->exten->parent->name, hint->exten->exten, 04108 AST_EXTENSION_DEACTIVATED, cblist->data); 04109 ast_free(cblist); 04110 } 04111 04112 AST_RWLIST_REMOVE_CURRENT(list); 04113 ast_free(hint); 04114 04115 res = 0; 04116 04117 break; 04118 } 04119 AST_RWLIST_TRAVERSE_SAFE_END; 04120 04121 return res; 04122 }
| int ast_spawn_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| int * | found, | |||
| int | combined_find_spawn | |||
| ) |
Launch a new extension (i.e. new stack).
| c | not important | |
| context | which context to generate the extension within | |
| exten | new extension to add | |
| priority | priority of new extension | |
| callerid | callerid of extension | |
| found | ||
| combined_find_spawn |
This adds a new extension to the asterisk extension list.
| 0 | on success | |
| -1 | on failure. |
Definition at line 4168 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), and loopback_exec().
04169 { 04170 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04171 }
| int ast_unlock_context | ( | struct ast_context * | con | ) |
| Unlocks | the given context |
| con | context to unlock |
| 0 | on success | |
| -1 | on failure |
Definition at line 9376 of file pbx.c.
References ast_rwlock_unlock(), and ast_context::lock.
Referenced by __ast_context_destroy(), _macro_exec(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), ast_context_remove_switch2(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09377 { 09378 return ast_rwlock_unlock(&con->lock); 09379 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 9358 of file pbx.c.
References ast_rwlock_unlock(), and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09359 { 09360 return ast_rwlock_unlock(&conlock); 09361 }
| 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 6403 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(), load_module(), and unload_module().
06404 { 06405 struct ast_app *tmp; 06406 06407 AST_RWLIST_WRLOCK(&apps); 06408 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 06409 if (!strcasecmp(app, tmp->name)) { 06410 unreference_cached_app(tmp); 06411 AST_RWLIST_REMOVE_CURRENT(list); 06412 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 06413 ast_string_field_free_memory(tmp); 06414 ast_free(tmp); 06415 break; 06416 } 06417 } 06418 AST_RWLIST_TRAVERSE_SAFE_END; 06419 AST_RWLIST_UNLOCK(&apps); 06420 06421 return tmp ? 0 : -1; 06422 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 5175 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
05176 { 05177 AST_RWLIST_WRLOCK(&switches); 05178 AST_RWLIST_REMOVE(&switches, sw, list); 05179 AST_RWLIST_UNLOCK(&switches); 05180 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | exten | |||
| ) | [read] |
Definition at line 9490 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
| struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
| struct ast_ignorepat * | ip | |||
| ) | [read] |
Definition at line 9523 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
09525 { 09526 if (!ip) 09527 return con ? con->ignorepats : NULL; 09528 else 09529 return ip->next; 09530 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 9514 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
| struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
| struct ast_sw * | sw | |||
| ) | [read] |
Definition at line 9499 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09501 { 09502 if (!sw) 09503 return con ? AST_LIST_FIRST(&con->alts) : NULL; 09504 else 09505 return AST_LIST_NEXT(sw, list); 09506 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 9485 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
| struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 9508 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
09510 { 09511 return priority ? priority->peer : exten; 09512 }
| int ast_wrlock_context | ( | struct ast_context * | con | ) |
Write locks a given context.
| con | context to lock |
| 0 | on success | |
| -1 | on failure |
Definition at line 9366 of file pbx.c.
References ast_rwlock_wrlock(), and ast_context::lock.
Referenced by __ast_context_destroy(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), and ast_context_remove_switch2().
09367 { 09368 return ast_rwlock_wrlock(&con->lock); 09369 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 9345 of file pbx.c.
References ast_atomic_fetchadd_int(), ast_rwlock_wrlock(), conlock, and conlock_wrlock_version.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
09346 { 09347 int res = ast_rwlock_wrlock(&conlock); 09348 if (!res) 09349 ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); 09350 return res; 09351 }
| int ast_wrlock_contexts_version | ( | void | ) |
Definition at line 9337 of file pbx.c.
References conlock_wrlock_version.
Referenced by ast_merge_contexts_and_delete().
09338 { 09339 return conlock_wrlock_version; 09340 }
| static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 7853 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_STATE_UP, ast_strlen_zero(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, ast_frame::frametype, LOG_ERROR, LOG_WARNING, ast_channel::name, 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().
07854 { 07855 struct async_stat *as = data; 07856 struct ast_channel *chan = as->chan; 07857 int timeout = as->timeout; 07858 int res; 07859 struct ast_frame *f; 07860 struct ast_app *app; 07861 07862 while (timeout && (chan->_state != AST_STATE_UP)) { 07863 res = ast_waitfor(chan, timeout); 07864 if (res < 1) 07865 break; 07866 if (timeout > -1) 07867 timeout = res; 07868 f = ast_read(chan); 07869 if (!f) 07870 break; 07871 if (f->frametype == AST_FRAME_CONTROL) { 07872 if ((f->subclass == AST_CONTROL_BUSY) || 07873 (f->subclass == AST_CONTROL_CONGESTION) ) { 07874 ast_frfree(f); 07875 break; 07876 } 07877 } 07878 ast_frfree(f); 07879 } 07880 if (chan->_state == AST_STATE_UP) { 07881 if (!ast_strlen_zero(as->app)) { 07882 app = pbx_findapp(as->app); 07883 if (app) { 07884 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 07885 pbx_exec(chan, app, as->appdata); 07886 } else 07887 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 07888 } else { 07889 if (!ast_strlen_zero(as->context)) 07890 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 07891 if (!ast_strlen_zero(as->exten)) 07892 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 07893 if (as->priority > 0) 07894 chan->priority = as->priority; 07895 /* Run the PBX */ 07896 if (ast_pbx_run(chan)) { 07897 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 07898 } else { 07899 /* PBX will have taken care of this */ 07900 chan = NULL; 07901 } 07902 } 07903 } 07904 ast_free(as); 07905 if (chan) 07906 ast_hangup(chan); 07907 return NULL; 07908 }
| static void cli_match_char_tree | ( | struct match_char * | node, | |
| char * | prefix, | |||
| int | fd | |||
| ) | [static] |
Definition at line 1523 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().
01524 { 01525 char extenstr[40]; 01526 struct ast_str *my_prefix = ast_str_alloca(1024); 01527 01528 extenstr[0] = '\0'; 01529 01530 if (node && node->exten && node->exten) 01531 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01532 01533 if (strlen(node->x) > 1) { 01534 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01535 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01536 node->exten ? node->exten->exten : "", extenstr); 01537 } else { 01538 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01539 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01540 node->exten ? node->exten->exten : "", extenstr); 01541 } 01542 01543 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01544 01545 if (node->next_char) 01546 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01547 01548 if (node->alt_char) 01549 cli_match_char_tree(node->alt_char, prefix, fd); 01550 }
| 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.
| waittime | is in milliseconds |
| 0 | on timeout or done. | |
| -1 | on error. |
Definition at line 4188 of file pbx.c.
References ast_channel::_softhangup, ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeoutms, and ast_channel::pbx.
Referenced by __ast_pbx_run().
04189 { 04190 int digit; 04191 04192 buf[pos] = '\0'; /* make sure it is properly terminated */ 04193 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 04194 /* As long as we're willing to wait, and as long as it's not defined, 04195 keep reading digits until we can't possibly get a right answer anymore. */ 04196 digit = ast_waitfordigit(c, waittime); 04197 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 04198 c->_softhangup = 0; 04199 } else { 04200 if (!digit) /* No entry */ 04201 break; 04202 if (digit < 0) /* Error, maybe a hangup */ 04203 return -1; 04204 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 04205 buf[pos++] = digit; 04206 buf[pos] = '\0'; 04207 } 04208 waittime = c->pbx->dtimeoutms; 04209 } 04210 } 04211 return 0; 04212 }
| static int compare_char | ( | const void * | a, | |
| const void * | b | |||
| ) | [static] |
Definition at line 981 of file pbx.c.
Referenced by add_exten_to_pattern_tree().
| 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 5371 of file pbx.c.
References ast_get_extension_name(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_hint::exten.
Referenced by handle_show_hint().
05372 { 05373 struct ast_hint *hint; 05374 char *ret = NULL; 05375 int which = 0; 05376 int wordlen; 05377 05378 if (pos != 3) 05379 return NULL; 05380 05381 wordlen = strlen(word); 05382 05383 AST_RWLIST_RDLOCK(&hints); 05384 /* walk through all hints */ 05385 AST_RWLIST_TRAVERSE(&hints, hint, list) { 05386 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 05387 ret = ast_strdup(ast_get_extension_name(hint->exten)); 05388 break; 05389 } 05390 } 05391 AST_RWLIST_UNLOCK(&hints); 05392 05393 return ret; 05394 }
| static char* complete_show_dialplan_context | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 5567 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().
05569 { 05570 struct ast_context *c = NULL; 05571 char *ret = NULL; 05572 int which = 0; 05573 int wordlen; 05574 05575 /* we are do completion of [exten@]context on second position only */ 05576 if (pos != 2) 05577 return NULL; 05578 05579 ast_rdlock_contexts(); 05580 05581 wordlen = strlen(word); 05582 05583 /* walk through all contexts and return the n-th match */ 05584 while ( (c = ast_walk_contexts(c)) ) { 05585 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 05586 ret = ast_strdup(ast_get_context_name(c)); 05587 break; 05588 } 05589 } 05590 05591 ast_unlock_contexts(); 05592 05593 return ret; 05594 }
| static void context_merge | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| struct ast_context * | context, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 6539 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().
06540 { 06541 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 06542 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 06543 struct ast_hashtab_iter *exten_iter; 06544 struct ast_hashtab_iter *prio_iter; 06545 int insert_count = 0; 06546 int first = 1; 06547 06548 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 06549 the current registrar, and copy them to the new context. If the new context does not 06550 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 06551 only create the empty matching context if the old one meets the criteria */ 06552 06553 if (context->root_table) { 06554 exten_iter = ast_hashtab_start_traversal(context->root_table); 06555 while ((exten_item=ast_hashtab_next(exten_iter))) { 06556 if (new) { 06557 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 06558 } else { 06559 new_exten_item = NULL; 06560 } 06561 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 06562 while ((prio_item=ast_hashtab_next(prio_iter))) { 06563 int res1; 06564 char *dupdstr; 06565 06566 if (new_exten_item) { 06567 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 06568 } else { 06569 new_prio_item = NULL; 06570 } 06571 if (strcmp(prio_item->registrar,registrar) == 0) { 06572 continue; 06573 } 06574 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 06575 if (!new) { 06576 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 */ 06577 } 06578 06579 /* copy in the includes, switches, and ignorepats */ 06580 if (first) { /* but, only need to do this once */ 06581 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 06582 first = 0; 06583 } 06584 06585 if (!new) { 06586 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 06587 return; /* no sense continuing. */ 06588 } 06589 /* we will not replace existing entries in the new context with stuff from the old context. 06590 but, if this is because of some sort of registrar conflict, we ought to say something... */ 06591 06592 dupdstr = ast_strdup(prio_item->data); 06593 06594 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 06595 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 06596 if (!res1 && new_exten_item && new_prio_item){ 06597 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 06598 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 06599 } else { 06600 /* 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, 06601 and no double frees take place, either! */ 06602 insert_count++; 06603 } 06604 } 06605 ast_hashtab_end_traversal(prio_iter); 06606 } 06607 ast_hashtab_end_traversal(exten_iter); 06608 } 06609 06610 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 06611 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 06612 /* we could have given it the registrar of the other module who incremented the refcount, 06613 but that's not available, so we give it the registrar we know about */ 06614 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 06615 06616 /* copy in the includes, switches, and ignorepats */ 06617 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 06618 } 06619 }
| static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
| struct ast_context * | old, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 6506 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().
06507 { 06508 struct ast_include *i; 06509 struct ast_ignorepat *ip; 06510 struct ast_sw *sw; 06511 06512 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); 06513 /* copy in the includes, switches, and ignorepats */ 06514 /* walk through includes */ 06515 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 06516 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 06517 continue; /* not mine */ 06518 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 06519 } 06520 06521 /* walk through switches */ 06522 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 06523 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 06524 continue; /* not mine */ 06525 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)); 06526 } 06527 06528 /* walk thru ignorepats ... */ 06529 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 06530 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 06531 continue; /* not mine */ 06532 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 06533 } 06534 }
| static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2000 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().
02001 { 02002 struct ast_hashtab_iter *t1; 02003 struct ast_exten *e1; 02004 #ifdef NEED_DEBUG 02005 int biggest_bucket, resizes, numobjs, numbucks; 02006 02007 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name); 02008 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02009 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02010 numobjs, numbucks, biggest_bucket, resizes); 02011 #endif 02012 t1 = ast_hashtab_start_traversal(con->root_table); 02013 while ((e1 = ast_hashtab_next(t1))) { 02014 if (e1->exten) { 02015 add_exten_to_pattern_tree(con, e1, 0); 02016 } else { 02017 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02018 } 02019 } 02020 ast_hashtab_end_traversal(t1); 02021 }
| static void decrease_call_count | ( | void | ) | [static] |
Definition at line 4517 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().
04518 { 04519 ast_mutex_lock(&maxcalllock); 04520 if (countcalls > 0) 04521 countcalls--; 04522 ast_mutex_unlock(&maxcalllock); 04523 }
| static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 4525 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().
04526 { 04527 if (e->priority == PRIORITY_HINT) 04528 ast_remove_hint(e); 04529 04530 if (e->peer_table) 04531 ast_hashtab_destroy(e->peer_table,0); 04532 if (e->peer_label_table) 04533 ast_hashtab_destroy(e->peer_label_table, 0); 04534 if (e->datad) 04535 e->datad(e->data); 04536 ast_free(e); 04537 }
| static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2023 of file pbx.c.
References match_char::alt_char, match_char::exten, free, match_char::next_char, and match_char::x.
Referenced by __ast_internal_context_destroy().
02024 { 02025 /* destroy all the alternates */ 02026 if (pattern_tree->alt_char) { 02027 destroy_pattern_tree(pattern_tree->alt_char); 02028 pattern_tree->alt_char = 0; 02029 } 02030 /* destroy all the nexts */ 02031 if (pattern_tree->next_char) { 02032 destroy_pattern_tree(pattern_tree->next_char); 02033 pattern_tree->next_char = 0; 02034 } 02035 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02036 if (pattern_tree->x) { 02037 free(pattern_tree->x); 02038 } 02039 free(pattern_tree); 02040 }
| static void device_state_cb | ( | const struct ast_event * | event, | |
| void * | unused | |||
| ) | [static] |
Definition at line 9283 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().
09284 { 09285 const char *device; 09286 struct statechange *sc; 09287 09288 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 09289 if (ast_strlen_zero(device)) { 09290 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 09291 return; 09292 } 09293 09294 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 09295 return; 09296 strcpy(sc->dev, device); 09297 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 09298 ast_free(sc); 09299 } 09300 }
| static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 2983 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
02984 { 02985 struct pbx_exception *exception = data; 02986 ast_string_field_free_memory(exception); 02987 ast_free(exception); 02988 }
| static int ext_cmp | ( | const char * | a, | |
| const char * | b | |||
| ) | [static] |
the full routine to compare extensions in rules.
Definition at line 2176 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02177 { 02178 /* make sure non-patterns come first. 02179 * If a is not a pattern, it either comes first or 02180 * we do a more complex pattern comparison. 02181 */ 02182 int ret = 0; 02183 02184 if (a[0] != '_') 02185 return (b[0] == '_') ? -1 : strcmp(a, b); 02186 02187 /* Now we know a is a pattern; if b is not, a comes first */ 02188 if (b[0] != '_') 02189 return 1; 02190 02191 /* ok we need full pattern sorting routine. 02192 * skip past the underscores */ 02193 ++a; ++b; 02194 do { 02195 unsigned char bitwise[2][32] = { { 0, } }; 02196 ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]); 02197 if (ret == 0) { 02198 /* Are the classes different, even though they score the same? */ 02199 ret = memcmp(bitwise[0], bitwise[1], 32); 02200 } 02201 } while (!ret && a && b); 02202 if (ret == 0) { 02203 return 0; 02204 } else { 02205 return (ret > 0) ? 1 : -1; 02206 } 02207 }
| static int ext_cmp1 | ( | const char ** | p, | |
| unsigned char * | bitwise | |||
| ) | [static] |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
ext_cmp1 compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, while bit 8-15 are the cardinality of the set minus 1. This way more specific patterns (smaller cardinality) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x000xx one character, xx 0x0yyxx yy character set starting with xx 0x10000 '.' (one or more of anything) 0x20000 '!' (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 equivalent to NUL. 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 2096 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
02097 { 02098 int c, cmin = 0xff, count = 0; 02099 const char *end; 02100 02101 /* load value and advance pointer */ 02102 c = *(*p)++; 02103 02104 /* always return unless we have a set of chars */ 02105 switch (toupper(c)) { 02106 default: /* ordinary character */ 02107 bitwise[c / 8] = 1 << (c % 8); 02108 return 0x0100 | (c & 0xff); 02109 02110 case 'N': /* 2..9 */ 02111 bitwise[6] = 0xfc; 02112 bitwise[7] = 0x03; 02113 return 0x0800 | '2'; 02114 02115 case 'X': /* 0..9 */ 02116 bitwise[6] = 0xff; 02117 bitwise[7] = 0x03; 02118 return 0x0A00 | '0'; 02119 02120 case 'Z': /* 1..9 */ 02121 bitwise[6] = 0xfe; 02122 bitwise[7] = 0x03; 02123 return 0x0900 | '1'; 02124 02125 case '.': /* wildcard */ 02126 return 0x10000; 02127 02128 case '!': /* earlymatch */ 02129 return 0x20000; /* less specific than NULL */ 02130 02131 case '\0': /* empty string */ 02132 *p = NULL; 02133 return 0x30000; 02134 02135 case '[': /* pattern */ 02136 break; 02137 } 02138 /* locate end of set */ 02139 end = strchr(*p, ']'); 02140 02141 if (end == NULL) { 02142 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02143 return 0x40000; /* XXX make this entry go last... */ 02144 } 02145 02146 for (; *p < end ; (*p)++) { 02147 unsigned char c1, c2; /* first-last char in range */ 02148 c1 = (unsigned char)((*p)[0]); 02149 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02150 c2 = (unsigned char)((*p)[2]); 02151 *p += 2; /* skip a total of 3 chars */ 02152 } else { /* individual character */ 02153 c2 = c1; 02154 } 02155 if (c1 < cmin) { 02156 cmin = c1; 02157 } 02158 for (; c1 <= c2; c1++) { 02159 unsigned char mask = 1 << (c1 % 8); 02160 /*!\note If two patterns score the same, the one with the lowest 02161 * ascii values will compare as coming first. */ 02162 /* Flag the character as included (used) and count it. */ 02163 if (!(bitwise[ c1 / 8 ] & mask)) { 02164 bitwise[ c1 / 8 ] |= mask; 02165 count += 0x100; 02166 } 02167 } 02168 } 02169 (*p)++; 02170 return count == 0 ? 0x30000 : (count | cmin); 02171 }
| static int ext_strncpy | ( | char * | dst, | |
| const char * | src, | |||
| int | len | |||
| ) | [static] |
copy a string skipping whitespace
Definition at line 7411 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
07412 { 07413 int count = 0; 07414 int insquares = 0; 07415 07416 while (*src && (count < len - 1)) { 07417 if (*src == '[') { 07418 insquares = 1; 07419 } else if (*src == ']') { 07420 insquares = 0; 07421 } else if (*src == ' ' && !insquares) { 07422 src++; 07423 continue; 07424 } 07425 *dst = *src; 07426 dst++; 07427 src++; 07428 count++; 07429 } 07430 *dst = '\0'; 07431 07432 return count; 07433 }
| static int extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 2389 of file pbx.c.
References _extension_match_core(), ast_add_profile(), and ast_mark().
Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().
02390 { 02391 int i; 02392 static int prof_id = -2; /* marker for 'unallocated' id */ 02393 if (prof_id == -2) { 02394 prof_id = ast_add_profile("ext_match", 0); 02395 } 02396 ast_mark(prof_id, 1); 02397 i = _extension_match_core(pattern, data, mode); 02398 ast_mark(prof_id, 0); 02399 return i; 02400 }
| 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 4641 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
04642 { 04643 struct ast_context *c = NULL; 04644 struct fake_context item; 04645 04646 ast_copy_string(item.name, context, sizeof(item.name)); 04647 04648 c = ast_hashtab_lookup(contexts_table,&item); 04649 04650 return c; 04651 }
| 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 4658 of file pbx.c.
References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_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_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
04659 { 04660 struct ast_context *c = NULL; 04661 struct fake_context item; 04662 04663 ast_copy_string(item.name, context, sizeof(item.name)); 04664 04665 ast_rdlock_contexts(); 04666 c = ast_hashtab_lookup(contexts_table,&item); 04667 04668 #ifdef NOTNOW 04669 04670 while ( (c = ast_walk_contexts(c)) ) { 04671 if (!strcmp(ast_get_context_name(c), context)) 04672 return c; 04673 } 04674 #endif 04675 if (!c) 04676 ast_unlock_contexts(); 04677 04678 return c; 04679 }
| 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 3338 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
03339 { 03340 char *args = strchr(function, '('); 03341 03342 if (!args) { 03343 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 03344 } else { 03345 char *p; 03346 *args++ = '\0'; 03347 if ((p = strrchr(args, ')'))) { 03348 *p = '\0'; 03349 } else { 03350 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 03351 } 03352 } 03353 return args; 03354 }
| static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1552 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.
01553 { 01554 /* find the exten at the end of the rope */ 01555 struct match_char *node2 = node; 01556 01557 for (node2 = node; node2; node2 = node2->next_char) { 01558 if (node2->exten) { 01559 #ifdef NEED_DEBUG_HERE 01560 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01561 #endif 01562 return node2->exten; 01563 } 01564 } 01565 #ifdef NEED_DEBUG_HERE 01566 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01567 #endif 01568 return 0; 01569 }
| static unsigned get_range | ( | char * | src, | |
| int | max, | |||
| 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 6807 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and lookup_name().
Referenced by ast_build_timing().
06808 { 06809 int start, end; /* start and ending position */ 06810 unsigned int mask = 0; 06811 char *part; 06812 06813 /* Check for whole range */ 06814 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 06815 return (1 << max) - 1; 06816 } 06817 06818 while ((part = strsep(&src, "&"))) { 06819 /* Get start and ending position */ 06820 char *endpart = strchr(part, '-'); 06821 if (endpart) { 06822 *endpart++ = '\0'; 06823 } 06824 /* Find the start */ 06825 if ((start = lookup_name(part, names, max)) < 0) { 06826 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 06827 continue; 06828 } 06829 if (endpart) { /* find end of range */ 06830 if ((end = lookup_name(endpart, names, max)) < 0) { 06831 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 06832 continue; 06833 } 06834 } else { 06835 end = start; 06836 } 06837 /* Fill the mask. Remember that ranges are cyclic */ 06838 mask |= (1 << end); /* initialize with last element */ 06839 while (start != end) { 06840 mask |= (1 << start); 06841 if (++start >= max) { 06842 start = 0; 06843 } 06844 } 06845 } 06846 return mask; 06847 }
| 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 6850 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
06851 { 06852 char *endpart, *part; 06853 int x; 06854 int st_h, st_m; 06855 int endh, endm; 06856 int minute_start, minute_end; 06857 06858 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 06859 memset(i->minmask, 0, sizeof(i->minmask)); 06860 06861 /* 1-minute per bit */ 06862 /* Star is all times */ 06863 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 06864 /* 48, because each hour takes 2 integers; 30 bits each */ 06865 for (x = 0; x < 48; x++) { 06866 i->minmask[x] = 0x3fffffff; /* 30 bits */ 06867 } 06868 return; 06869 } 06870 /* Otherwise expect a range */ 06871 while ((part = strsep(×, "&"))) { 06872 if (!(endpart = strchr(part, '-'))) { 06873 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 06874 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 06875 continue; 06876 } 06877 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 06878 continue; 06879 } 06880 *endpart++ = '\0'; 06881 /* why skip non digits? Mostly to skip spaces */ 06882 while (*endpart && !isdigit(*endpart)) { 06883 endpart++; 06884 } 06885 if (!*endpart) { 06886 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 06887 continue; 06888 } 06889 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 06890 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 06891 continue; 06892 } 06893 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 06894 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 06895 continue; 06896 } 06897 minute_start = st_h * 60 + st_m; 06898 minute_end = endh * 60 + endm; 06899 /* Go through the time and enable each appropriate bit */ 06900 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 06901 i->minmask[x / 30] |= (1 << (x % 30)); 06902 } 06903 /* Do the last one */ 06904 i->minmask[x / 30] |= (1 << (x % 30)); 06905 } 06906 /* All done */ 06907 return; 06908 }
| static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Send ack once.
Definition at line 5892 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, 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, 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.
05893 { 05894 char *exten = NULL, *context = NULL; 05895 /* Variables used for different counters */ 05896 struct dialplan_counters counters; 05897 const char *incstack[AST_PBX_MAX_STACK]; 05898 05899 switch (cmd) { 05900 case CLI_INIT: 05901 e->command = "dialplan debug"; 05902 e->usage = 05903 "Usage: dialplan debug [context]\n" 05904 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 05905 return NULL; 05906 case CLI_GENERATE: 05907 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05908 } 05909 05910 memset(&counters, 0, sizeof(counters)); 05911 05912 if (a->argc != 2 && a->argc != 3) 05913 return CLI_SHOWUSAGE; 05914 05915 /* we obtain [exten@]context? if yes, split them ... */ 05916 /* note: we ignore the exten totally here .... */ 05917 if (a->argc == 3) { 05918 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05919 context = ast_strdupa(a->argv[2]); 05920 exten = strsep(&context, "@"); 05921 /* change empty strings to NULL */ 05922 if (ast_strlen_zero(exten)) 05923 exten = NULL; 05924 } else { /* no '@' char, only context given */ 05925 context = a->argv[2]; 05926 } 05927 if (ast_strlen_zero(context)) 05928 context = NULL; 05929 } 05930 /* else Show complete dial plan, context and exten are NULL */ 05931 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05932 05933 /* check for input failure and throw some error messages */ 05934 if (context && !counters.context_existence) { 05935 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05936 return CLI_FAILURE; 05937 } 05938 05939 05940 ast_cli(a->fd,"-= %d %s. =-\n", 05941 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05942 05943 /* everything ok */ 05944 return CLI_SUCCESS; 05945 }
| static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6269 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), 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.
06270 { 06271 struct ast_channel *chan; 06272 const char *chan_name, *var_name, *var_value; 06273 06274 switch (cmd) { 06275 case CLI_INIT: 06276 e->command = "dialplan set chanvar"; 06277 e->usage = 06278 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 06279 " Set channel variable <varname> to <value>\n"; 06280 return NULL; 06281 case CLI_GENERATE: 06282 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 06283 } 06284 06285 if (a->argc != e->args + 3) 06286 return CLI_SHOWUSAGE; 06287 06288 chan_name = a->argv[e->args]; 06289 var_name = a->argv[e->args + 1]; 06290 var_value = a->argv[e->args + 2]; 06291 06292 if (!(chan = ast_get_channel_by_name_locked(chan_name))) { 06293 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 06294 return CLI_FAILURE; 06295 } 06296 06297 pbx_builtin_setvar_helper(chan, var_name, var_value); 06298 ast_channel_unlock(chan); 06299 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 06300 06301 return CLI_SUCCESS; 06302 }
| static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6304 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.
06305 { 06306 int oldval = 0; 06307 06308 switch (cmd) { 06309 case CLI_INIT: 06310 e->command = "dialplan set extenpatternmatchnew true"; 06311 e->usage = 06312 "Usage: dialplan set extenpatternmatchnew true|false\n" 06313 " Use the NEW extension pattern matching algorithm, true or false.\n"; 06314 return NULL; 06315 case CLI_GENERATE: 06316 return NULL; 06317 } 06318 06319 if (a->argc != 4) 06320 return CLI_SHOWUSAGE; 06321 06322 oldval = pbx_set_extenpatternmatchnew(1); 06323 06324 if (oldval) 06325 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 06326 else 06327 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 06328 06329 return CLI_SUCCESS; 06330 }
| static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6247 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.
06248 { 06249 switch (cmd) { 06250 case CLI_INIT: 06251 e->command = "dialplan set global"; 06252 e->usage = 06253 "Usage: dialplan set global <name> <value>\n" 06254 " Set global dialplan variable <name> to <value>\n"; 06255 return NULL; 06256 case CLI_GENERATE: 06257 return NULL; 06258 } 06259 06260 if (a->argc != e->args + 2) 06261 return CLI_SHOWUSAGE; 06262 06263 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 06264 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 06265 06266 return CLI_SUCCESS; 06267 }
| static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5261 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.
05262 { 05263 struct ast_app *aa; 05264 int app, no_registered_app = 1; 05265 char *ret = NULL; 05266 int which = 0; 05267 int wordlen; 05268 05269 switch (cmd) { 05270 case CLI_INIT: 05271 e->command = "core show application"; 05272 e->usage = 05273 "Usage: core show application <application> [<application> [<application> [...]]]\n" 05274 " Describes a particular application.\n"; 05275 return NULL; 05276 case CLI_GENERATE: 05277 /* 05278 * There is a possibility to show informations about more than one 05279 * application at one time. You can type 'show application Dial Echo' and 05280 * you will see informations about these two applications ... 05281 */ 05282 wordlen = strlen(a->word); 05283 /* return the n-th [partial] matching entry */ 05284 AST_RWLIST_RDLOCK(&apps); 05285 AST_RWLIST_TRAVERSE(&apps, aa, list) { 05286 if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) { 05287 ret = ast_strdup(aa->name); 05288 break; 05289 } 05290 } 05291 AST_RWLIST_UNLOCK(&apps); 05292 05293 return ret; 05294 } 05295 05296 if (a->argc < 4) { 05297 return CLI_SHOWUSAGE; 05298 } 05299 05300 AST_RWLIST_RDLOCK(&apps); 05301 AST_RWLIST_TRAVERSE(&apps, aa, list) { 05302 /* Check for each app that was supplied as an argument */ 05303 for (app = 3; app < a->argc; app++) { 05304 if (strcasecmp(aa->name, a->argv[app])) { 05305 continue; 05306 } 05307 05308 /* We found it! */ 05309 no_registered_app = 0; 05310 05311 print_app_docs(aa, a->fd); 05312 } 05313 } 05314 AST_RWLIST_UNLOCK(&apps); 05315 05316 /* we found at least one app? no? */ 05317 if (no_registered_app) { 05318 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 05319 return CLI_FAILURE; 05320 } 05321 05322 return CLI_SUCCESS; 05323 }
| static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5481 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.
05482 { 05483 struct ast_app *aa; 05484 int like = 0, describing = 0; 05485 int total_match = 0; /* Number of matches in like clause */ 05486 int total_apps = 0; /* Number of apps registered */ 05487 static char* choices[] = { "like", "describing", NULL }; 05488 05489 switch (cmd) { 05490 case CLI_INIT: 05491 e->command = "core show applications [like|describing]"; 05492 e->usage = 05493 "Usage: core show applications [{like|describing} <text>]\n" 05494 " List applications which are currently available.\n" 05495 " If 'like', <text> will be a substring of the app name\n" 05496 " If 'describing', <text> will be a substring of the description\n"; 05497 return NULL; 05498 case CLI_GENERATE: 05499 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 05500 } 05501 05502 AST_RWLIST_RDLOCK(&apps); 05503 05504 if (AST_RWLIST_EMPTY(&apps)) { 05505 ast_cli(a->fd, "There are no registered applications\n"); 05506 AST_RWLIST_UNLOCK(&apps); 05507 return CLI_SUCCESS; 05508 } 05509 05510 /* core list applications like <keyword> */ 05511 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 05512 like = 1; 05513 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 05514 describing = 1; 05515 } 05516 05517 /* core list applications describing <keyword1> [<keyword2>] [...] */ 05518 if ((!like) && (!describing)) { 05519 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 05520 } else { 05521 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 05522 } 05523 05524 AST_RWLIST_TRAVERSE(&apps, aa, list) { 05525 int printapp = 0; 05526 total_apps++; 05527 if (like) { 05528 if (strcasestr(aa->name, a->argv[4])) { 05529 printapp = 1; 05530 total_match++; 05531 } 05532 } else if (describing) { 05533 if (aa->description) { 05534 /* Match all words on command line */ 05535 int i; 05536 printapp = 1; 05537 for (i = 4; i < a->argc; i++) { 05538 if (!strcasestr(aa->description, a->argv[i])) { 05539 printapp = 0; 05540 } else { 05541 total_match++; 05542 } 05543 } 05544 } 05545 } else { 05546 printapp = 1; 05547 } 05548 05549 if (printapp) { 05550 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 05551 } 05552 } 05553 if ((!like) && (!describing)) { 05554 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 05555 } else { 05556 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 05557 } 05558 05559 AST_RWLIST_UNLOCK(&apps); 05560 05561 return CLI_SUCCESS; 05562 }
| 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 6215 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), 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.
06216 { 06217 struct ast_channel *chan = NULL; 06218 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 06219 06220 switch (cmd) { 06221 case CLI_INIT: 06222 e->command = "dialplan show chanvar"; 06223 e->usage = 06224 "Usage: dialplan show chanvar <channel>\n" 06225 " List current channel variables and their values\n"; 06226 return NULL; 06227 case CLI_GENERATE: 06228 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 06229 } 06230 06231 if (a->argc != e->args + 1) 06232 return CLI_SHOWUSAGE; 06233 06234 if (!(chan = ast_get_channel_by_name_locked(a->argv[e->args]))) { 06235 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 06236 return CLI_FAILURE; 06237 } 06238 06239 pbx_builtin_serialize_variables(chan, &vars); 06240 if (ast_str_strlen(vars)) { 06241 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 06242 } 06243 ast_channel_unlock(chan); 06244 return CLI_SUCCESS; 06245 }
| static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5825 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, 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, 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.
05826 { 05827 char *exten = NULL, *context = NULL; 05828 /* Variables used for different counters */ 05829 struct dialplan_counters counters; 05830 const char *incstack[AST_PBX_MAX_STACK]; 05831 05832 switch (cmd) { 05833 case CLI_INIT: 05834 e->command = "dialplan show"; 05835 e->usage = 05836 "Usage: dialplan show [[exten@]context]\n" 05837 " Show dialplan\n"; 05838 return NULL; 05839 case CLI_GENERATE: 05840 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05841 } 05842 05843 memset(&counters, 0, sizeof(counters)); 05844 05845 if (a->argc != 2 && a->argc != 3) 05846 return CLI_SHOWUSAGE; 05847 05848 /* we obtain [exten@]context? if yes, split them ... */ 05849 if (a->argc == 3) { 05850 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05851 context = ast_strdupa(a->argv[2]); 05852 exten = strsep(&context, "@"); 05853 /* change empty strings to NULL */ 05854 if (ast_strlen_zero(exten)) 05855 exten = NULL; 05856 } else { /* no '@' char, only context given */ 05857 context = a->argv[2]; 05858 } 05859 if (ast_strlen_zero(context)) 05860 context = NULL; 05861 } 05862 /* else Show complete dial plan, context and exten are NULL */ 05863 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05864 05865 /* check for input failure and throw some error messages */ 05866 if (context && !counters.context_existence) { 05867 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05868 return CLI_FAILURE; 05869 } 05870 05871 if (exten && !counters.extension_existence) { 05872 if (context) 05873 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 05874 exten, context); 05875 else 05876 ast_cli(a->fd, 05877 "There is no existence of '%s' extension in all contexts\n", 05878 exten); 05879 return CLI_FAILURE; 05880 } 05881 05882 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 05883 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 05884 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 05885 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05886 05887 /* everything ok */ 05888 return CLI_SUCCESS; 05889 }
| static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3095 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_custom_function::arguments, 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::desc, description, ast_custom_function::docsrc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, S_OR, ast_custom_function::seealso, ast_custom_function::synopsis, synopsis, ast_custom_function::syntax, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
03096 { 03097 struct ast_custom_function *acf; 03098 /* Maximum number of characters added by terminal coloring is 22 */ 03099 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03100 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03101 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03102 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03103 char *ret = NULL; 03104 int which = 0; 03105 int wordlen; 03106 03107 switch (cmd) { 03108 case CLI_INIT: 03109 e->command = "core show function"; 03110 e->usage = 03111 "Usage: core show function <function>\n" 03112 " Describe a particular dialplan function.\n"; 03113 return NULL; 03114 case CLI_GENERATE: 03115 wordlen = strlen(a->word); 03116 /* case-insensitive for convenience in this 'complete' function */ 03117 AST_RWLIST_RDLOCK(&acf_root); 03118 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03119 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03120 ret = ast_strdup(acf->name); 03121 break; 03122 } 03123 } 03124 AST_RWLIST_UNLOCK(&acf_root); 03125 03126 return ret; 03127 } 03128 03129 if (a->argc < 4) { 03130 return CLI_SHOWUSAGE; 03131 } 03132 03133 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03134 ast_cli(a->fd, "No function by that name registered.\n"); 03135 return CLI_FAILURE; 03136 } 03137 03138 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03139 if (!(syntax = ast_malloc(syntax_size))) { 03140 ast_cli(a->fd, "Memory allocation failure!\n"); 03141 return CLI_FAILURE; 03142 } 03143 03144 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03145 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03146 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03147 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03148 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03149 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03150 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03151 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03152 #ifdef AST_XML_DOCS 03153 if (acf->docsrc == AST_XML_DOC) { 03154 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03155 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03156 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03157 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03158 } else 03159 #endif 03160 { 03161 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03162 synopsis = ast_malloc(synopsis_size); 03163 03164 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03165 description = ast_malloc(description_size); 03166 03167 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03168 arguments = ast_malloc(arguments_size); 03169 03170 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03171 seealso = ast_malloc(seealso_size); 03172 03173 /* check allocated memory. */ 03174 if (!synopsis || !description || !arguments || !seealso) { 03175 ast_free(synopsis); 03176 ast_free(description); 03177 ast_free(arguments); 03178 ast_free(seealso); 03179 ast_free(syntax); 03180 return CLI_FAILURE; 03181 } 03182 03183 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03184 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03185 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03186 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03187 } 03188 03189 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03190 infotitle, syntitle, synopsis, destitle, description, 03191 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03192 03193 ast_free(arguments); 03194 ast_free(synopsis); 03195 ast_free(description); 03196 ast_free(seealso); 03197 ast_free(syntax); 03198 03199 return CLI_SUCCESS; 03200 }
| static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3053 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, ast_custom_function::synopsis, ast_custom_function::syntax, and ast_cli_entry::usage.
03054 { 03055 struct ast_custom_function *acf; 03056 int count_acf = 0; 03057 int like = 0; 03058 03059 switch (cmd) { 03060 case CLI_INIT: 03061 e->command = "core show functions [like]"; 03062 e->usage = 03063 "Usage: core show functions [like <text>]\n" 03064 " List builtin functions, optionally only those matching a given string\n"; 03065 return NULL; 03066 case CLI_GENERATE: 03067 return NULL; 03068 } 03069 03070 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03071 like = 1; 03072 } else if (a->argc != 3) { 03073 return CLI_SHOWUSAGE; 03074 } 03075 03076 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03077 03078 AST_RWLIST_RDLOCK(&acf_root); 03079 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03080 if (!like || strstr(acf->name, a->argv[4])) { 03081 count_acf++; 03082 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03083 S_OR(acf->name, ""), 03084 S_OR(acf->syntax, ""), 03085 S_OR(acf->synopsis, "")); 03086 } 03087 } 03088 AST_RWLIST_UNLOCK(&acf_root); 03089 03090 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03091 03092 return CLI_SUCCESS; 03093 }
| 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 6157 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_var_t::entries, ast_cli_args::fd, globals, globalslock, and ast_cli_entry::usage.
06158 { 06159 int i = 0; 06160 struct ast_var_t *newvariable; 06161 06162 switch (cmd) { 06163 case CLI_INIT: 06164 e->command = "dialplan show globals"; 06165 e->usage = 06166 "Usage: dialplan show globals\n" 06167 " List current global dialplan variables and their values\n"; 06168 return NULL; 06169 case CLI_GENERATE: 06170 return NULL; 06171 } 06172 06173 ast_rwlock_rdlock(&globalslock); 06174 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 06175 i++; 06176 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 06177 } 06178 ast_rwlock_unlock(&globalslock); 06179 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 06180 06181 return CLI_SUCCESS; 06182 }
| 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 5397 of file pbx.c.
References 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_LIST_TRAVERSE, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, 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, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, num, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
05398 { 05399 struct ast_hint *hint; 05400 int watchers; 05401 int num = 0, extenlen; 05402 struct ast_state_cb *watcher; 05403 05404 switch (cmd) { 05405 case CLI_INIT: 05406 e->command = "core show hint"; 05407 e->usage = 05408 "Usage: core show hint <exten>\n" 05409 " List registered hint\n"; 05410 return NULL; 05411 case CLI_GENERATE: 05412 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 05413 } 05414 05415 if (a->argc < 4) 05416 return CLI_SHOWUSAGE; 05417 05418 AST_RWLIST_RDLOCK(&hints); 05419 if (AST_RWLIST_EMPTY(&hints)) { 05420 ast_cli(a->fd, "There are no registered dialplan hints\n"); 05421 AST_RWLIST_UNLOCK(&hints); 05422 return CLI_SUCCESS; 05423 } 05424 extenlen = strlen(a->argv[3]); 05425 AST_RWLIST_TRAVERSE(&hints, hint, list) { 05426 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 05427 watchers = 0; 05428 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 05429 watchers++; 05430 } 05431 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 05432 ast_get_extension_name(hint->exten), 05433 ast_get_context_name(ast_get_extension_context(hint->exten)), 05434 ast_get_extension_app(hint->exten), 05435 ast_extension_state2str(hint->laststate), watchers); 05436 num++; 05437 } 05438 } 05439 AST_RWLIST_UNLOCK(&hints); 05440 if (!num) 05441 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 05442 else 05443 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 05444 return CLI_SUCCESS; 05445 }
| 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 5326 of file pbx.c.
References ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_LIST_TRAVERSE, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, ast_hint::laststate, num, and ast_cli_entry::usage.
05327 { 05328 struct ast_hint *hint; 05329 int num = 0; 05330 int watchers; 05331 struct ast_state_cb *watcher; 05332 05333 switch (cmd) { 05334 case CLI_INIT: 05335 e->command = "core show hints"; 05336 e->usage = 05337 "Usage: core show hints\n" 05338 " List registered hints\n"; 05339 return NULL; 05340 case CLI_GENERATE: 05341 return NULL; 05342 } 05343 05344 AST_RWLIST_RDLOCK(&hints); 05345 if (AST_RWLIST_EMPTY(&hints)) { 05346 ast_cli(a->fd, "There are no registered dialplan hints\n"); 05347 AST_RWLIST_UNLOCK(&hints); 05348 return CLI_SUCCESS; 05349 } 05350 /* ... we have hints ... */ 05351 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 05352 AST_RWLIST_TRAVERSE(&hints, hint, list) { 05353 watchers = 0; 05354 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 05355 watchers++; 05356 } 05357 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 05358 ast_get_extension_name(hint->exten), 05359 ast_get_context_name(ast_get_extension_context(hint->exten)), 05360 ast_get_extension_app(hint->exten), 05361 ast_extension_state2str(hint->laststate), watchers); 05362 num++; 05363 } 05364 ast_cli(a->fd, "----------------\n"); 05365 ast_cli(a->fd, "- %d hints registered\n", num); 05366 AST_RWLIST_UNLOCK(&hints); 05367 return CLI_SUCCESS; 05368 }
| 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 5449 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.
05450 { 05451 struct ast_switch *sw; 05452 05453 switch (cmd) { 05454 case CLI_INIT: 05455 e->command = "core show switches"; 05456 e->usage = 05457 "Usage: core show switches\n" 05458 " List registered switches\n"; 05459 return NULL; 05460 case CLI_GENERATE: 05461 return NULL; 05462 } 05463 05464 AST_RWLIST_RDLOCK(&switches); 05465 05466 if (AST_RWLIST_EMPTY(&switches)) { 05467 AST_RWLIST_UNLOCK(&switches); 05468 ast_cli(a->fd, "There are no registered alternative switches\n"); 05469 return CLI_SUCCESS; 05470 } 05471 05472 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 05473 AST_RWLIST_TRAVERSE(&switches, sw, list) 05474 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 05475 05476 AST_RWLIST_UNLOCK(&switches); 05477 05478 return CLI_SUCCESS; 05479 }
| static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 3843 of file pbx.c.
References ast_copy_string(), ast_extension_state2(), ast_free, ast_get_extension_app(), AST_LIST_TRAVERSE, AST_MAX_EXTENSION, ast_rdlock_contexts(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_unlock_contexts(), buf, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, statechange::dev, ast_exten::exten, ast_hint::exten, ast_hint::laststate, ast_context::name, ast_exten::parent, and parse().
Referenced by device_state_cb().
03844 { 03845 struct ast_hint *hint; 03846 struct statechange *sc = datap; 03847 03848 ast_rdlock_contexts(); 03849 AST_RWLIST_RDLOCK(&hints); 03850 03851 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03852 struct ast_state_cb *cblist; 03853 char buf[AST_MAX_EXTENSION]; 03854 char *parse = buf; 03855 char *cur; 03856 int state; 03857 03858 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 03859 while ( (cur = strsep(&parse, "&")) ) { 03860 if (!strcasecmp(cur, sc->dev)) { 03861 break; 03862 } 03863 } 03864 if (!cur) { 03865 continue; 03866 } 03867 03868 /* Get device state for this hint */ 03869 state = ast_extension_state2(hint->exten); 03870 03871 if ((state == -1) || (state == hint->laststate)) { 03872 continue; 03873 } 03874 03875 /* Device state changed since last check - notify the watchers */ 03876 03877 /* For general callbacks */ 03878 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03879 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03880 } 03881 03882 /* For extension callbacks */ 03883 AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) { 03884 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03885 } 03886 03887 hint->laststate = state; /* record we saw the change */ 03888 } 03889 AST_RWLIST_UNLOCK(&hints); 03890 ast_unlock_contexts(); 03891 ast_free(sc); 03892 return 0; 03893 }
| static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6332 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.
06333 { 06334 int oldval = 0; 06335 06336 switch (cmd) { 06337 case CLI_INIT: 06338 e->command = "dialplan set extenpatternmatchnew false"; 06339 e->usage = 06340 "Usage: dialplan set extenpatternmatchnew true|false\n" 06341 " Use the NEW extension pattern matching algorithm, true or false.\n"; 06342 return NULL; 06343 case CLI_GENERATE: 06344 return NULL; 06345 } 06346 06347 if (a->argc != 4) 06348 return CLI_SHOWUSAGE; 06349 06350 oldval = pbx_set_extenpatternmatchnew(0); 06351 06352 if (!oldval) 06353 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 06354 else 06355 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 06356 06357 return CLI_SUCCESS; 06358 }
| 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 1023 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 1004 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01005 { 01006 const struct ast_exten *ac = ah_a; 01007 const struct ast_exten *bc = ah_b; 01008 int x = strcmp(ac->exten, bc->exten); 01009 if (x) { /* if exten names are diff, then return */ 01010 return x; 01011 } 01012 01013 /* but if they are the same, do the cidmatch values match? */ 01014 if (ac->matchcid && bc->matchcid) { 01015 return strcmp(ac->cidmatch,bc->cidmatch); 01016 } else if (!ac->matchcid && !bc->matchcid) { 01017 return 0; /* if there's no matchcid on either side, then this is a match */ 01018 } else { 01019 return 1; /* if there's matchcid on one but not the other, they are different */ 01020 } 01021 }
| static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1043 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01044 { 01045 const struct ast_exten *ac = obj; 01046 unsigned int x = ast_hashtab_hash_string(ac->exten); 01047 unsigned int y = 0; 01048 if (ac->matchcid) 01049 y = ast_hashtab_hash_string(ac->cidmatch); 01050 return x+y; 01051 }
| static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1059 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01060 { 01061 const struct ast_exten *ac = obj; 01062 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01063 }
| static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1053 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01054 { 01055 const struct ast_exten *ac = obj; 01056 return ast_hashtab_hash_int(ac->priority); 01057 }
| static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1391 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01392 { 01393 if (!i->hastime) 01394 return 1; 01395 01396 return ast_check_timing(&(i->timing)); 01397 }
| 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 4470 of file pbx.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), countcalls, LOG_WARNING, maxcalllock, ast_channel::name, option_maxcalls, option_maxload, option_minmemfree, and totalcalls.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
04471 { 04472 int failed = 0; 04473 double curloadavg; 04474 #if defined(HAVE_SYSINFO) 04475 long curfreemem; 04476 struct sysinfo sys_info; 04477 #endif 04478 04479 ast_mutex_lock(&maxcalllock); 04480 if (option_maxcalls) { 04481 if (countcalls >= option_maxcalls) { 04482 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 04483 failed = -1; 04484 } 04485 } 04486 if (option_maxload) { 04487 getloadavg(&curloadavg, 1); 04488 if (curloadavg >= option_maxload) { 04489 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 04490 failed = -1; 04491 } 04492 } 04493 #if defined(HAVE_SYSINFO) 04494 if (option_minmemfree) { 04495 if (!sysinfo(&sys_info)) { 04496 /* make sure that the free system memory is above the configured low watermark 04497 * convert the amount of freeram from mem_units to MB */ 04498 curfreemem = sys_info.freeram / sys_info.mem_unit; 04499 curfreemem /= 1024 * 1024; 04500 if (curfreemem < option_minmemfree) { 04501 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 04502 failed = -1; 04503 } 04504 } 04505 } 04506 #endif 04507 04508 if (!failed) { 04509 countcalls++; 04510 totalcalls++; 04511 } 04512 ast_mutex_unlock(&maxcalllock); 04513 04514 return failed; 04515 }
| static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
| struct match_char * | node | |||
| ) | [static] |
Definition at line 1799 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01800 { 01801 struct match_char *curr, *lcurr; 01802 01803 /* insert node into the tree at "current", so the alt_char list from current is 01804 sorted in increasing value as you go to the leaves */ 01805 if (!(*parent_ptr)) { 01806 *parent_ptr = node; 01807 } else { 01808 if ((*parent_ptr)->specificity > node->specificity) { 01809 /* insert at head */ 01810 node->alt_char = (*parent_ptr); 01811 *parent_ptr = node; 01812 } else { 01813 lcurr = *parent_ptr; 01814 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01815 if (curr->specificity > node->specificity) { 01816 node->alt_char = curr; 01817 lcurr->alt_char = node; 01818 break; 01819 } 01820 lcurr = curr; 01821 } 01822 if (!curr) { 01823 lcurr->alt_char = node; 01824 } 01825 } 01826 } 01827 }
| int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 9302 of file pbx.c.
References __ast_custom_function_register(), ARRAY_LEN, ast_cli_register_multiple(), AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register2(), ast_register_application2(), 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(), mandescr_show_dialplan, and pbx_cli.
Referenced by main().
09303 { 09304 int x; 09305 09306 /* Initialize the PBX */ 09307 ast_verb(1, "Asterisk PBX Core Initializing\n"); 09308 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 09309 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 09310 } 09311 09312 ast_verb(1, "Registering builtin applications:\n"); 09313 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 09314 __ast_custom_function_register(&exception_function, NULL); 09315 09316 /* Register builtin applications */ 09317 for (x = 0; x < ARRAY_LEN(builtins); x++) { 09318 ast_verb(1, "[%s]\n", builtins[x].name); 09319 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 09320 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 09321 return -1; 09322 } 09323 } 09324 09325 /* Register manager application */ 09326 ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan); 09327 09328 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL, 09329 AST_EVENT_IE_END))) { 09330 return -1; 09331 } 09332 09333 return 0; 09334 }
| void log_match_char_tree | ( | struct match_char * | node, | |
| char * | prefix | |||
| ) |
Definition at line 1494 of file pbx.c.
References match_char::alt_char, ast_debug, 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 ast_context_remove_extension_callerid2(), and pbx_find_extension().
01495 { 01496 char extenstr[40]; 01497 struct ast_str *my_prefix = ast_str_alloca(1024); 01498 01499 extenstr[0] = '\0'; 01500 01501 if (node && node->exten && node->exten) 01502 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01503 01504 if (strlen(node->x) > 1) { 01505 ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 01506 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 01507 node->exten ? node->exten->exten : "", extenstr); 01508 } else { 01509 ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 01510 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 01511 node->exten ? node->exten->exten : "", extenstr); 01512 } 01513 01514 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01515 01516 if (node->next_char) 01517 log_match_char_tree(node->next_char, ast_str_buffer(my_prefix)); 01518 01519 if (node->alt_char) 01520 log_match_char_tree(node->alt_char, prefix); 01521 }
| static int lookup_name | ( | const char * | s, | |
| 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 6784 of file pbx.c.
Referenced by get_range().
06785 { 06786 int i; 06787 06788 if (names && *s > '9') { 06789 for (i = 0; names[i]; i++) { 06790 if (!strcasecmp(s, names[i])) { 06791 return i; 06792 } 06793 } 06794 } 06795 06796 /* Allow months and weekdays to be specified as numbers, as well */ 06797 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 06798 /* What the array offset would have been: "1" would be at offset 0 */ 06799 return i - 1; 06800 } 06801 return -1; /* error return */ 06802 }
| static void manager_dpsendack | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Send ack once.
Definition at line 5948 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan_helper().
05949 { 05950 astman_send_listack(s, m, "DialPlan list will follow", "start"); 05951 }
| static int manager_show_dialplan | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager listing of dial plan.
Definition at line 6094 of file pbx.c.
References ast_strlen_zero(), astman_get_header(), astman_send_error(), dialplan_counters::context_existence, EVENT_FLAG_CONFIG, dialplan_counters::extension_existence, manager_event, 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().
06095 { 06096 const char *exten, *context; 06097 const char *id = astman_get_header(m, "ActionID"); 06098 char idtext[256]; 06099 int res; 06100 06101 /* Variables used for different counters */ 06102 struct dialplan_counters counters; 06103 06104 if (!ast_strlen_zero(id)) 06105 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 06106 else 06107 idtext[0] = '\0'; 06108 06109 memset(&counters, 0, sizeof(counters)); 06110 06111 exten = astman_get_header(m, "Extension"); 06112 context = astman_get_header(m, "Context"); 06113 06114 res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 06115 06116 if (context && !counters.context_existence) { 06117 char errorbuf[BUFSIZ]; 06118 06119 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 06120 astman_send_error(s, m, errorbuf); 06121 return 0; 06122 } 06123 if (exten && !counters.extension_existence) { 06124 char errorbuf[BUFSIZ]; 06125 06126 if (context) 06127 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 06128 else 06129 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 06130 astman_send_error(s, m, errorbuf); 06131 return 0; 06132 } 06133 06134 manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete", 06135 "EventList: Complete\r\n" 06136 "ListItems: %d\r\n" 06137 "ListExtensions: %d\r\n" 06138 "ListPriorities: %d\r\n" 06139 "ListContexts: %d\r\n" 06140 "%s" 06141 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 06142 06143 /* everything ok */ 06144 return 0; 06145 }
| 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 5957 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().
05961 { 05962 struct ast_context *c; 05963 int res = 0, old_total_exten = dpc->total_exten; 05964 05965 if (ast_strlen_zero(exten)) 05966 exten = NULL; 05967 if (ast_strlen_zero(context)) 05968 context = NULL; 05969 05970 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 05971 05972 /* try to lock contexts */ 05973 if (ast_rdlock_contexts()) { 05974 astman_send_error(s, m, "Failed to lock contexts"); 05975 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 05976 return -1; 05977 } 05978 05979 c = NULL; /* walk all contexts ... */ 05980 while ( (c = ast_walk_contexts(c)) ) { 05981 struct ast_exten *e; 05982 struct ast_include *i; 05983 struct ast_ignorepat *ip; 05984 05985 if (context && strcmp(ast_get_context_name(c), context) != 0) 05986 continue; /* not the name we want */ 05987 05988 dpc->context_existence = 1; 05989 05990 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 05991 05992 if (ast_rdlock_context(c)) { /* failed to lock */ 05993 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 05994 continue; 05995 } 05996 05997 /* XXX note- an empty context is not printed */ 05998 e = NULL; /* walk extensions in context */ 05999 while ( (e = ast_walk_context_extensions(c, e)) ) { 06000 struct ast_exten *p; 06001 06002 /* looking for extension? is this our extension? */ 06003 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 06004 /* not the one we are looking for, continue */ 06005 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 06006 continue; 06007 } 06008 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 06009 06010 dpc->extension_existence = 1; 06011 06012 /* may we print context info? */ 06013 dpc->total_context++; 06014 dpc->total_exten++; 06015 06016 p = NULL; /* walk next extension peers */ 06017 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06018 int prio = ast_get_extension_priority(p); 06019 06020 dpc->total_prio++; 06021 if (!dpc->total_items++) 06022 manager_dpsendack(s, m); 06023 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06024 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 06025 06026 /* XXX maybe make this conditional, if p != e ? */ 06027 if (ast_get_extension_label(p)) 06028 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 06029 06030 if (prio == PRIORITY_HINT) { 06031 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 06032 } else { 06033 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)); 06034 } 06035 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 06036 } 06037 } 06038 06039 i = NULL; /* walk included and write info ... */ 06040 while ( (i = ast_walk_context_includes(c, i)) ) { 06041 if (exten) { 06042 /* Check all includes for the requested extension */ 06043 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 06044 } else { 06045 if (!dpc->total_items++) 06046 manager_dpsendack(s, m); 06047 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06048 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)); 06049 astman_append(s, "\r\n"); 06050 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 06051 } 06052 } 06053 06054 ip = NULL; /* walk ignore patterns and write info ... */ 06055 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06056 const char *ipname = ast_get_ignorepat_name(ip); 06057 char ignorepat[AST_MAX_EXTENSION]; 06058 06059 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06060 if (!exten || ast_extension_match(ignorepat, exten)) { 06061 if (!dpc->total_items++) 06062 manager_dpsendack(s, m); 06063 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06064 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 06065 astman_append(s, "\r\n"); 06066 } 06067 } 06068 if (!rinclude) { 06069 struct ast_sw *sw = NULL; 06070 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06071 if (!dpc->total_items++) 06072 manager_dpsendack(s, m); 06073 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06074 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)); 06075 astman_append(s, "\r\n"); 06076 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 06077 } 06078 } 06079 06080 ast_unlock_context(c); 06081 } 06082 ast_unlock_contexts(); 06083 06084 if (dpc->total_exten == old_total_exten) { 06085 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 06086 /* Nothing new under the sun */ 06087 return -1; 06088 } else { 06089 return res; 06090 } 06091 }
| static int matchcid | ( | const char * | cidpattern, | |
| const char * | callerid | |||
| ) | [static] |
Definition at line 2457 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02458 { 02459 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02460 failing to get a number should count as a match, otherwise not */ 02461 02462 if (ast_strlen_zero(callerid)) { 02463 return ast_strlen_zero(cidpattern) ? 1 : 0; 02464 } 02465 02466 return ast_extension_match(cidpattern, callerid); 02467 }
| 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 1629 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, 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().
01630 { 01631 struct match_char *p; /* note minimal stack storage requirements */ 01632 struct ast_exten pattern = { .label = label }; 01633 #ifdef DEBUG_THIS 01634 if (tree) 01635 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01636 else 01637 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01638 #endif 01639 for (p = tree; p; p = p->alt_char) { 01640 if (p->x[0] == 'N') { 01641 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01642 #define NEW_MATCHER_CHK_MATCH \ 01643 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01644 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01645 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01646 if (!p->deleted) { \ 01647 if (action == E_FINDLABEL) { \ 01648 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01649 ast_debug(4, "Found label in preferred extension\n"); \ 01650 return; \ 01651 } \ 01652 } else { \ 01653 ast_debug(4,"returning an exact match-- first found-- %s\n", p->exten->exten); \ 01654 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01655 } \ 01656 } \ 01657 } \ 01658 } 01659 01660 #define NEW_MATCHER_RECURSE \ 01661 if (p->next_char && ( *(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01662 || p->next_char->x[0] == '!')) { \ 01663 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01664 new_find_extension(str + 1, score, p->next_char, length + 1, spec+p->specificity, callerid, label, action); \ 01665 if (score->exten) { \ 01666 ast_debug(4, "returning an exact match-- %s\n", score->exten->exten); \ 01667 return; /* the first match is all we need */ \ 01668 } \ 01669 } else { \ 01670 new_find_extension("/", score, p->next_char, length + 1, spec+p->specificity, callerid, label, action); \ 01671 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01672 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01673 "NULL"); \ 01674 return; /* the first match is all we need */ \ 01675 } \ 01676 } \ 01677 } else if (p->next_char && !*(str + 1)) { \ 01678 score->canmatch = 1; \ 01679 score->canmatch_exten = get_canmatch_exten(p); \ 01680 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01681 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01682 return; \ 01683 } \ 01684 } 01685 01686 NEW_MATCHER_CHK_MATCH; 01687 NEW_MATCHER_RECURSE; 01688 } 01689 } else if (p->x[0] == 'Z') { 01690 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01691 NEW_MATCHER_CHK_MATCH; 01692 NEW_MATCHER_RECURSE; 01693 } 01694 } else if (p->x[0] == 'X') { 01695 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01696 NEW_MATCHER_CHK_MATCH; 01697 NEW_MATCHER_RECURSE; 01698 } 01699 } else if (p->x[0] == '.' && p->x[1] == 0) { 01700 /* how many chars will the . match against? */ 01701 int i = 0; 01702 const char *str2 = str; 01703 while (*str2 && *str2 != '/') { 01704 str2++; 01705 i++; 01706 } 01707 if (p->exten && *str2 != '/') { 01708 update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p); 01709 if (score->exten) { 01710 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01711 return; /* the first match is all we need */ 01712 } 01713 } 01714 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01715 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action); 01716 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01717 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01718 return; /* the first match is all we need */ 01719 } 01720 } 01721 } else if (p->x[0] == '!' && p->x[1] == 0) { 01722 /* how many chars will the . match against? */ 01723 int i = 1; 01724 const char *str2 = str; 01725 while (*str2 && *str2 != '/') { 01726 str2++; 01727 i++; 01728 } 01729 if (p->exten && *str2 != '/') { 01730 update_scoreboard(score, length + 1, spec+(p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01731 if (score->exten) { 01732 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01733 return; /* the first match is all we need */ 01734 } 01735 } 01736 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01737 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01738 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01739 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01740 return; /* the first match is all we need */ 01741 } 01742 } 01743 } else if (p->x[0] == '/' && p->x[1] == 0) { 01744 /* the pattern in the tree includes the cid match! */ 01745 if (p->next_char && callerid && *callerid) { 01746 new_find_extension(callerid, score, p->next_char, length+1, spec, callerid, label, action); 01747 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01748 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01749 return; /* the first match is all we need */ 01750 } 01751 } 01752 } else if (strchr(p->x, *str)) { 01753 ast_debug(4, "Nothing strange about this match\n"); 01754 NEW_MATCHER_CHK_MATCH; 01755 NEW_MATCHER_RECURSE; 01756 } 01757 } 01758 ast_debug(4, "return at end of func\n"); 01759 }
| static int parse_variable_name | ( | char * | var, | |
| int * | offset, | |||
| int * | length, | |||
| int * | isfunc | |||
| ) | [static] |
extract offset:length from variable name.
Definition at line 2792 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02793 { 02794 int parens = 0; 02795 02796 *offset = 0; 02797 *length = INT_MAX; 02798 *isfunc = 0; 02799 for (; *var; var++) { 02800 if (*var == '(') { 02801 (*isfunc)++; 02802 parens++; 02803 } else if (*var == ')') { 02804 parens--; 02805 } else if (*var == ':' && parens == 0) { 02806 *var++ = '\0'; 02807 sscanf(var, "%30d:%30d", offset, length); 02808 return 1; /* offset:length valid */ 02809 } 02810 } 02811 return 0; 02812 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 9182 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_var_delete(), ast_var_t::entries, globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), and reload().
09183 { 09184 struct ast_var_t *vardata; 09185 09186 ast_rwlock_wrlock(&globalslock); 09187 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 09188 ast_var_delete(vardata); 09189 ast_rwlock_unlock(&globalslock); 09190 }
| const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name | |||
| ) |
Return a pointer to the value of the corresponding channel variable.
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 8951 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_call_forward(), ast_eivr_getvariable(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), confbridge_exec(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), listfilter(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
08952 { 08953 struct ast_var_t *variables; 08954 const char *ret = NULL; 08955 int i; 08956 struct varshead *places[2] = { NULL, &globals }; 08957 08958 if (!name) 08959 return NULL; 08960 08961 if (chan) { 08962 ast_channel_lock(chan); 08963 places[0] = &chan->varshead; 08964 } 08965 08966 for (i = 0; i < 2; i++) { 08967 if (!places[i]) 08968 continue; 08969 if (places[i] == &globals) 08970 ast_rwlock_rdlock(&globalslock); 08971 AST_LIST_TRAVERSE(places[i], variables, entries) { 08972 if (!strcmp(name, ast_var_name(variables))) { 08973 ret = ast_var_value(variables); 08974 break; 08975 } 08976 } 08977 if (places[i] == &globals) 08978 ast_rwlock_unlock(&globalslock); 08979 if (ret) 08980 break; 08981 } 08982 08983 if (chan) 08984 ast_channel_unlock(chan); 08985 08986 return ret; 08987 }
| static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 9204 of file pbx.c.
References ast_debug, ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), and pbx_checkcondition().
09205 { 09206 char *condition, *branch1, *branch2, *branch; 09207 char *stringp; 09208 09209 if (ast_strlen_zero(data)) { 09210 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 09211 return 0; 09212 } 09213 09214 stringp = ast_strdupa(data); 09215 condition = strsep(&stringp,"?"); 09216 branch1 = strsep(&stringp,":"); 09217 branch2 = strsep(&stringp,""); 09218 branch = pbx_checkcondition(condition) ? branch1 : branch2; 09219 09220 if (ast_strlen_zero(branch)) { 09221 ast_debug(1, "Not taking any branch\n"); 09222 return 0; 09223 } 09224 09225 return pbx_builtin_goto(chan, branch); 09226 }
| int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 9140 of file pbx.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, and VAR_BUF_SIZE.
09141 { 09142 char *name; 09143 char *value; 09144 char *channel; 09145 char tmp[VAR_BUF_SIZE]; 09146 static int deprecation_warning = 0; 09147 09148 if (ast_strlen_zero(data)) { 09149 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 09150 return 0; 09151 } 09152 tmp[0] = 0; 09153 if (!deprecation_warning) { 09154 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 09155 deprecation_warning = 1; 09156 } 09157 09158 value = ast_strdupa(data); 09159 name = strsep(&value,"="); 09160 channel = strsep(&value,","); 09161 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 09162 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 09163 if (chan2) { 09164 char *s = alloca(strlen(value) + 4); 09165 if (s) { 09166 sprintf(s, "${%s}", value); 09167 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 09168 } 09169 ast_channel_unlock(chan2); 09170 } 09171 pbx_builtin_setvar_helper(chan, name, tmp); 09172 } 09173 09174 return(0); 09175 }
| static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8536 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
08537 { 08538 char *options = data; 08539 int answer = 1; 08540 08541 /* Some channels can receive DTMF in unanswered state; some cannot */ 08542 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 08543 answer = 0; 08544 } 08545 08546 /* If the channel is hungup, stop waiting */ 08547 if (ast_check_hangup(chan)) { 08548 return -1; 08549 } else if (chan->_state != AST_STATE_UP && answer) { 08550 __ast_answer(chan, 0, 1); 08551 } 08552 08553 return AST_PBX_INCOMPLETE; 08554 }
| static int pbx_builtin_noop | ( | struct ast_channel * | chan, | |
| void * | 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 8989 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
08990 { 08991 struct ast_var_t *newvariable; 08992 struct varshead *headp; 08993 08994 if (name[strlen(name)-1] == ')') { 08995 char *function = ast_strdupa(name); 08996 08997 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 08998 ast_func_write(chan, function, value); 08999 return; 09000 } 09001 09002 if (chan) { 09003 ast_channel_lock(chan); 09004 headp = &chan->varshead; 09005 } else { 09006 ast_rwlock_wrlock(&globalslock); 09007 headp = &globals; 09008 } 09009 09010 if (value) { 09011 if (headp == &globals) 09012 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09013 newvariable = ast_var_assign(name, value); 09014 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09015 } 09016 09017 if (chan) 09018 ast_channel_unlock(chan); 09019 else 09020 ast_rwlock_unlock(&globalslock); 09021 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| void * | vreason | |||
| ) |
Definition at line 2995 of file pbx.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_free, ast_string_field_init, ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run().
02996 { 02997 const char *reason = vreason; 02998 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02999 struct pbx_exception *exception = NULL; 03000 03001 if (!ds) { 03002 ds = ast_datastore_alloc(&exception_store_info, NULL); 03003 if (!ds) 03004 return -1; 03005 exception = ast_calloc(1, sizeof(struct pbx_exception)); 03006 if (!exception) { 03007 ast_datastore_free(ds); 03008 return -1; 03009 } 03010 if (ast_string_field_init(exception, 128)) { 03011 ast_free(exception); 03012 ast_datastore_free(ds); 03013 return -1; 03014 } 03015 ds->data = exception; 03016 ast_channel_datastore_add(chan, ds); 03017 } else 03018 exception = ds->data; 03019 03020 ast_string_field_set(exception, reason, reason); 03021 ast_string_field_set(exception, context, chan->context); 03022 ast_string_field_set(exception, exten, chan->exten); 03023 exception->priority = chan->priority; 03024 set_ext_pri(chan, "e", 0); 03025 return 0; 03026 }
| static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 9265 of file pbx.c.
References ast_say_character_str(), and ast_channel::language.
09266 { 09267 int res = 0; 09268 09269 if (data) 09270 res = ast_say_character_str(chan, data, "", chan->language); 09271 return res; 09272 }
| static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 9256 of file pbx.c.
References ast_say_digit_str(), and ast_channel::language.
09257 { 09258 int res = 0; 09259 09260 if (data) 09261 res = ast_say_digit_str(chan, data, "", chan->language); 09262 return res; 09263 }
| static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 9228 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), ast_channel::language, and LOG_WARNING.
09229 { 09230 char tmp[256]; 09231 char *number = tmp; 09232 char *options; 09233 09234 if (ast_strlen_zero(data)) { 09235 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 09236 return -1; 09237 } 09238 ast_copy_string(tmp, data, sizeof(tmp)); 09239 strsep(&number, ","); 09240 options = strsep(&number, ","); 09241 if (options) { 09242 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 09243 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 09244 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 09245 return -1; 09246 } 09247 } 09248 09249 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 09250 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 09251 } 09252 09253 return 0; 09254 }
| static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 9274 of file pbx.c.
References ast_say_phonetic_str(), and ast_channel::language.
09275 { 09276 int res = 0; 09277 09278 if (data) 09279 res = ast_say_phonetic_str(chan, data, "", chan->language); 09280 return res; 09281 }
| int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
| struct ast_str ** | buf | |||
| ) |
Create a human-readable string, specifying all variables and their corresponding values.
| chan | Channel from which to read variables | |
| buf | Dynamic string in which to place the result (should be allocated with |
Definition at line 8920 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
08921 { 08922 struct ast_var_t *variables; 08923 const char *var, *val; 08924 int total = 0; 08925 08926 if (!chan) 08927 return 0; 08928 08929 ast_str_reset(*buf); 08930 08931 ast_channel_lock(chan); 08932 08933 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 08934 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 08935 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 08936 ) { 08937 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 08938 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 08939 break; 08940 } else 08941 total++; 08942 } else 08943 break; 08944 } 08945 08946 ast_channel_unlock(chan); 08947 08948 return total; 08949 }
| int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 9081 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), and pbx_builtin_setvar_multiple().
Referenced by ast_compile_ael2(), and rpt_exec().
09082 { 09083 char *name, *value, *mydata; 09084 09085 if (ast_compat_app_set) { 09086 return pbx_builtin_setvar_multiple(chan, data); 09087 } 09088 09089 if (ast_strlen_zero(data)) { 09090 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 09091 return 0; 09092 } 09093 09094 mydata = ast_strdupa(data); 09095 name = strsep(&mydata, "="); 09096 value = mydata; 09097 if (strchr(name, ' ')) 09098 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 09099 09100 pbx_builtin_setvar_helper(chan, name, value); 09101 return(0); 09102 }
| void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Add a variable to the channel variable stack, removing the most recently set value for the same name.
Definition at line 9023 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, ast_channel::name, ast_channel::uniqueid, and ast_channel::varshead.
Referenced by __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_exec(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), aqm_exec(), array(), ast_bridge_call(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_rtp_set_vars(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_request_and_dial(), frame_set_var(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), pri_dchannel(), privacy_exec(), process_ast_dsp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), record_exec(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss7_start_call(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), transmit(), tryexec_exec(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
09024 { 09025 struct ast_var_t *newvariable; 09026 struct varshead *headp; 09027 const char *nametail = name; 09028 09029 if (name[strlen(name) - 1] == ')') { 09030 char *function = ast_strdupa(name); 09031 09032 ast_func_write(chan, function, value); 09033 return; 09034 } 09035 09036 if (chan) { 09037 ast_channel_lock(chan); 09038 headp = &chan->varshead; 09039 } else { 09040 ast_rwlock_wrlock(&globalslock); 09041 headp = &globals; 09042 } 09043 09044 /* For comparison purposes, we have to strip leading underscores */ 09045 if (*nametail == '_') { 09046 nametail++; 09047 if (*nametail == '_') 09048 nametail++; 09049 } 09050 09051 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 09052 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 09053 /* there is already such a variable, delete it */ 09054 AST_LIST_REMOVE_CURRENT(entries); 09055 ast_var_delete(newvariable); 09056 break; 09057 } 09058 } 09059 AST_LIST_TRAVERSE_SAFE_END; 09060 09061 if (value) { 09062 if (headp == &globals) 09063 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09064 newvariable = ast_var_assign(name, value); 09065 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09066 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 09067 "Channel: %s\r\n" 09068 "Variable: %s\r\n" 09069 "Value: %s\r\n" 09070 "Uniqueid: %s\r\n", 09071 chan ? chan->name : "none", name, value, 09072 chan ? chan->uniqueid : "none"); 09073 } 09074 09075 if (chan) 09076 ast_channel_unlock(chan); 09077 else 09078 ast_rwlock_unlock(&globalslock); 09079 }
| int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
| void * | vdata | |||
| ) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
Definition at line 9104 of file pbx.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), and ast_channel::priority.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
09105 { 09106 char *data; 09107 int x; 09108 AST_DECLARE_APP_ARGS(args, 09109 AST_APP_ARG(pair)[24]; 09110 ); 09111 AST_DECLARE_APP_ARGS(pair, 09112 AST_APP_ARG(name); 09113 AST_APP_ARG(value); 09114 ); 09115 09116 if (ast_strlen_zero(vdata)) { 09117 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 09118 return 0; 09119 } 09120 09121 data = ast_strdupa(vdata); 09122 AST_STANDARD_APP_ARGS(args, data); 09123 09124 for (x = 0; x < args.argc; x++) { 09125 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 09126 if (pair.argc == 2) { 09127 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 09128 if (strchr(pair.name, ' ')) 09129 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value); 09130 } else if (!chan) { 09131 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 09132 } else { 09133 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 09134 } 09135 } 09136 09137 return 0; 09138 }
| int pbx_checkcondition | ( | const char * | condition | ) |
Evaluate a condition.
| 0 | if the condition is NULL or of zero length | |
| int | If the string is an integer, the integer representation of the integer is returned | |
| 1 | Any other non-empty string |
Definition at line 9192 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().
09193 { 09194 int res; 09195 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 09196 return 0; 09197 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 09198 return res; 09199 } else { /* Strings are true */ 09200 return 1; 09201 } 09202 }
| static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 1399 of file pbx.c.
References ast_free.
Referenced by __ast_pbx_run().
01400 { 01401 ast_free(p); 01402 }
| int pbx_exec | ( | struct ast_channel * | c, | |
| struct ast_app * | app, | |||
| void * | data | |||
| ) |
Execute an application.
| c | channel to execute on | |
| app | which app to execute | |
| data | the data passed into the app |
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.
| 0 | success | |
| -1 | failure |
| c | Channel | |
| app | Application | |
| data | Data for execution |
Definition at line 1322 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01325 { 01326 int res; 01327 struct ast_module_user *u = NULL; 01328 const char *saved_c_appl; 01329 const char *saved_c_data; 01330 01331 if (c->cdr && !ast_check_hangup(c)) 01332 ast_cdr_setapp(c->cdr, app->name, data); 01333 01334 /* save channel values */ 01335 saved_c_appl= c->appl; 01336 saved_c_data= c->data; 01337 01338 c->appl = app->name; 01339 c->data = data; 01340 if (app->module) 01341 u = __ast_module_user_add(app->module, c); 01342 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01343 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01344 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01345 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01346 app->name, (char *) data); 01347 } 01348 res = app->execute(c, S_OR((char *) data, "")); 01349 if (app->module && u) 01350 __ast_module_user_remove(app->module, u); 01351 /* restore channel values */ 01352 c->appl = saved_c_appl; 01353 c->data = saved_c_data; 01354 return res; 01355 }
| 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 3647 of file pbx.c.
References ast_exten::app, app, ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::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_channel::name, ast_app::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), 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(), ast_channel::uniqueid, and VERBOSITY_ATLEAST.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
03650 { 03651 struct ast_exten *e; 03652 struct ast_app *app; 03653 int res; 03654 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 03655 char passdata[EXT_DATA_SIZE]; 03656 03657 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 03658 03659 ast_rdlock_contexts(); 03660 if (found) 03661 *found = 0; 03662 03663 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 03664 if (e) { 03665 if (found) 03666 *found = 1; 03667 if (matching_action) { 03668 ast_unlock_contexts(); 03669 return -1; /* success, we found it */ 03670 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 03671 res = e->priority; 03672 ast_unlock_contexts(); 03673 return res; /* the priority we were looking for */ 03674 } else { /* spawn */ 03675 if (!e->cached_app) 03676 e->cached_app = pbx_findapp(e->app); 03677 app = e->cached_app; 03678 ast_unlock_contexts(); 03679 if (!app) { 03680 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 03681 return -1; 03682 } 03683 if (c->context != context) 03684 ast_copy_string(c->context, context, sizeof(c->context)); 03685 if (c->exten != exten) 03686 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03687 c->priority = priority; 03688 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 03689 #ifdef CHANNEL_TRACE 03690 ast_channel_trace_update(c); 03691 #endif 03692 ast_debug(1, "Launching '%s'\n", app->name); 03693 if (VERBOSITY_ATLEAST(3)) { 03694 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 03695 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 03696 exten, context, priority, 03697 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 03698 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 03699 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 03700 "in new stack"); 03701 } 03702 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 03703 "Channel: %s\r\n" 03704 "Context: %s\r\n" 03705 "Extension: %s\r\n" 03706 "Priority: %d\r\n" 03707 "Application: %s\r\n" 03708 "AppData: %s\r\n" 03709 "Uniqueid: %s\r\n", 03710 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 03711 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 03712 } 03713 } else if (q.swo) { /* not found here, but in another switch */ 03714 if (found) 03715 *found = 1; 03716 ast_unlock_contexts(); 03717 if (matching_action) { 03718 return -1; 03719 } else { 03720 if (!q.swo->exec) { 03721 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 03722 res = -1; 03723 } 03724 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 03725 } 03726 } else { /* not found anywhere, see what happened */ 03727 ast_unlock_contexts(); 03728 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 03729 switch (q.status) { 03730 case STATUS_NO_CONTEXT: 03731 if (!matching_action && !combined_find_spawn) 03732 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 03733 break; 03734 case STATUS_NO_EXTENSION: 03735 if (!matching_action && !combined_find_spawn) 03736 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 03737 break; 03738 case STATUS_NO_PRIORITY: 03739 if (!matching_action && !combined_find_spawn) 03740 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 03741 break; 03742 case STATUS_NO_LABEL: 03743 if (context && !combined_find_spawn) 03744 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 03745 break; 03746 default: 03747 ast_debug(1, "Shouldn't happen!\n"); 03748 } 03749 03750 return (matching_action) ? 0 : -1; 03751 } 03752 }
| struct ast_exten* pbx_find_extension | ( | struct ast_channel * | chan, | |
| struct ast_context * | bypass, | |||
| struct pbx_find_info * | q, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| enum ext_match_t | action | |||
| ) | [read] |
Definition at line 2469 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strlen_zero(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_switch::canmatch, scoreboard::canmatch_exten, contexts_table, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_sw::name, ast_context::name, fake_context::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().
02473 { 02474 int x, res; 02475 struct ast_context *tmp = NULL; 02476 struct ast_exten *e = NULL, *eroot = NULL; 02477 struct ast_include *i = NULL; 02478 struct ast_sw *sw = NULL; 02479 struct ast_exten pattern = {NULL, }; 02480 struct scoreboard score = {0, }; 02481 struct ast_str *tmpdata = NULL; 02482 02483 pattern.label = label; 02484 pattern.priority = priority; 02485 #ifdef NEED_DEBUG_HERE 02486 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02487 #endif 02488 02489 /* Initialize status if appropriate */ 02490 if (q->stacklen == 0) { 02491 q->status = STATUS_NO_CONTEXT; 02492 q->swo = NULL; 02493 q->data = NULL; 02494 q->foundcontext = NULL; 02495 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02496 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02497 return NULL; 02498 } 02499 02500 /* Check first to see if we've already been checked */ 02501 for (x = 0; x < q->stacklen; x++) { 02502 if (!strcasecmp(q->incstack[x], context)) 02503 return NULL; 02504 } 02505 02506 if (bypass) { /* bypass means we only look there */ 02507 tmp = bypass; 02508 } else { /* look in contexts */ 02509 struct fake_context item; 02510 02511 ast_copy_string(item.name, context, sizeof(item.name)); 02512 02513 tmp = ast_hashtab_lookup(contexts_table, &item); 02514 #ifdef NOTNOW 02515 tmp = NULL; 02516 while ((tmp = ast_walk_contexts(tmp)) ) { 02517 if (!strcmp(tmp->name, context)) { 02518 break; 02519 } 02520 } 02521 #endif 02522 if (!tmp) { 02523 return NULL; 02524 } 02525 } 02526 02527 if (q->status < STATUS_NO_EXTENSION) 02528 q->status = STATUS_NO_EXTENSION; 02529 02530 /* Do a search for matching extension */ 02531 02532 eroot = NULL; 02533 score.total_specificity = 0; 02534 score.exten = 0; 02535 score.total_length = 0; 02536 if (!tmp->pattern_tree && tmp->root_table) { 02537 create_match_char_tree(tmp); 02538 #ifdef NEED_DEBUG 02539 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02540 log_match_char_tree(tmp->pattern_tree," "); 02541 #endif 02542 } 02543 #ifdef NEED_DEBUG 02544 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02545 log_match_char_tree(tmp->pattern_tree, ":: "); 02546 #endif 02547 02548 do { 02549 if (!ast_strlen_zero(overrideswitch)) { 02550 char *osw = ast_strdupa(overrideswitch), *name; 02551 struct ast_switch *asw; 02552 ast_switch_f *aswf = NULL; 02553 char *datap; 02554 int eval = 0; 02555 02556 name = strsep(&osw, "/"); 02557 asw = pbx_findswitch(name); 02558 02559 if (!asw) { 02560 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02561 break; 02562 } 02563 02564 if (osw && strchr(osw, '$')) { 02565 eval = 1; 02566 } 02567 02568 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02569 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02570 break; 02571 } else if (eval) { 02572 /* Substitute variables now */ 02573 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02574 datap = ast_str_buffer(tmpdata); 02575 } else { 02576 datap = osw; 02577 } 02578 02579 /* equivalent of extension_match_core() at the switch level */ 02580 if (action == E_CANMATCH) 02581 aswf = asw->canmatch; 02582 else if (action == E_MATCHMORE) 02583 aswf = asw->matchmore; 02584 else /* action == E_MATCH */ 02585 aswf = asw->exists; 02586 if (!aswf) { 02587 res = 0; 02588 } else { 02589 if (chan) { 02590 ast_autoservice_start(chan); 02591 } 02592 res = aswf(chan, context, exten, priority, callerid, datap); 02593 if (chan) { 02594 ast_autoservice_stop(chan); 02595 } 02596 } 02597 if (res) { /* Got a match */ 02598 q->swo = asw; 02599 q->data = datap; 02600 q->foundcontext = context; 02601 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02602 return NULL; 02603 } 02604 } 02605 } while (0); 02606 02607 if (extenpatternmatchnew) { 02608 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02609 eroot = score.exten; 02610 02611 if (score.last_char == '!' && action == E_MATCHMORE) { 02612 /* We match an extension ending in '!'. 02613 * The decision in this case is final and is NULL (no match). 02614 */ 02615 #ifdef NEED_DEBUG_HERE 02616 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02617 #endif 02618 return NULL; 02619 } 02620 02621 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02622 q->status = STATUS_SUCCESS; 02623 #ifdef NEED_DEBUG_HERE 02624 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02625 #endif 02626 return score.canmatch_exten; 02627 } 02628 02629 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02630 if (score.node) { 02631 struct ast_exten *z = trie_find_next_match(score.node); 02632 if (z) { 02633 #ifdef NEED_DEBUG_HERE 02634 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02635 #endif 02636 } else { 02637 if (score.canmatch_exten) { 02638 #ifdef NEED_DEBUG_HERE 02639 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02640 #endif 02641 return score.canmatch_exten; 02642 } else { 02643 #ifdef NEED_DEBUG_HERE 02644 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02645 #endif 02646 } 02647 } 02648 return z; 02649 } 02650 #ifdef NEED_DEBUG_HERE 02651 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02652 #endif 02653 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02654 } 02655 02656 if (eroot) { 02657 /* found entry, now look for the right priority */ 02658 if (q->status < STATUS_NO_PRIORITY) 02659 q->status = STATUS_NO_PRIORITY; 02660 e = NULL; 02661 if (action == E_FINDLABEL && label ) { 02662 if (q->status < STATUS_NO_LABEL) 02663 q->status = STATUS_NO_LABEL; 02664 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02665 } else { 02666 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02667 } 02668 if (e) { /* found a valid match */ 02669 q->status = STATUS_SUCCESS; 02670 q->foundcontext = context; 02671 #ifdef NEED_DEBUG_HERE 02672 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02673 #endif 02674 return e; 02675 } 02676 } 02677 } else { /* the old/current default exten pattern match algorithm */ 02678 02679 /* scan the list trying to match extension and CID */ 02680 eroot = NULL; 02681 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02682 int match = extension_match_core(eroot->exten, exten, action); 02683 /* 0 on fail, 1 on match, 2 on earlymatch */ 02684 02685 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02686 continue; /* keep trying */ 02687 if (match == 2 && action == E_MATCHMORE) { 02688 /* We match an extension ending in '!'. 02689 * The decision in this case is final and is NULL (no match). 02690 */ 02691 return NULL; 02692 } 02693 /* found entry, now look for the right priority */ 02694 if (q->status < STATUS_NO_PRIORITY) 02695 q->status = STATUS_NO_PRIORITY; 02696 e = NULL; 02697 if (action == E_FINDLABEL && label ) { 02698 if (q->status < STATUS_NO_LABEL) 02699 q->status = STATUS_NO_LABEL; 02700 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02701 } else { 02702 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02703 } 02704 #ifdef NOTNOW 02705 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 02706 /* Match label or priority */ 02707 if (action == E_FINDLABEL) { 02708 if (q->status < STATUS_NO_LABEL) 02709 q->status = STATUS_NO_LABEL; 02710 if (label && e->label && !strcmp(label, e->label)) 02711 break; /* found it */ 02712 } else if (e->priority == priority) { 02713 break; /* found it */ 02714 } /* else keep searching */ 02715 } 02716 #endif 02717 if (e) { /* found a valid match */ 02718 q->status = STATUS_SUCCESS; 02719 q->foundcontext = context; 02720 return e; 02721 } 02722 } 02723 } 02724 02725 /* Check alternative switches */ 02726 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02727 struct ast_switch *asw = pbx_findswitch(sw->name); 02728 ast_switch_f *aswf = NULL; 02729 char *datap; 02730 02731 if (!asw) { 02732 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02733 continue; 02734 } 02735 02736 /* Substitute variables now */ 02737 if (sw->eval) { 02738 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02739 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02740 continue; 02741 } 02742 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02743 } 02744 02745 /* equivalent of extension_match_core() at the switch level */ 02746 if (action == E_CANMATCH) 02747 aswf = asw->canmatch; 02748 else if (action == E_MATCHMORE) 02749 aswf = asw->matchmore; 02750 else /* action == E_MATCH */ 02751 aswf = asw->exists; 02752 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02753 if (!aswf) 02754 res = 0; 02755 else { 02756 if (chan) 02757 ast_autoservice_start(chan); 02758 res = aswf(chan, context, exten, priority, callerid, datap); 02759 if (chan) 02760 ast_autoservice_stop(chan); 02761 } 02762 if (res) { /* Got a match */ 02763 q->swo = asw; 02764 q->data = datap; 02765 q->foundcontext = context; 02766 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02767 return NULL; 02768 } 02769 } 02770 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02771 /* Now try any includes we have in this context */ 02772 for (i = tmp->includes; i; i = i->next) { 02773 if (include_valid(i)) { 02774 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02775 #ifdef NEED_DEBUG_HERE 02776 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02777 #endif 02778 return e; 02779 } 02780 if (q->swo) 02781 return NULL; 02782 } 02783 } 02784 return NULL; 02785 }
| struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 1363 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01364 { 01365 struct ast_app *tmp; 01366 01367 AST_RWLIST_RDLOCK(&apps); 01368 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01369 if (!strcasecmp(tmp->name, app)) 01370 break; 01371 } 01372 AST_RWLIST_UNLOCK(&apps); 01373 01374 return tmp; 01375 }
| static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 1377 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
01378 { 01379 struct ast_switch *asw; 01380 01381 AST_RWLIST_RDLOCK(&switches); 01382 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01383 if (!strcasecmp(asw->name, sw)) 01384 break; 01385 } 01386 AST_RWLIST_UNLOCK(&switches); 01387 01388 return asw; 01389 }
| static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string, | |||
| int | async | |||
| ) | [static] |
Definition at line 9580 of file pbx.c.
References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, LOG_WARNING, and ast_channel::priority.
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
09581 { 09582 char *exten, *pri, *context; 09583 char *stringp; 09584 int ipri; 09585 int mode = 0; 09586 09587 if (ast_strlen_zero(goto_string)) { 09588 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 09589 return -1; 09590 } 09591 stringp = ast_strdupa(goto_string); 09592 context = strsep(&stringp, ","); /* guaranteed non-null */ 09593 exten = strsep(&stringp, ","); 09594 pri = strsep(&stringp, ","); 09595 if (!exten) { /* Only a priority in this one */ 09596 pri = context; 09597 exten = NULL; 09598 context = NULL; 09599 } else if (!pri) { /* Only an extension and priority in this one */ 09600 pri = exten; 09601 exten = context; 09602 context = NULL; 09603 } 09604 if (*pri == '+') { 09605 mode = 1; 09606 pri++; 09607 } else if (*pri == '-') { 09608 mode = -1; 09609 pri++; 09610 } 09611 if (sscanf(pri, "%30d", &ipri) != 1) { 09612 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 09613 pri, chan->cid.cid_num)) < 1) { 09614 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 09615 return -1; 09616 } else 09617 mode = 0; 09618 } 09619 /* At this point we have a priority and maybe an extension and a context */ 09620 09621 if (mode) 09622 ipri = chan->priority + (ipri * mode); 09623 09624 if (async) 09625 ast_async_goto(chan, context, exten, ipri); 09626 else 09627 ast_explicit_goto(chan, context, exten, ipri); 09628 09629 return 0; 09630 09631 }
| 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 2867 of file pbx.c.
References ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_eid_default, ast_eid_to_str(), ast_get_hint(), AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_channel::name, parse_variable_name(), ast_channel::priority, s, substring(), ast_channel::uniqueid, and ast_channel::varshead.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02868 { 02869 const char not_found = '\0'; 02870 char *tmpvar; 02871 const char *s; /* the result */ 02872 int offset, length; 02873 int i, need_substring; 02874 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02875 02876 if (c) { 02877 ast_channel_lock(c); 02878 places[0] = &c->varshead; 02879 } 02880 /* 02881 * Make a copy of var because parse_variable_name() modifies the string. 02882 * Then if called directly, we might need to run substring() on the result; 02883 * remember this for later in 'need_substring', 'offset' and 'length' 02884 */ 02885 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 02886 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 02887 02888 /* 02889 * Look first into predefined variables, then into variable lists. 02890 * Variable 's' points to the result, according to the following rules: 02891 * s == ¬_found (set at the beginning) means that we did not find a 02892 * matching variable and need to look into more places. 02893 * If s != ¬_found, s is a valid result string as follows: 02894 * s = NULL if the variable does not have a value; 02895 * you typically do this when looking for an unset predefined variable. 02896 * s = workspace if the result has been assembled there; 02897 * typically done when the result is built e.g. with an snprintf(), 02898 * so we don't need to do an additional copy. 02899 * s != workspace in case we have a string, that needs to be copied 02900 * (the ast_copy_string is done once for all at the end). 02901 * Typically done when the result is already available in some string. 02902 */ 02903 s = ¬_found; /* default value */ 02904 if (c) { /* This group requires a valid channel */ 02905 /* Names with common parts are looked up a piece at a time using strncmp. */ 02906 if (!strncmp(var, "CALL", 4)) { 02907 if (!strncmp(var + 4, "ING", 3)) { 02908 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 02909 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 02910 s = workspace; 02911 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 02912 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 02913 s = workspace; 02914 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 02915 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 02916 s = workspace; 02917 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 02918 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 02919 s = workspace; 02920 } 02921 } 02922 } else if (!strcmp(var, "HINT")) { 02923 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 02924 } else if (!strcmp(var, "HINTNAME")) { 02925 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 02926 } else if (!strcmp(var, "EXTEN")) { 02927 s = c->exten; 02928 } else if (!strcmp(var, "CONTEXT")) { 02929 s = c->context; 02930 } else if (!strcmp(var, "PRIORITY")) { 02931 snprintf(workspace, workspacelen, "%d", c->priority); 02932 s = workspace; 02933 } else if (!strcmp(var, "CHANNEL")) { 02934 s = c->name; 02935 } else if (!strcmp(var, "UNIQUEID")) { 02936 s = c->uniqueid; 02937 } else if (!strcmp(var, "HANGUPCAUSE")) { 02938 snprintf(workspace, workspacelen, "%d", c->hangupcause); 02939 s = workspace; 02940 } 02941 } 02942 if (s == ¬_found) { /* look for more */ 02943 if (!strcmp(var, "EPOCH")) { 02944 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 02945 s = workspace; 02946 } else if (!strcmp(var, "SYSTEMNAME")) { 02947 s = ast_config_AST_SYSTEM_NAME; 02948 } else if (!strcmp(var, "ENTITYID")) { 02949 ast_eid_to_str(workspace, workspacelen, &ast_eid_default); 02950 s = workspace; 02951 } 02952 } 02953 /* if not found, look into chanvars or global vars */ 02954 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 02955 struct ast_var_t *variables; 02956 if (!places[i]) 02957 continue; 02958 if (places[i] == &globals) 02959 ast_rwlock_rdlock(&globalslock); 02960 AST_LIST_TRAVERSE(places[i], variables, entries) { 02961 if (!strcasecmp(ast_var_name(variables), var)) { 02962 s = ast_var_value(variables); 02963 break; 02964 } 02965 } 02966 if (places[i] == &globals) 02967 ast_rwlock_unlock(&globalslock); 02968 } 02969 if (s == ¬_found || s == NULL) 02970 *ret = NULL; 02971 else { 02972 if (s != workspace) 02973 ast_copy_string(workspace, s, workspacelen); 02974 *ret = workspace; 02975 if (need_substring) 02976 *ret = substring(*ret, offset, length, workspace, workspacelen); 02977 } 02978 02979 if (c) 02980 ast_channel_unlock(c); 02981 }
| int pbx_set_autofallthrough | ( | int | newval | ) |
Set "autofallthrough" flag, if newval is <0, does not actually set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.
Definition at line 4611 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
04612 { 04613 int oldval = autofallthrough; 04614 autofallthrough = newval; 04615 return oldval; 04616 }
| int pbx_set_extenpatternmatchnew | ( | int | newval | ) |
Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use the old linear-search algorithm. Returns previous value.
Definition at line 4618 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
04619 { 04620 int oldval = extenpatternmatchnew; 04621 extenpatternmatchnew = newval; 04622 return oldval; 04623 }
| void pbx_set_overrideswitch | ( | const char * | newval | ) |
Set "overrideswitch" field. If set and of nonzero length, all contexts will be tried directly through the named switch prior to any other matching within that context.
Definition at line 4625 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
04626 { 04627 if (overrideswitch) { 04628 ast_free(overrideswitch); 04629 } 04630 if (!ast_strlen_zero(newval)) { 04631 overrideswitch = ast_strdup(newval); 04632 } else { 04633 overrideswitch = NULL; 04634 } 04635 }
| static void pbx_substitute_variables | ( | char * | passdata, | |
| int | datalen, | |||
| struct ast_channel * | c, | |||
| struct ast_exten * | e | |||
| ) | [static] |
Definition at line 3610 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
03611 { 03612 const char *tmp; 03613 03614 /* Nothing more to do */ 03615 if (!e->data) { 03616 *passdata = '\0'; 03617 return; 03618 } 03619 03620 /* No variables or expressions in e->data, so why scan it? */ 03621 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 03622 ast_copy_string(passdata, e->data, datalen); 03623 return; 03624 } 03625 03626 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 03627 }
| void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3598 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by _macro_exec(), acf_import(), add_extensions(), ast_add_extension2_lockopt(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), function_eval(), function_fieldqty(), get_mapping_weight(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_curl(), realtime_exec(), realtime_multi_curl(), require_curl(), rotate_file(), rpt_do_lstats(), rpt_exec(), sendmail(), sendpage(), sqlite3_log(), store_curl(), substituted(), try_calling(), tryexec_exec(), update2_curl(), and update_curl().
03599 { 03600 size_t used; 03601 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 03602 }
| void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
| struct varshead * | headp, | |||
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count, | |||
| size_t * | used | |||
| ) |
Definition at line 3403 of file pbx.c.
References ast_channel_alloc, ast_channel_free(), ast_copy_string(), ast_debug, ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
03404 { 03405 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03406 char *cp4; 03407 const char *tmp, *whereweare, *orig_cp2 = cp2; 03408 int length, offset, offset2, isfunction; 03409 char *workspace = NULL; 03410 char *ltmp = NULL, *var = NULL; 03411 char *nextvar, *nextexp, *nextthing; 03412 char *vars, *vare; 03413 int pos, brackets, needsub, len; 03414 03415 *cp2 = 0; /* just in case nothing ends up there */ 03416 whereweare=tmp=cp1; 03417 while (!ast_strlen_zero(whereweare) && count) { 03418 /* Assume we're copying the whole remaining string */ 03419 pos = strlen(whereweare); 03420 nextvar = NULL; 03421 nextexp = NULL; 03422 nextthing = strchr(whereweare, '$'); 03423 if (nextthing) { 03424 switch (nextthing[1]) { 03425 case '{': 03426 nextvar = nextthing; 03427 pos = nextvar - whereweare; 03428 break; 03429 case '[': 03430 nextexp = nextthing; 03431 pos = nextexp - whereweare; 03432 break; 03433 default: 03434 pos = 1; 03435 } 03436 } 03437 03438 if (pos) { 03439 /* Can't copy more than 'count' bytes */ 03440 if (pos > count) 03441 pos = count; 03442 03443 /* Copy that many bytes */ 03444 memcpy(cp2, whereweare, pos); 03445 03446 count -= pos; 03447 cp2 += pos; 03448 whereweare += pos; 03449 *cp2 = 0; 03450 } 03451 03452 if (nextvar) { 03453 /* We have a variable. Find the start and end, and determine 03454 if we are going to have to recursively call ourselves on the 03455 contents */ 03456 vars = vare = nextvar + 2; 03457 brackets = 1; 03458 needsub = 0; 03459 03460 /* Find the end of it */ 03461 while (brackets && *vare) { 03462 if ((vare[0] == '$') && (vare[1] == '{')) { 03463 needsub++; 03464 } else if (vare[0] == '{') { 03465 brackets++; 03466 } else if (vare[0] == '}') { 03467 brackets--; 03468 } else if ((vare[0] == '$') && (vare[1] == '[')) 03469 needsub++; 03470 vare++; 03471 } 03472 if (brackets) 03473 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03474 len = vare - vars - 1; 03475 03476 /* Skip totally over variable string */ 03477 whereweare += (len + 3); 03478 03479 if (!var) 03480 var = alloca(VAR_BUF_SIZE); 03481 03482 /* Store variable name (and truncate) */ 03483 ast_copy_string(var, vars, len + 1); 03484 03485 /* Substitute if necessary */ 03486 if (needsub) { 03487 size_t used; 03488 if (!ltmp) 03489 ltmp = alloca(VAR_BUF_SIZE); 03490 03491 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03492 vars = ltmp; 03493 } else { 03494 vars = var; 03495 } 03496 03497 if (!workspace) 03498 workspace = alloca(VAR_BUF_SIZE); 03499 03500 workspace[0] = '\0'; 03501 03502 parse_variable_name(vars, &offset, &offset2, &isfunction); 03503 if (isfunction) { 03504 /* Evaluate function */ 03505 if (c || !headp) 03506 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03507 else { 03508 struct varshead old; 03509 struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 03510 if (bogus) { 03511 memcpy(&old, &bogus->varshead, sizeof(old)); 03512 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03513 cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03514 /* Don't deallocate the varshead that was passed in */ 03515 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03516 ast_channel_free(bogus); 03517 } else 03518 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03519 } 03520 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03521 } else { 03522 /* Retrieve variable value */ 03523 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03524 } 03525 if (cp4) { 03526 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03527 03528 length = strlen(cp4); 03529 if (length > count) 03530 length = count; 03531 memcpy(cp2, cp4, length); 03532 count -= length; 03533 cp2 += length; 03534 *cp2 = 0; 03535 } 03536 } else if (nextexp) { 03537 /* We have an expression. Find the start and end, and determine 03538 if we are going to have to recursively call ourselves on the 03539 contents */ 03540 vars = vare = nextexp + 2; 03541 brackets = 1; 03542 needsub = 0; 03543 03544 /* Find the end of it */ 03545 while (brackets && *vare) { 03546 if ((vare[0] == '$') && (vare[1] == '[')) { 03547 needsub++; 03548 brackets++; 03549 vare++; 03550 } else if (vare[0] == '[') { 03551 brackets++; 03552 } else if (vare[0] == ']') { 03553 brackets--; 03554 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03555 needsub++; 03556 vare++; 03557 } 03558 vare++; 03559 } 03560 if (brackets) 03561 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03562 len = vare - vars - 1; 03563 03564 /* Skip totally over expression */ 03565 whereweare += (len + 3); 03566 03567 if (!var) 03568 var = alloca(VAR_BUF_SIZE); 03569 03570 /* Store variable name (and truncate) */ 03571 ast_copy_string(var, vars, len + 1); 03572 03573 /* Substitute if necessary */ 03574 if (needsub) { 03575 size_t used; 03576 if (!ltmp) 03577 ltmp = alloca(VAR_BUF_SIZE); 03578 03579 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03580 vars = ltmp; 03581 } else { 03582 vars = var; 03583 } 03584 03585 length = ast_expr(vars, cp2, count, c); 03586 03587 if (length) { 03588 ast_debug(1, "Expression result is '%s'\n", cp2); 03589 count -= length; 03590 cp2 += length; 03591 *cp2 = 0; 03592 } 03593 } 03594 } 03595 *used = cp2 - orig_cp2; 03596 }
| void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3604 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by add_user_extension(), build_user_routes(), do_say(), dundi_lookup_local(), loopback_subst(), phoneprov_callback(), pp_each_extension_exec(), and pp_each_user_exec().
03605 { 03606 size_t used; 03607 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 03608 }
| static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 4539 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
04540 { 04541 /* Oh joyeous kernel, we're a new thread, with nothing to do but 04542 answer this channel and get it going. 04543 */ 04544 /* NOTE: 04545 The launcher of this function _MUST_ increment 'countcalls' 04546 before invoking the function; it will be decremented when the 04547 PBX has finished running on the channel 04548 */ 04549 struct ast_channel *c = data; 04550 04551 __ast_pbx_run(c, NULL); 04552 decrease_call_count(); 04553 04554 pthread_exit(NULL); 04555 04556 return NULL; 04557 }
| static void print_app_docs | ( | struct ast_app * | aa, | |
| int | fd | |||
| ) | [static] |
Definition at line 5186 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, 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().
05187 { 05188 /* Maximum number of characters added by terminal coloring is 22 */ 05189 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 05190 char seealsotitle[40]; 05191 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 05192 char *seealso = NULL; 05193 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 05194 05195 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 05196 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 05197 05198 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 05199 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 05200 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 05201 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 05202 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 05203 05204 #ifdef AST_XML_DOCS 05205 if (aa->docsrc == AST_XML_DOC) { 05206 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 05207 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 05208 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 05209 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 05210 05211 if (!synopsis || !description || !arguments || !seealso) { 05212 goto return_cleanup; 05213 } 05214 } else 05215 #endif 05216 { 05217 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05218 synopsis = ast_malloc(synopsis_size); 05219 05220 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05221 description = ast_malloc(description_size); 05222 05223 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05224 arguments = ast_malloc(arguments_size); 05225 05226 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05227 seealso = ast_malloc(seealso_size); 05228 05229 if (!synopsis || !description || !arguments || !seealso) { 05230 goto return_cleanup; 05231 } 05232 05233 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 05234 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 05235 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 05236 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 05237 } 05238 05239 /* Handle the syntax the same for both XML and raw docs */ 05240 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05241 if (!(syntax = ast_malloc(syntax_size))) { 05242 goto return_cleanup; 05243 } 05244 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 05245 05246 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 05247 infotitle, syntitle, synopsis, destitle, description, 05248 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 05249 05250 return_cleanup: 05251 ast_free(description); 05252 ast_free(arguments); 05253 ast_free(synopsis); 05254 ast_free(seealso); 05255 ast_free(syntax); 05256 }
| static void print_ext | ( | struct ast_exten * | e, | |
| char * | buf, | |||
| int | buflen | |||
| ) | [static] |
helper function to print an extension
Definition at line 5607 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().
05608 { 05609 int prio = ast_get_extension_priority(e); 05610 if (prio == PRIORITY_HINT) { 05611 snprintf(buf, buflen, "hint: %s", 05612 ast_get_extension_app(e)); 05613 } else { 05614 snprintf(buf, buflen, "%d. %s(%s)", 05615 prio, ast_get_extension_app(e), 05616 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 05617 } 05618 }
| 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 4174 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_raise_exception(), and pbx_builtin_waitexten().
04175 { 04176 ast_channel_lock(c); 04177 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04178 c->priority = pri; 04179 ast_channel_unlock(c); 04180 }
| 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 5772 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().
05773 { 05774 struct ast_context *c = NULL; 05775 int res = 0, old_total_exten = dpc->total_exten; 05776 05777 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 05778 05779 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 05780 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 05781 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 05782 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 05783 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 05784 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 05785 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 05786 ast_rdlock_contexts(); 05787 05788 /* walk all contexts ... */ 05789 while ( (c = ast_walk_contexts(c)) ) { 05790 int context_info_printed = 0; 05791 05792 if (context && strcmp(ast_get_context_name(c), context)) 05793 continue; /* skip this one, name doesn't match */ 05794 05795 dpc->context_existence = 1; 05796 05797 if (!c->pattern_tree) 05798 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 05799 05800 ast_rdlock_context(c); 05801 05802 dpc->total_context++; 05803 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05804 ast_get_context_name(c), ast_get_context_registrar(c)); 05805 context_info_printed = 1; 05806 05807 if (c->pattern_tree) 05808 { 05809 cli_match_char_tree(c->pattern_tree, " ", fd); 05810 } else { 05811 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 05812 } 05813 05814 ast_unlock_context(c); 05815 05816 /* if we print something in context, make an empty line */ 05817 if (context_info_printed) 05818 ast_cli(fd, "\n"); 05819 } 05820 ast_unlock_contexts(); 05821 05822 return (dpc->total_exten == old_total_exten) ? -1 : res; 05823 }
| 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 5621 of file pbx.c.
References ast_cli(), 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(), buf, buf2, 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().
05622 { 05623 struct ast_context *c = NULL; 05624 int res = 0, old_total_exten = dpc->total_exten; 05625 05626 ast_rdlock_contexts(); 05627 05628 /* walk all contexts ... */ 05629 while ( (c = ast_walk_contexts(c)) ) { 05630 struct ast_exten *e; 05631 struct ast_include *i; 05632 struct ast_ignorepat *ip; 05633 char buf[256], buf2[256]; 05634 int context_info_printed = 0; 05635 05636 if (context && strcmp(ast_get_context_name(c), context)) 05637 continue; /* skip this one, name doesn't match */ 05638 05639 dpc->context_existence = 1; 05640 05641 ast_rdlock_context(c); 05642 05643 /* are we looking for exten too? if yes, we print context 05644 * only if we find our extension. 05645 * Otherwise print context even if empty ? 05646 * XXX i am not sure how the rinclude is handled. 05647 * I think it ought to go inside. 05648 */ 05649 if (!exten) { 05650 dpc->total_context++; 05651 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05652 ast_get_context_name(c), ast_get_context_registrar(c)); 05653 context_info_printed = 1; 05654 } 05655 05656 /* walk extensions ... */ 05657 e = NULL; 05658 while ( (e = ast_walk_context_extensions(c, e)) ) { 05659 struct ast_exten *p; 05660 05661 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 05662 continue; /* skip, extension match failed */ 05663 05664 dpc->extension_existence = 1; 05665 05666 /* may we print context info? */ 05667 if (!context_info_printed) { 05668 dpc->total_context++; 05669 if (rinclude) { /* TODO Print more info about rinclude */ 05670 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 05671 ast_get_context_name(c), ast_get_context_registrar(c)); 05672 } else { 05673 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05674 ast_get_context_name(c), ast_get_context_registrar(c)); 05675 } 05676 context_info_printed = 1; 05677 } 05678 dpc->total_prio++; 05679 05680 /* write extension name and first peer */ 05681 if (e->matchcid) 05682 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 05683 else 05684 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 05685 05686 print_ext(e, buf2, sizeof(buf2)); 05687 05688 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 05689 ast_get_extension_registrar(e)); 05690 05691 dpc->total_exten++; 05692 /* walk next extension peers */ 05693 p = e; /* skip the first one, we already got it */ 05694 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05695 const char *el = ast_get_extension_label(p); 05696 dpc->total_prio++; 05697 if (el) 05698 snprintf(buf, sizeof(buf), " [%s]", el); 05699 else 05700 buf[0] = '\0'; 05701 print_ext(p, buf2, sizeof(buf2)); 05702 05703 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 05704 ast_get_extension_registrar(p)); 05705 } 05706 } 05707 05708 /* walk included and write info ... */ 05709 i = NULL; 05710 while ( (i = ast_walk_context_includes(c, i)) ) { 05711 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 05712 if (exten) { 05713 /* Check all includes for the requested extension */ 05714 if (includecount >= AST_PBX_MAX_STACK) { 05715 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 05716 } else { 05717 int dupe = 0; 05718 int x; 05719 for (x = 0; x < includecount; x++) { 05720 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 05721 dupe++; 05722 break; 05723 } 05724 } 05725 if (!dupe) { 05726 includes[includecount] = ast_get_include_name(i); 05727 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 05728 } else { 05729 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 05730 } 05731 } 05732 } else { 05733 ast_cli(fd, " Include => %-45s [%s]\n", 05734 buf, ast_get_include_registrar(i)); 05735 } 05736 } 05737 05738 /* walk ignore patterns and write info ... */ 05739 ip = NULL; 05740 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05741 const char *ipname = ast_get_ignorepat_name(ip); 05742 char ignorepat[AST_MAX_EXTENSION]; 05743 snprintf(buf, sizeof(buf), "'%s'", ipname); 05744 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05745 if (!exten || ast_extension_match(ignorepat, exten)) { 05746 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 05747 buf, ast_get_ignorepat_registrar(ip)); 05748 } 05749 } 05750 if (!rinclude) { 05751 struct ast_sw *sw = NULL; 05752 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05753 snprintf(buf, sizeof(buf), "'%s/%s'", 05754 ast_get_switch_name(sw), 05755 ast_get_switch_data(sw)); 05756 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 05757 buf, ast_get_switch_registrar(sw)); 05758 } 05759 } 05760 05761 ast_unlock_context(c); 05762 05763 /* if we print something in context, make an empty line */ 05764 if (context_info_printed) 05765 ast_cli(fd, "\n"); 05766 } 05767 ast_unlock_contexts(); 05768 05769 return (dpc->total_exten == old_total_exten) ? -1 : res; 05770 }
| 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 2825 of file pbx.c.
References ast_copy_string().
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02826 { 02827 char *ret = workspace; 02828 int lr; /* length of the input string after the copy */ 02829 02830 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 02831 02832 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 02833 02834 /* Quick check if no need to do anything */ 02835 if (offset == 0 && length >= lr) /* take the whole string */ 02836 return ret; 02837 02838 if (offset < 0) { /* translate negative offset into positive ones */ 02839 offset = lr + offset; 02840 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02841 offset = 0; 02842 } 02843 02844 /* too large offset result in empty string so we know what to return */ 02845 if (offset >= lr) 02846 return ret + lr; /* the final '\0' */ 02847 02848 ret += offset; /* move to the start position */ 02849 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 02850 ret[length] = '\0'; 02851 else if (length < 0) { 02852 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 02853 ret[lr + length - offset] = '\0'; 02854 else 02855 ret[0] = '\0'; 02856 } 02857 02858 return ret; 02859 }
| static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1571 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().
01572 { 01573 struct match_char *m3; 01574 struct match_char *m4; 01575 struct ast_exten *e3; 01576 01577 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01578 return node->exten; 01579 } 01580 01581 if (node && node->x[0] == '!' && !node->x[1]) { 01582 return node->exten; 01583 } 01584 01585 if (!node || !node->next_char) { 01586 return NULL; 01587 } 01588 01589 m3 = node->next_char; 01590 01591 if (m3->exten) { 01592 return m3->exten; 01593 } 01594 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01595 if (m4->exten) { 01596 return m4->exten; 01597 } 01598 } 01599 for (m4 = m3; m4; m4 = m4->alt_char) { 01600 e3 = trie_find_next_match(m3); 01601 if (e3) { 01602 return e3; 01603 } 01604 } 01605 return NULL; 01606 }
| static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 6384 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().
06385 { 06386 struct ast_context *context = NULL; 06387 struct ast_exten *eroot = NULL, *e = NULL; 06388 06389 ast_rdlock_contexts(); 06390 while ((context = ast_walk_contexts(context))) { 06391 while ((eroot = ast_walk_context_extensions(context, eroot))) { 06392 while ((e = ast_walk_extension_priorities(eroot, e))) { 06393 if (e->cached_app == app) 06394 e->cached_app = NULL; 06395 } 06396 } 06397 } 06398 ast_unlock_contexts(); 06399 06400 return; 06401 }
| 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 1478 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().
01479 { 01480 /* if this extension is marked as deleted, then skip this -- if it never shows 01481 on the scoreboard, it will never be found, nor will halt the traversal. */ 01482 if (deleted) 01483 return; 01484 board->total_specificity = spec; 01485 board->total_length = length; 01486 board->exten = exten; 01487 board->last_char = last; 01488 board->node = node; 01489 #ifdef NEED_DEBUG_HERE 01490 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01491 #endif 01492 }
| static void wait_for_hangup | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8422 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().
08423 { 08424 int res; 08425 struct ast_frame *f; 08426 double waitsec; 08427 int waittime; 08428 08429 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 08430 waitsec = -1; 08431 if (waitsec > -1) { 08432 waittime = waitsec * 1000.0; 08433 ast_safe_sleep(chan, waittime); 08434 } else do { 08435 res = ast_waitfor(chan, -1); 08436 if (res < 0) 08437 return; 08438 f = ast_read(chan); 08439 if (f) 08440 ast_frfree(f); 08441 } while(f); 08442 }
int autofallthrough = 1 [static] |
Definition at line 1069 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 745 of file pbx.c.
Referenced by pbx_builtin_background().
struct pbx_builtin builtins[] [static] |
Declaration of builtin applications.
Referenced by load_pbx().
ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER [static] |
Lock for the ast_context list
Definition at line 1122 of file pbx.c.
Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().
int conlock_wrlock_version = 0 [static] |
Definition at line 9335 of file pbx.c.
Referenced by ast_wrlock_contexts(), and ast_wrlock_contexts_version().
struct ast_context* contexts [static] |
Definition at line 1119 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 1120 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_merge_contexts_and_delete(), find_context(), find_context_locked(), and pbx_find_extension().
int countcalls [static] |
Definition at line 1077 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
char* days[] [static] |
Definition at line 6910 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 1074 of file pbx.c.
Referenced by load_pbx().
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
{
.name = "EXCEPTION",
.read = acf_exception_read,
}
Definition at line 3048 of file pbx.c.
Referenced by load_pbx().
struct ast_datastore_info exception_store_info [static] |
{
.type = "EXCEPTION",
.destroy = exception_store_free,
}
Definition at line 2990 of file pbx.c.
Referenced by acf_exception_read(), and pbx_builtin_raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1070 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 761 of file pbx.c.
Referenced by ast_extension_state2().
Definition at line 1067 of file pbx.c.
Referenced by handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), and pbx_retrieve_variable().
ast_rwlock_t globalslock = PTHREAD_RWLOCK_INITIALIZER [static] |
Definition at line 1066 of file pbx.c.
Referenced by handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), and pbx_retrieve_variable().
char mandescr_show_dialplan[] [static] |
Definition at line 6147 of file pbx.c.
Referenced by load_pbx().
ast_mutex_t maxcalllock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 1076 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
char* months[] [static] |
Definition at line 6922 of file pbx.c.
Referenced by ast_build_timing().
char* overrideswitch = NULL [static] |
Definition at line 1071 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 6363 of file pbx.c.
Referenced by load_pbx().
struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = (1 << 1) }, [ 'a' ] = { .flag = (1 << 2) }, [ 'v' ] = { .flag = (1 << 0) }, [ 'e' ] = { .flag = (1 << 10) },} [static] |
Definition at line 8561 of file pbx.c.
Referenced by pbx_builtin_resetcdr().
int stateid = 1 [static] |
Definition at line 1128 of file pbx.c.
Referenced by ast_extension_state_add().
struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } [static] |
Definition at line 760 of file pbx.c.
Referenced by pbx_find_extension().
int totalcalls [static] |
Definition at line 1078 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 753 of file pbx.c.
Referenced by pbx_builtin_waitexten().
1.6.2