Core PBX routines. More...
#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <sys/sysinfo.h>
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/cel.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
struct | acf_root |
struct | app_tmp |
struct | apps |
struct | ast_app |
ast_app: A registered application More... | |
struct | ast_context |
ast_context: An extension context More... | |
struct | ast_custom_escalating_function |
Extra information for an ast_custom_function holding privilege escalation information. Kept in a separate structure for ABI compatibility. More... | |
struct | ast_exten |
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
struct | ast_hint |
Structure for dial plan hints. More... | |
struct | ast_ignorepat |
ast_ignorepat: Ignore patterns in dial plan More... | |
struct | ast_include |
ast_include: include= support in extensions.conf More... | |
struct | ast_state_cb |
ast_state_cb: An extension state notify register item More... | |
struct | ast_sw |
ast_sw: Switch statement in extensions.conf More... | |
struct | async_stat |
struct | cfextension_states |
struct | dialplan_counters |
Counters for the show dialplan manager command. More... | |
struct | escalation_root |
struct | fake_context |
struct | match_char |
match_char: forms a syntax tree for quick matching of extension patterns More... | |
struct | pattern_node |
struct | pbx_builtin |
Declaration of builtin applications. More... | |
struct | pbx_exception |
struct | scoreboard |
struct | statechange |
struct | store_hint |
struct | store_hints |
struct | switches |
Defines | |
#define | BACKGROUND_MATCHEXTEN (1 << 2) |
#define | BACKGROUND_NOANSWER (1 << 1) |
#define | BACKGROUND_PLAYBACK (1 << 3) |
#define | BACKGROUND_SKIP (1 << 0) |
#define | BITS_PER 8 |
#define | EXT_DATA_SIZE 8192 |
#define | HASH_EXTENHINT_SIZE 563 |
#define | INC_DST_OVERFLOW_CHECK |
#define | NEW_MATCHER_CHK_MATCH |
#define | NEW_MATCHER_RECURSE |
#define | SAY_STUBS |
#define | STATUS_NO_CONTEXT 1 |
#define | STATUS_NO_EXTENSION 2 |
#define | STATUS_NO_LABEL 4 |
#define | STATUS_NO_PRIORITY 3 |
#define | STATUS_SUCCESS 5 |
#define | SWITCH_DATA_LENGTH 256 |
#define | VAR_BUF_SIZE 4096 |
#define | VAR_HARDTRAN 3 |
#define | VAR_NORMAL 1 |
#define | VAR_SOFTTRAN 2 |
#define | WAITEXTEN_DIALTONE (1 << 1) |
#define | WAITEXTEN_MOH (1 << 0) |
Functions | |
void | __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar) |
int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
Register a custom function. | |
int | __ast_custom_function_register_escalating (struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod) |
Register a custom function which requires escalated privileges. | |
static int | __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async) |
static void | __ast_internal_context_destroy (struct ast_context *con) |
static enum ast_pbx_result | __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args) |
static void | __init_extensionstate_buf (void) |
static void | __init_switch_data (void) |
static void | __init_thread_inhibit_escalations_tl (void) |
A thread local indicating whether the current thread can run 'dangerous' dialplan functions. | |
static int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static int | acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
static int | acf_retrieve_docs (struct ast_custom_function *acf) |
static struct match_char * | add_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly) |
static struct match_char * | add_pattern_node (struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr) |
static int | add_priority (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace) |
add the extension in the priority chain. | |
static struct match_char * | already_in_tree (struct match_char *current, char *pat, int is_pattern) |
int | ast_active_calls (void) |
Retrieve the number of active calls. | |
int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add and extension to an extension context. | |
int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Main interface to add extensions to the list for out context. | |
static int | ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int lock_context) |
Same as ast_add_extension2() but controls the context locking. | |
static int | ast_add_extension_nolock (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
static int | ast_add_hint (struct ast_exten *e) |
Add hint to hint list, check initial extension state. | |
int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
Set the channel to next execute the specified dialplan location. | |
int | ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority) |
Set the channel to next execute the specified dialplan location. | |
int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_build_timing (struct ast_timing *i, const char *info_in) |
Construct a timing bitmap, for use in time-based conditionals. | |
int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks for a valid matching extension. | |
static int | ast_change_hint (struct ast_exten *oe, struct ast_exten *ne) |
Change hint for an extension. | |
int | ast_check_timing (const struct ast_timing *i) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified. | |
int | ast_check_timing2 (const struct ast_timing *i, const struct timeval tv) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified. | |
char * | ast_complete_applications (const char *line, const char *word, int state) |
Command completion for the list of installed applications. | |
int | ast_context_add_ignorepat (const char *context, const char *value, const char *registrar) |
Add an ignorepat. | |
int | ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar) |
int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
Add a context include. | |
int | ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar) |
Add a context include. | |
int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
Add a switch. | |
int | ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar) |
Adds a switch (first param is a ast_context). | |
void | ast_context_destroy (struct ast_context *con, const char *registrar) |
Destroy a context (matches the specified context (or ANY context if NULL). | |
struct ast_context * | ast_context_find (const char *name) |
Find a context. | |
struct ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
Register a new context or find an existing one. | |
int | ast_context_lockmacro (const char *context) |
locks the macrolock in the given given context | |
int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
Simply remove extension from context. | |
int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar) |
int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked) |
int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ... | |
int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault. | |
int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
Remove a switch. | |
int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
This function locks given context, removes switch, unlock context and return. | |
int | ast_context_unlockmacro (const char *context) |
Unlocks the macrolock in the given context. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
struct ast_custom_function * | ast_custom_function_find (const char *name) |
int | ast_custom_function_unregister (struct ast_custom_function *acf) |
Unregister a custom function. | |
int | ast_destroy_timing (struct ast_timing *i) |
Deallocates memory structures associated with a timing bitmap. | |
enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
Map devstate to an extension state. | |
int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Determine whether an extension exists. | |
int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_extension_close (const char *pattern, const char *data, int needmore) |
int | ast_extension_cmp (const char *a, const char *b) |
Determine if one extension should match before another. | |
int | ast_extension_match (const char *pattern, const char *data) |
Determine if a given extension matches a given pattern (in NXX format). | |
int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
Check extension state for an extension by using hint. | |
static int | ast_extension_state2 (struct ast_exten *e) |
Check state of extension by using hints. | |
const char * | ast_extension_state2str (int extension_state) |
Return extension_state as string. | |
static int | ast_extension_state3 (struct ast_str *hint_app) |
int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data) |
Add watcher for extension states. | |
int | ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data) |
Add watcher for extension states with destructor. | |
int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
ast_extension_state_del: Remove a watcher from the callback list | |
int | ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
Find the priority of an extension that has the specified label. | |
int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
Find the priority of an extension that has the specified label. | |
int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
executes a read operation on a function | |
int | ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen) |
executes a read operation on a function | |
int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
executes a write operation on a function | |
const char * | ast_get_context_name (struct ast_context *con) |
const char * | ast_get_context_registrar (struct ast_context *c) |
const char * | ast_get_extension_app (struct ast_exten *e) |
void * | ast_get_extension_app_data (struct ast_exten *e) |
const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
struct ast_context * | ast_get_extension_context (struct ast_exten *exten) |
const char * | ast_get_extension_label (struct ast_exten *exten) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
const char * | ast_get_extension_name (struct ast_exten *exten) |
int | ast_get_extension_priority (struct ast_exten *exten) |
const char * | ast_get_extension_registrar (struct ast_exten *e) |
int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
Get hint for channel. | |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *inc) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_data (struct ast_sw *sw) |
int | ast_get_switch_eval (struct ast_sw *sw) |
const char * | ast_get_switch_name (struct ast_sw *sw) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b) |
hashtable functions for contexts | |
unsigned int | ast_hashtab_hash_contexts (const void *obj) |
static struct ast_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
static struct ast_exten * | ast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten) |
Find hint for given extension in context. | |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_pbx_init (void) |
int | ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
static int | ast_pbx_outgoing_cdr_failed (void) |
Function to post an empty cdr after a spool call fails. | |
int | ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) |
enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
static void * | ast_pbx_run_app (void *data) |
run the application and free the descriptor once done | |
enum ast_pbx_result | ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args) |
Execute the PBX in the current thread. | |
enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
Create a new thread and start the PBX. | |
int | ast_processed_calls (void) |
Retrieve the total number of calls processed through the PBX since last restart. | |
int | ast_rdlock_context (struct ast_context *con) |
Read locks a given context. | |
int | ast_rdlock_contexts (void) |
Read locks the context list. | |
int | ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod) |
Dynamically register a new dial plan application. | |
int | ast_register_switch (struct ast_switch *sw) |
Register an alternative dialplan switch. | |
static int | ast_remove_hint (struct ast_exten *e) |
Remove hint from extension. | |
int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn) |
Launch a new extension (i.e. new stack). | |
int | ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten) |
Get hint for channel. | |
const char * | ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var) |
void | ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ) |
void | ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used) |
void | ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ) |
static const char * | ast_str_substring (struct ast_str *value, int offset, int length) |
int | ast_thread_inhibit_escalations (void) |
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect. | |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts (void) |
Unlocks contexts. | |
int | ast_unregister_application (const char *app) |
Unregister an application. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
struct ast_context * | ast_walk_contexts (struct ast_context *con) |
struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
int | ast_wrlock_context (struct ast_context *con) |
Write locks a given context. | |
int | ast_wrlock_contexts (void) |
Write locks the context list. | |
static void * | async_wait (void *data) |
static void | cli_match_char_tree (struct match_char *node, char *prefix, int fd) |
static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
collect digits from the channel into the buffer. | |
static int | compare_char (const void *a, const void *b) |
static char * | complete_core_show_hint (const char *line, const char *word, int pos, int state) |
autocomplete for CLI command 'core show hint' | |
static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
static void | context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar) |
static void | context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar) |
static void | create_match_char_tree (struct ast_context *con) |
static void | decrease_call_count (void) |
static void | destroy_exten (struct ast_exten *e) |
static void | destroy_hint (void *obj) |
static void | destroy_pattern_tree (struct match_char *pattern_tree) |
static void | destroy_state_cb (void *doomed) |
static void | device_state_cb (const struct ast_event *event, void *unused) |
static void | exception_store_free (void *data) |
static int | ext_cmp (const char *left, const char *right) |
static int | ext_cmp_exten (const char *left, const char *right) |
static int | ext_cmp_exten_partial (const char *left, const char *right) |
static int | ext_cmp_exten_strlen (const char *str) |
static int | ext_cmp_pattern (const char *left, const char *right) |
static int | ext_cmp_pattern_pos (const char **p, unsigned char *bitwise) |
helper functions to sort extension patterns in the desired way, so that more specific patterns appear first. | |
static int | ext_strncpy (char *dst, const char *src, int len) |
copy a string skipping whitespace | |
static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static struct ast_context * | find_context (const char *context) |
lookup for a context with a given name, | |
static struct ast_context * | find_context_locked (const char *context) |
lookup for a context with a given name, | |
static int | find_hint_by_cb_id (void *obj, void *arg, int flags) |
Remove a watcher from the callback list. | |
static char * | func_args (char *function) |
return a pointer to the arguments of the function, and terminates the function name with '\0' | |
static struct ast_exten * | get_canmatch_exten (struct match_char *node) |
static const char * | get_pattern_node (struct pattern_node *node, const char *src, int pattern, const char *extenbuf) |
static unsigned | get_range (char *src, int max, const char *const names[], const char *msg) |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
static void | get_timerange (struct ast_timing *i, char *times) |
store a bitmask of valid times, one bit each 1 minute | |
static char * | handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Send ack once. | |
static char * | handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI support for listing chanvar's variables in a parseable way. | |
static char * | handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI support for listing global variables in a parseable way. | |
static char * | handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_hint: CLI support for listing registered dial plan hint | |
static char * | handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_hints: CLI support for listing registered dial plan hints | |
static char * | handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_switches: CLI support for listing registered dial plan switches | |
static int | handle_statechange (void *datap) |
static char * | handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | hashtab_compare_exten_labels (const void *ah_a, const void *ah_b) |
static int | hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b) |
static int | hashtab_compare_extens (const void *ha_a, const void *ah_b) |
static unsigned int | hashtab_hash_extens (const void *obj) |
static unsigned int | hashtab_hash_labels (const void *obj) |
static unsigned int | hashtab_hash_priority (const void *obj) |
static int | hint_cmp (void *obj, void *arg, int flags) |
static int | hint_hash (const void *obj, const int flags) |
static int | hint_id_cmp (void *obj, void *arg, int flags) |
static int | hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
static int | include_valid (struct ast_include *i) |
static int | increase_call_count (const struct ast_channel *c) |
Increase call count for channel. | |
static void | insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node) |
static int | is_read_allowed (struct ast_custom_function *acfptr) |
Determines whether execution of a custom function's read function is allowed. | |
static int | is_write_allowed (struct ast_custom_function *acfptr) |
Determines whether execution of a custom function's write function is allowed. | |
int | load_pbx (void) |
static int | lookup_name (const char *s, const char *const names[], int max) |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
static void | manager_dpsendack (struct mansession *s, const struct message *m) |
Send ack once. | |
static int | manager_show_dialplan (struct mansession *s, const struct message *m) |
Manager listing of dial plan. | |
static int | manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude) |
Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not. | |
static int | matchcid (const char *cidpattern, const char *callerid) |
static void | new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action) |
static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
extract offset:length from variable name. | |
static int | pbx_builtin_answer (struct ast_channel *, const char *) |
static int | pbx_builtin_background (struct ast_channel *, const char *) |
static int | pbx_builtin_busy (struct ast_channel *, const char *) |
void | pbx_builtin_clear_globals (void) |
static int | pbx_builtin_congestion (struct ast_channel *, const char *) |
static int | pbx_builtin_execiftime (struct ast_channel *, const char *) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
Return a pointer to the value of the corresponding channel variable. | |
static int | pbx_builtin_goto (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoif (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoiftime (struct ast_channel *, const char *) |
static int | pbx_builtin_hangup (struct ast_channel *, const char *) |
static int | pbx_builtin_importvar (struct ast_channel *, const char *) |
static int | pbx_builtin_incomplete (struct ast_channel *, const char *) |
static int | pbx_builtin_noop (struct ast_channel *, const char *) |
static int | pbx_builtin_proceeding (struct ast_channel *, const char *) |
static int | pbx_builtin_progress (struct ast_channel *, const char *) |
void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, without removing any previously set value. | |
int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason) |
static int | pbx_builtin_resetcdr (struct ast_channel *, const char *) |
static int | pbx_builtin_ringing (struct ast_channel *, const char *) |
static int | pbx_builtin_saycharacters (struct ast_channel *, const char *) |
static int | pbx_builtin_saydigits (struct ast_channel *, const char *) |
static int | pbx_builtin_saynumber (struct ast_channel *, const char *) |
static int | pbx_builtin_sayphonetic (struct ast_channel *, const char *) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
Create a human-readable string, specifying all variables and their corresponding values. | |
static int | pbx_builtin_setamaflags (struct ast_channel *, const char *) |
int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
static int | pbx_builtin_wait (struct ast_channel *, const char *) |
static int | pbx_builtin_waitexten (struct ast_channel *, const char *) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
static void | pbx_destroy (struct ast_pbx *p) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
Execute an application. | |
static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn) |
The return value depends on the action:. | |
struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
struct ast_app * | pbx_findapp (const char *app) |
Find application handle in linked list. | |
static struct ast_switch * | pbx_findswitch (const char *sw) |
void | pbx_live_dangerously (int new_live_dangerously) |
Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.). | |
static int | pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async) |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
Support for Asterisk built-in variables in the dialplan. | |
int | pbx_set_autofallthrough (int newval) |
int | pbx_set_extenpatternmatchnew (int newval) |
void | pbx_set_overrideswitch (const char *newval) |
static void | pbx_shutdown (void) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
static void * | pbx_thread (void *data) |
static void | print_app_docs (struct ast_app *aa, int fd) |
static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
helper function to print an extension | |
static int | raise_exception (struct ast_channel *chan, const char *reason, int priority) |
static int | read_escalates (const struct ast_custom_function *acf) |
Returns true if given custom function escalates privileges on read. | |
static void | set_ext_pri (struct ast_channel *c, const char *exten, int pri) |
static int | show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static int | show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static int | statecbs_cmp (void *obj, void *arg, int flags) |
static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
takes a substring. It is ok to call with value == workspace. | |
static int | testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value) |
static int | thread_inhibits_escalations (void) |
Indicates whether the current thread inhibits the execution of dangerous functions. | |
static struct ast_exten * | trie_find_next_match (struct match_char *node) |
static void | unload_pbx (void) |
static void | unreference_cached_app (struct ast_app *app) |
static void | update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node) |
static void | wait_for_hangup (struct ast_channel *chan, const void *data) |
static int | write_escalates (const struct ast_custom_function *acf) |
Returns true if given custom function escalates privileges on write. | |
Variables | |
static int | autofallthrough = 1 |
static struct ast_app_option | background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} |
static struct pbx_builtin | builtins [] |
Declaration of builtin applications. | |
static ast_mutex_t | conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Lock for the ast_context list. | |
static ast_mutex_t | context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete. | |
static struct ast_context * | contexts |
static struct ast_hashtab * | contexts_table = NULL |
static int | countcalls |
static const char *const | days [] |
static struct ast_event_sub * | device_state_sub |
Subscription for device state change events. | |
static struct ast_taskprocessor * | device_state_tps |
static struct ast_custom_function | exception_function |
static struct ast_datastore_info | exception_store_info |
static int | extenpatternmatchnew = 0 |
static struct cfextension_states | extension_states [] |
static struct ast_threadstorage | extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } |
static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
static ast_rwlock_t | globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } |
static struct ao2_container * | hints |
static struct ast_data_handler | hints_data_provider |
static int | live_dangerously |
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. | |
static ast_mutex_t | maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static const char *const | months [] |
static char * | overrideswitch = NULL |
static struct ast_cli_entry | pbx_cli [] |
static struct ast_data_entry | pbx_data_providers [] |
static struct ast_app_option | resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} |
static struct ao2_container * | statecbs |
static int | stateid = 1 |
static struct ast_threadstorage | switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } |
static struct ast_custom_function | testtime_function |
static struct ast_threadstorage | thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , } |
static int | totalcalls |
static struct ast_app_option | waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} |
Core PBX routines.
Definition in file pbx.c.
#define BACKGROUND_MATCHEXTEN (1 << 2) |
Definition at line 799 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_NOANSWER (1 << 1) |
Definition at line 798 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_PLAYBACK (1 << 3) |
Definition at line 800 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_SKIP (1 << 0) |
Definition at line 797 of file pbx.c.
Referenced by pbx_builtin_background().
#define BITS_PER 8 |
Referenced by ext_cmp_pattern_pos().
#define EXT_DATA_SIZE 8192 |
The speed of extension handling will likely be among the most important aspects of this PBX. The switching scheme as it exists right now isn't terribly bad (it's O(N+M), where N is the # of extensions and M is the avg # of priorities, but a constant search time here would be great ;-)
A new algorithm to do searching based on a 'compiled' pattern tree is introduced here, and shows a fairly flat (constant) search time, even for over 10000 patterns.
Also, using a hash table for context/priority name lookup can help prevent the find_extension routines from absorbing exponential cpu cycles as the number of contexts/priorities grow. I've previously tested find_extension with red-black trees, which have O(log2(n)) speed. Right now, I'm using hash tables, which do searches (ideally) in O(1) time. While these techniques do not yield much speed in small dialplans, they are worth the trouble in large dialplans.
Definition at line 786 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
#define HASH_EXTENHINT_SIZE 563 |
Definition at line 986 of file pbx.c.
Referenced by ast_pbx_init().
#define INC_DST_OVERFLOW_CHECK |
Referenced by get_pattern_node().
#define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
#define NEW_MATCHER_RECURSE |
Referenced by new_find_extension().
#define VAR_BUF_SIZE 4096 |
Definition at line 791 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_DIALTONE (1 << 1) |
Definition at line 810 of file pbx.c.
Referenced by pbx_builtin_waitexten().
#define WAITEXTEN_MOH (1 << 0) |
Definition at line 809 of file pbx.c.
Referenced by pbx_builtin_waitexten().
void __ast_context_destroy | ( | struct ast_context * | list, | |
struct ast_hashtab * | contexttab, | |||
struct ast_context * | con, | |||
const char * | registrar | |||
) |
Definition at line 9672 of file pbx.c.
References __ast_internal_context_destroy(), ast_context::alts, ast_context_remove_extension_callerid2(), ast_copy_string(), ast_debug, ast_free, ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_remove_this_object(), ast_hashtab_start_traversal(), AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_MAX_EXTENSION, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ast_context::ignorepats, ast_context::includes, ast_exten::matchcid, ast_context::name, ast_include::next, ast_ignorepat::next, ast_context::next, ast_sw::next, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_context_destroy().
09673 { 09674 struct ast_context *tmp, *tmpl=NULL; 09675 struct ast_exten *exten_item, *prio_item; 09676 09677 for (tmp = list; tmp; ) { 09678 struct ast_context *next = NULL; /* next starting point */ 09679 /* The following code used to skip forward to the next 09680 context with matching registrar, but this didn't 09681 make sense; individual priorities registrar'd to 09682 the matching registrar could occur in any context! */ 09683 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 09684 if (con) { 09685 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 09686 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 09687 if ( !strcasecmp(tmp->name, con->name) ) { 09688 break; /* found it */ 09689 } 09690 } 09691 } 09692 09693 if (!tmp) /* not found, we are done */ 09694 break; 09695 ast_wrlock_context(tmp); 09696 09697 if (registrar) { 09698 /* then search thru and remove any extens that match registrar. */ 09699 struct ast_hashtab_iter *exten_iter; 09700 struct ast_hashtab_iter *prio_iter; 09701 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 09702 struct ast_include *i, *pi = NULL, *ni = NULL; 09703 struct ast_sw *sw = NULL; 09704 09705 /* remove any ignorepats whose registrar matches */ 09706 for (ip = tmp->ignorepats; ip; ip = ipn) { 09707 ipn = ip->next; 09708 if (!strcmp(ip->registrar, registrar)) { 09709 if (ipl) { 09710 ipl->next = ip->next; 09711 ast_free(ip); 09712 continue; /* don't change ipl */ 09713 } else { 09714 tmp->ignorepats = ip->next; 09715 ast_free(ip); 09716 continue; /* don't change ipl */ 09717 } 09718 } 09719 ipl = ip; 09720 } 09721 /* remove any includes whose registrar matches */ 09722 for (i = tmp->includes; i; i = ni) { 09723 ni = i->next; 09724 if (strcmp(i->registrar, registrar) == 0) { 09725 /* remove from list */ 09726 if (pi) { 09727 pi->next = i->next; 09728 /* free include */ 09729 ast_free(i); 09730 continue; /* don't change pi */ 09731 } else { 09732 tmp->includes = i->next; 09733 /* free include */ 09734 ast_free(i); 09735 continue; /* don't change pi */ 09736 } 09737 } 09738 pi = i; 09739 } 09740 /* remove any switches whose registrar matches */ 09741 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 09742 if (strcmp(sw->registrar,registrar) == 0) { 09743 AST_LIST_REMOVE_CURRENT(list); 09744 ast_free(sw); 09745 } 09746 } 09747 AST_LIST_TRAVERSE_SAFE_END; 09748 09749 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 09750 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 09751 while ((exten_item=ast_hashtab_next(exten_iter))) { 09752 int end_traversal = 1; 09753 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 09754 while ((prio_item=ast_hashtab_next(prio_iter))) { 09755 char extension[AST_MAX_EXTENSION]; 09756 char cidmatch[AST_MAX_EXTENSION]; 09757 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 09758 continue; 09759 } 09760 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 09761 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 09762 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 09763 if (prio_item->cidmatch) { 09764 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 09765 } 09766 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1); 09767 } 09768 /* Explanation: 09769 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 09770 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 09771 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 09772 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 09773 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 09774 * free the iterator 09775 */ 09776 if (end_traversal) { 09777 ast_hashtab_end_traversal(prio_iter); 09778 } else { 09779 ast_free(prio_iter); 09780 } 09781 } 09782 ast_hashtab_end_traversal(exten_iter); 09783 } 09784 09785 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 09786 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 09787 another registrar. It's not empty if there are any extensions */ 09788 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 09789 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09790 ast_hashtab_remove_this_object(contexttab, tmp); 09791 09792 next = tmp->next; 09793 if (tmpl) 09794 tmpl->next = next; 09795 else 09796 contexts = next; 09797 /* Okay, now we're safe to let it go -- in a sense, we were 09798 ready to let it go as soon as we locked it. */ 09799 ast_unlock_context(tmp); 09800 __ast_internal_context_destroy(tmp); 09801 } else { 09802 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 09803 tmp->refcount, tmp->root); 09804 ast_unlock_context(tmp); 09805 next = tmp->next; 09806 tmpl = tmp; 09807 } 09808 } else if (con) { 09809 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 09810 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09811 ast_hashtab_remove_this_object(contexttab, tmp); 09812 09813 next = tmp->next; 09814 if (tmpl) 09815 tmpl->next = next; 09816 else 09817 contexts = next; 09818 /* Okay, now we're safe to let it go -- in a sense, we were 09819 ready to let it go as soon as we locked it. */ 09820 ast_unlock_context(tmp); 09821 __ast_internal_context_destroy(tmp); 09822 } 09823 09824 /* if we have a specific match, we are done, otherwise continue */ 09825 tmp = con ? NULL : next; 09826 } 09827 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3900 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by __ast_custom_function_register_escalating(), and load_pbx().
03901 { 03902 struct ast_custom_function *cur; 03903 char tmps[80]; 03904 03905 if (!acf) { 03906 return -1; 03907 } 03908 03909 acf->mod = mod; 03910 #ifdef AST_XML_DOCS 03911 acf->docsrc = AST_STATIC_DOC; 03912 #endif 03913 03914 if (acf_retrieve_docs(acf)) { 03915 return -1; 03916 } 03917 03918 AST_RWLIST_WRLOCK(&acf_root); 03919 03920 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03921 if (!strcmp(acf->name, cur->name)) { 03922 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03923 AST_RWLIST_UNLOCK(&acf_root); 03924 return -1; 03925 } 03926 } 03927 03928 /* Store in alphabetical order */ 03929 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03930 if (strcasecmp(acf->name, cur->name) < 0) { 03931 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03932 break; 03933 } 03934 } 03935 AST_RWLIST_TRAVERSE_SAFE_END; 03936 03937 if (!cur) { 03938 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03939 } 03940 03941 AST_RWLIST_UNLOCK(&acf_root); 03942 03943 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03944 03945 return 0; 03946 }
int __ast_custom_function_register_escalating | ( | struct ast_custom_function * | acf, | |
enum ast_custom_function_escalation | escalation, | |||
struct ast_module * | mod | |||
) |
Register a custom function which requires escalated privileges.
Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).
Definition at line 3948 of file pbx.c.
References __ast_custom_function_register(), ast_custom_escalating_function::acf, ast_calloc, AST_CFE_BOTH, AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, ast_custom_function_unregister(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_custom_escalating_function::read_escalates, and ast_custom_escalating_function::write_escalates.
03949 { 03950 struct ast_custom_escalating_function *acf_escalation = NULL; 03951 int res; 03952 03953 res = __ast_custom_function_register(acf, mod); 03954 if (res != 0) { 03955 return -1; 03956 } 03957 03958 if (escalation == AST_CFE_NONE) { 03959 /* No escalations; no need to do anything else */ 03960 return 0; 03961 } 03962 03963 acf_escalation = ast_calloc(1, sizeof(*acf_escalation)); 03964 if (!acf_escalation) { 03965 ast_custom_function_unregister(acf); 03966 return -1; 03967 } 03968 03969 acf_escalation->acf = acf; 03970 switch (escalation) { 03971 case AST_CFE_NONE: 03972 break; 03973 case AST_CFE_READ: 03974 acf_escalation->read_escalates = 1; 03975 break; 03976 case AST_CFE_WRITE: 03977 acf_escalation->write_escalates = 1; 03978 break; 03979 case AST_CFE_BOTH: 03980 acf_escalation->read_escalates = 1; 03981 acf_escalation->write_escalates = 1; 03982 break; 03983 } 03984 03985 AST_RWLIST_WRLOCK(&escalation_root); 03986 AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list); 03987 AST_RWLIST_UNLOCK(&escalation_root); 03988 03989 return 0; 03990 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 11099 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, ast_party_id::number, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
11100 { 11101 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 11102 11103 if (!chan) 11104 return -2; 11105 11106 if (context == NULL) 11107 context = chan->context; 11108 if (exten == NULL) 11109 exten = chan->exten; 11110 11111 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 11112 if (ast_exists_extension(chan, context, exten, priority, 11113 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 11114 return goto_func(chan, context, exten, priority); 11115 else { 11116 return AST_PBX_GOTO_FAILED; 11117 } 11118 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 9624 of file pbx.c.
References ast_context::alts, ast_free, ast_hashtab_destroy(), AST_LIST_REMOVE_HEAD, ast_mutex_destroy, ast_rwlock_destroy, destroy_exten(), destroy_pattern_tree(), el, ast_context::ignorepats, ast_context::includes, ast_context::lock, ast_context::macrolock, ast_exten::next, ast_ignorepat::next, ast_include::next, ast_context::pattern_tree, ast_exten::peer, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().
09625 { 09626 struct ast_include *tmpi; 09627 struct ast_sw *sw; 09628 struct ast_exten *e, *el, *en; 09629 struct ast_ignorepat *ipi; 09630 struct ast_context *tmp = con; 09631 09632 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 09633 struct ast_include *tmpil = tmpi; 09634 tmpi = tmpi->next; 09635 ast_free(tmpil); 09636 } 09637 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 09638 struct ast_ignorepat *ipl = ipi; 09639 ipi = ipi->next; 09640 ast_free(ipl); 09641 } 09642 if (tmp->registrar) 09643 ast_free(tmp->registrar); 09644 09645 /* destroy the hash tabs */ 09646 if (tmp->root_table) { 09647 ast_hashtab_destroy(tmp->root_table, 0); 09648 } 09649 /* and destroy the pattern tree */ 09650 if (tmp->pattern_tree) 09651 destroy_pattern_tree(tmp->pattern_tree); 09652 09653 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 09654 ast_free(sw); 09655 for (e = tmp->root; e;) { 09656 for (en = e->peer; en;) { 09657 el = en; 09658 en = en->peer; 09659 destroy_exten(el); 09660 } 09661 el = e; 09662 e = e->next; 09663 destroy_exten(el); 09664 } 09665 tmp->root = NULL; 09666 ast_rwlock_destroy(&tmp->lock); 09667 ast_mutex_destroy(&tmp->macrolock); 09668 ast_free(tmp); 09669 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 5427 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_copy_string(), ast_debug, ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_free, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_opt_end_cdr_before_h_exten, AST_PBX_ERROR, AST_PBX_INCOMPLETE, ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verb, autofallthrough, ast_channel::caller, ast_channel::cdr, collect_digits(), ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_pbx_args::no_hangup_chan, ast_party_id::number, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, raise_exception(), ast_pbx::rtimeoutms, S_COR, set_ext_pri(), status, ast_party_number::str, ast_party_number::valid, and ast_channel::whentohangup.
Referenced by ast_pbx_run_args(), and pbx_thread().
05429 { 05430 int found = 0; /* set if we find at least one match */ 05431 int res = 0; 05432 int autoloopflag; 05433 int error = 0; /* set an error conditions */ 05434 05435 /* A little initial setup here */ 05436 if (c->pbx) { 05437 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 05438 /* XXX and now what ? */ 05439 ast_free(c->pbx); 05440 } 05441 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 05442 return -1; 05443 /* Set reasonable defaults */ 05444 c->pbx->rtimeoutms = 10000; 05445 c->pbx->dtimeoutms = 5000; 05446 05447 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 05448 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 05449 05450 /* Start by trying whatever the channel is set to */ 05451 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05452 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05453 /* If not successful fall back to 's' */ 05454 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); 05455 /* XXX the original code used the existing priority in the call to 05456 * ast_exists_extension(), and reset it to 1 afterwards. 05457 * I believe the correct thing is to set it to 1 immediately. 05458 */ 05459 set_ext_pri(c, "s", 1); 05460 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05461 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05462 /* JK02: And finally back to default if everything else failed */ 05463 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); 05464 ast_copy_string(c->context, "default", sizeof(c->context)); 05465 } 05466 } 05467 ast_channel_lock(c); 05468 if (c->cdr) { 05469 /* allow CDR variables that have been collected after channel was created to be visible during call */ 05470 ast_cdr_update(c); 05471 } 05472 ast_channel_unlock(c); 05473 for (;;) { 05474 char dst_exten[256]; /* buffer to accumulate digits */ 05475 int pos = 0; /* XXX should check bounds */ 05476 int digit = 0; 05477 int invalid = 0; 05478 int timeout = 0; 05479 05480 /* No digits pressed yet */ 05481 dst_exten[pos] = '\0'; 05482 05483 /* loop on priorities in this context/exten */ 05484 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05485 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05486 &found, 1))) { 05487 if (!ast_check_hangup(c)) { 05488 ++c->priority; 05489 continue; 05490 } 05491 05492 /* Check softhangup flags. */ 05493 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05494 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05495 continue; 05496 } 05497 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05498 if (ast_exists_extension(c, c->context, "T", 1, 05499 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05500 set_ext_pri(c, "T", 1); 05501 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05502 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05503 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05504 continue; 05505 } else if (ast_exists_extension(c, c->context, "e", 1, 05506 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05507 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05508 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05509 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05510 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05511 continue; 05512 } 05513 05514 /* Call timed out with no special extension to jump to. */ 05515 error = 1; 05516 break; 05517 } 05518 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 05519 c->exten, c->priority); 05520 error = 1; 05521 break; 05522 } /* end while - from here on we can use 'break' to go out */ 05523 if (found && res) { 05524 /* Something bad happened, or a hangup has been requested. */ 05525 if (strchr("0123456789ABCDEF*#", res)) { 05526 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 05527 pos = 0; 05528 dst_exten[pos++] = digit = res; 05529 dst_exten[pos] = '\0'; 05530 } else if (res == AST_PBX_INCOMPLETE) { 05531 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05532 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05533 05534 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 05535 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 05536 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05537 invalid = 1; 05538 } else { 05539 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 05540 digit = 1; 05541 pos = strlen(dst_exten); 05542 } 05543 } else { 05544 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05545 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05546 05547 if ((res == AST_PBX_ERROR) 05548 && ast_exists_extension(c, c->context, "e", 1, 05549 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05550 /* if we are already on the 'e' exten, don't jump to it again */ 05551 if (!strcmp(c->exten, "e")) { 05552 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); 05553 error = 1; 05554 } else { 05555 raise_exception(c, "ERROR", 1); 05556 continue; 05557 } 05558 } 05559 05560 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05561 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05562 continue; 05563 } 05564 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05565 if (ast_exists_extension(c, c->context, "T", 1, 05566 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05567 set_ext_pri(c, "T", 1); 05568 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05569 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05570 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05571 continue; 05572 } else if (ast_exists_extension(c, c->context, "e", 1, 05573 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05574 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05575 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05576 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05577 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05578 continue; 05579 } 05580 /* Call timed out with no special extension to jump to. */ 05581 } 05582 ast_channel_lock(c); 05583 if (c->cdr) { 05584 ast_cdr_update(c); 05585 } 05586 ast_channel_unlock(c); 05587 error = 1; 05588 break; 05589 } 05590 } 05591 if (error) 05592 break; 05593 05594 /*!\note 05595 * We get here on a failure of some kind: non-existing extension or 05596 * hangup. We have options, here. We can either catch the failure 05597 * and continue, or we can drop out entirely. */ 05598 05599 if (invalid 05600 || (ast_strlen_zero(dst_exten) && 05601 !ast_exists_extension(c, c->context, c->exten, 1, 05602 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) { 05603 /*!\note 05604 * If there is no match at priority 1, it is not a valid extension anymore. 05605 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 05606 * neither exist. 05607 */ 05608 if (ast_exists_extension(c, c->context, "i", 1, 05609 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05610 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 05611 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 05612 set_ext_pri(c, "i", 1); 05613 } else if (ast_exists_extension(c, c->context, "e", 1, 05614 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05615 raise_exception(c, "INVALID", 1); 05616 } else { 05617 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 05618 c->name, c->exten, c->context); 05619 error = 1; /* we know what to do with it */ 05620 break; 05621 } 05622 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05623 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 05624 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05625 } else { /* keypress received, get more digits for a full extension */ 05626 int waittime = 0; 05627 if (digit) 05628 waittime = c->pbx->dtimeoutms; 05629 else if (!autofallthrough) 05630 waittime = c->pbx->rtimeoutms; 05631 if (!waittime) { 05632 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 05633 if (!status) 05634 status = "UNKNOWN"; 05635 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 05636 if (!strcasecmp(status, "CONGESTION")) 05637 res = pbx_builtin_congestion(c, "10"); 05638 else if (!strcasecmp(status, "CHANUNAVAIL")) 05639 res = pbx_builtin_congestion(c, "10"); 05640 else if (!strcasecmp(status, "BUSY")) 05641 res = pbx_builtin_busy(c, "10"); 05642 error = 1; /* XXX disable message */ 05643 break; /* exit from the 'for' loop */ 05644 } 05645 05646 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 05647 break; 05648 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 05649 timeout = 1; 05650 if (!timeout 05651 && ast_exists_extension(c, c->context, dst_exten, 1, 05652 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 05653 set_ext_pri(c, dst_exten, 1); 05654 } else { 05655 /* No such extension */ 05656 if (!timeout && !ast_strlen_zero(dst_exten)) { 05657 /* An invalid extension */ 05658 if (ast_exists_extension(c, c->context, "i", 1, 05659 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05660 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 05661 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 05662 set_ext_pri(c, "i", 1); 05663 } else if (ast_exists_extension(c, c->context, "e", 1, 05664 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05665 raise_exception(c, "INVALID", 1); 05666 } else { 05667 ast_log(LOG_WARNING, 05668 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", 05669 dst_exten, c->context); 05670 found = 1; /* XXX disable message */ 05671 break; 05672 } 05673 } else { 05674 /* A simple timeout */ 05675 if (ast_exists_extension(c, c->context, "t", 1, 05676 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05677 ast_verb(3, "Timeout on %s\n", c->name); 05678 set_ext_pri(c, "t", 1); 05679 } else if (ast_exists_extension(c, c->context, "e", 1, 05680 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05681 raise_exception(c, "RESPONSETIMEOUT", 1); 05682 } else { 05683 ast_log(LOG_WARNING, 05684 "Timeout, but no rule 't' or 'e' in context '%s'\n", 05685 c->context); 05686 found = 1; /* XXX disable message */ 05687 break; 05688 } 05689 } 05690 } 05691 ast_channel_lock(c); 05692 if (c->cdr) { 05693 ast_verb(2, "CDR updated on %s\n",c->name); 05694 ast_cdr_update(c); 05695 } 05696 ast_channel_unlock(c); 05697 } 05698 } 05699 05700 if (!found && !error) { 05701 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 05702 } 05703 05704 if (!args || !args->no_hangup_chan) { 05705 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 05706 } 05707 05708 if ((!args || !args->no_hangup_chan) 05709 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 05710 && ast_exists_extension(c, c->context, "h", 1, 05711 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05712 set_ext_pri(c, "h", 1); 05713 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 05714 ast_cdr_end(c->cdr); 05715 } 05716 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05717 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05718 &found, 1)) == 0) { 05719 c->priority++; 05720 } 05721 if (found && res) { 05722 /* Something bad happened, or a hangup has been requested. */ 05723 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05724 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05725 } 05726 } 05727 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 05728 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 05729 pbx_destroy(c->pbx); 05730 c->pbx = NULL; 05731 05732 if (!args || !args->no_hangup_chan) { 05733 ast_hangup(c); 05734 } 05735 05736 return 0; 05737 }
static void __init_extensionstate_buf | ( | void | ) | [static] |
static void __init_switch_data | ( | void | ) | [static] |
static void __init_thread_inhibit_escalations_tl | ( | void | ) | [static] |
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2693 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, ext_cmp_exten(), ext_cmp_exten_partial(), ext_cmp_exten_strlen(), ext_cmp_pattern(), LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02694 { 02695 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02696 02697 #ifdef NEED_DEBUG_HERE 02698 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02699 #endif 02700 02701 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02702 int lp = ext_cmp_exten_strlen(pattern); 02703 int ld = ext_cmp_exten_strlen(data); 02704 02705 if (lp < ld) { /* pattern too short, cannot match */ 02706 #ifdef NEED_DEBUG_HERE 02707 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02708 #endif 02709 return 0; 02710 } 02711 /* depending on the mode, accept full or partial match or both */ 02712 if (mode == E_MATCH) { 02713 #ifdef NEED_DEBUG_HERE 02714 ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data); 02715 #endif 02716 return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */ 02717 } 02718 if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */ 02719 #ifdef NEED_DEBUG_HERE 02720 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02721 #endif 02722 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02723 } else { 02724 #ifdef NEED_DEBUG_HERE 02725 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02726 #endif 02727 return 0; 02728 } 02729 } 02730 if (mode == E_MATCH && data[0] == '_') { 02731 /* 02732 * XXX It is bad design that we don't know if we should be 02733 * comparing data and pattern as patterns or comparing data if 02734 * it conforms to pattern when the function is called. First, 02735 * assume they are both patterns. If they don't match then try 02736 * to see if data conforms to the given pattern. 02737 * 02738 * note: if this test is left out, then _x. will not match _x. !!! 02739 */ 02740 #ifdef NEED_DEBUG_HERE 02741 ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data); 02742 #endif 02743 if (!ext_cmp_pattern(pattern + 1, data + 1)) { 02744 #ifdef NEED_DEBUG_HERE 02745 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02746 #endif 02747 return 1; 02748 } 02749 } 02750 02751 ++pattern; /* skip leading _ */ 02752 /* 02753 * XXX below we stop at '/' which is a separator for the CID info. However we should 02754 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02755 */ 02756 for (;;) { 02757 const char *end; 02758 02759 /* Ignore '-' chars as eye candy fluff. */ 02760 while (*data == '-') { 02761 ++data; 02762 } 02763 while (*pattern == '-') { 02764 ++pattern; 02765 } 02766 if (!*data || !*pattern || *pattern == '/') { 02767 break; 02768 } 02769 02770 switch (*pattern) { 02771 case '[': /* a range */ 02772 ++pattern; 02773 end = strchr(pattern, ']'); /* XXX should deal with escapes ? */ 02774 if (!end) { 02775 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02776 return 0; /* unconditional failure */ 02777 } 02778 if (pattern == end) { 02779 /* Ignore empty character sets. */ 02780 ++pattern; 02781 continue; 02782 } 02783 for (; pattern < end; ++pattern) { 02784 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02785 if (*data >= pattern[0] && *data <= pattern[2]) 02786 break; /* match found */ 02787 else { 02788 pattern += 2; /* skip a total of 3 chars */ 02789 continue; 02790 } 02791 } else if (*data == pattern[0]) 02792 break; /* match found */ 02793 } 02794 if (pattern >= end) { 02795 #ifdef NEED_DEBUG_HERE 02796 ast_log(LOG_NOTICE,"return (0) when pattern>=end\n"); 02797 #endif 02798 return 0; 02799 } 02800 pattern = end; /* skip and continue */ 02801 break; 02802 case 'n': 02803 case 'N': 02804 if (*data < '2' || *data > '9') { 02805 #ifdef NEED_DEBUG_HERE 02806 ast_log(LOG_NOTICE,"return (0) N is not matched\n"); 02807 #endif 02808 return 0; 02809 } 02810 break; 02811 case 'x': 02812 case 'X': 02813 if (*data < '0' || *data > '9') { 02814 #ifdef NEED_DEBUG_HERE 02815 ast_log(LOG_NOTICE,"return (0) X is not matched\n"); 02816 #endif 02817 return 0; 02818 } 02819 break; 02820 case 'z': 02821 case 'Z': 02822 if (*data < '1' || *data > '9') { 02823 #ifdef NEED_DEBUG_HERE 02824 ast_log(LOG_NOTICE,"return (0) Z is not matched\n"); 02825 #endif 02826 return 0; 02827 } 02828 break; 02829 case '.': /* Must match, even with more digits */ 02830 #ifdef NEED_DEBUG_HERE 02831 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02832 #endif 02833 return 1; 02834 case '!': /* Early match */ 02835 #ifdef NEED_DEBUG_HERE 02836 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02837 #endif 02838 return 2; 02839 default: 02840 if (*data != *pattern) { 02841 #ifdef NEED_DEBUG_HERE 02842 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02843 #endif 02844 return 0; 02845 } 02846 break; 02847 } 02848 ++data; 02849 ++pattern; 02850 } 02851 if (*data) /* data longer than pattern, no match */ { 02852 #ifdef NEED_DEBUG_HERE 02853 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02854 #endif 02855 return 0; 02856 } 02857 02858 /* 02859 * match so far, but ran off the end of data. 02860 * Depending on what is next, determine match or not. 02861 */ 02862 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02863 #ifdef NEED_DEBUG_HERE 02864 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02865 #endif 02866 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02867 } else if (*pattern == '!') { /* early match */ 02868 #ifdef NEED_DEBUG_HERE 02869 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02870 #endif 02871 return 2; 02872 } else { /* partial match */ 02873 #ifdef NEED_DEBUG_HERE 02874 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02875 #endif 02876 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02877 } 02878 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 3580 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.
03581 { 03582 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03583 struct pbx_exception *exception = NULL; 03584 if (!ds || !ds->data) 03585 return -1; 03586 exception = ds->data; 03587 if (!strcasecmp(data, "REASON")) 03588 ast_copy_string(buf, exception->reason, buflen); 03589 else if (!strcasecmp(data, "CONTEXT")) 03590 ast_copy_string(buf, exception->context, buflen); 03591 else if (!strncasecmp(data, "EXTEN", 5)) 03592 ast_copy_string(buf, exception->exten, buflen); 03593 else if (!strcasecmp(data, "PRIORITY")) 03594 snprintf(buf, buflen, "%d", exception->priority); 03595 else 03596 return -1; 03597 return 0; 03598 }
static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3855 of file pbx.c.
References ast_free, ast_module_name(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, and synopsis.
Referenced by __ast_custom_function_register().
03856 { 03857 #ifdef AST_XML_DOCS 03858 char *tmpxml; 03859 03860 /* Let's try to find it in the Documentation XML */ 03861 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03862 return 0; 03863 } 03864 03865 if (ast_string_field_init(acf, 128)) { 03866 return -1; 03867 } 03868 03869 /* load synopsis */ 03870 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); 03871 ast_string_field_set(acf, synopsis, tmpxml); 03872 ast_free(tmpxml); 03873 03874 /* load description */ 03875 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); 03876 ast_string_field_set(acf, desc, tmpxml); 03877 ast_free(tmpxml); 03878 03879 /* load syntax */ 03880 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod)); 03881 ast_string_field_set(acf, syntax, tmpxml); 03882 ast_free(tmpxml); 03883 03884 /* load arguments */ 03885 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod)); 03886 ast_string_field_set(acf, arguments, tmpxml); 03887 ast_free(tmpxml); 03888 03889 /* load seealso */ 03890 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod)); 03891 ast_string_field_set(acf, seealso, tmpxml); 03892 ast_free(tmpxml); 03893 03894 acf->docsrc = AST_XML_DOC; 03895 #endif 03896 03897 return 0; 03898 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static, read] |
Definition at line 2176 of file pbx.c.
References add_pattern_node(), already_in_tree(), ARRAY_LEN, ast_copy_string(), ast_log(), pattern_node::buf, ast_exten::cidmatch, match_char::deleted, match_char::exten, ast_exten::exten, get_pattern_node(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_exten::matchcid, match_char::next_char, and ast_context::pattern_tree.
Referenced by add_priority(), ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().
02177 { 02178 struct match_char *m1 = NULL; 02179 struct match_char *m2 = NULL; 02180 struct match_char **m0; 02181 const char *pos; 02182 int already; 02183 int pattern = 0; 02184 int idx_cur; 02185 int idx_next; 02186 char extenbuf[512]; 02187 struct pattern_node pat_node[2]; 02188 02189 if (e1->matchcid) { 02190 if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) { 02191 ast_log(LOG_ERROR, 02192 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", 02193 e1->exten, e1->cidmatch); 02194 return NULL; 02195 } 02196 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */ 02197 } else { 02198 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 02199 } 02200 02201 #ifdef NEED_DEBUG 02202 ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf); 02203 #endif 02204 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 02205 m0 = &con->pattern_tree; 02206 already = 1; 02207 02208 pos = extenbuf; 02209 if (*pos == '_') { 02210 pattern = 1; 02211 ++pos; 02212 } 02213 idx_cur = 0; 02214 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf); 02215 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) { 02216 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node); 02217 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf); 02218 02219 /* See about adding node to tree. */ 02220 m2 = NULL; 02221 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern)) 02222 && m2->next_char) { 02223 if (!pat_node[idx_next].buf[0]) { 02224 /* 02225 * This is the end of the pattern, but not the end of the tree. 02226 * Mark this node with the exten... a shorter pattern might win 02227 * if the longer one doesn't match. 02228 */ 02229 if (findonly) { 02230 return m2; 02231 } 02232 if (m2->exten) { 02233 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02234 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02235 } 02236 m2->exten = e1; 02237 m2->deleted = 0; 02238 } 02239 m1 = m2->next_char; /* m1 points to the node to compare against */ 02240 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02241 } else { /* not already OR not m2 OR nor m2->next_char */ 02242 if (m2) { 02243 if (findonly) { 02244 return m2; 02245 } 02246 m1 = m2; /* while m0 stays the same */ 02247 } else { 02248 if (findonly) { 02249 return m1; 02250 } 02251 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0); 02252 if (!m1) { /* m1 is the node just added */ 02253 return NULL; 02254 } 02255 m0 = &m1->next_char; 02256 } 02257 if (!pat_node[idx_next].buf[0]) { 02258 if (m2 && m2->exten) { 02259 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02260 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02261 } 02262 m1->deleted = 0; 02263 m1->exten = e1; 02264 } 02265 02266 /* The 'already' variable is a mini-optimization designed to make it so that we 02267 * don't have to call already_in_tree when we know it will return false. 02268 */ 02269 already = 0; 02270 } 02271 } 02272 return m1; 02273 }
static struct match_char* add_pattern_node | ( | struct ast_context * | con, | |
struct match_char * | current, | |||
const struct pattern_node * | pattern, | |||
int | is_pattern, | |||
int | already, | |||
struct match_char ** | nextcharptr | |||
) | [static, read] |
Definition at line 1978 of file pbx.c.
References ast_calloc, pattern_node::buf, insert_in_next_chars_alt_char_list(), match_char::is_pattern, match_char::next_char, ast_context::pattern_tree, pattern_node::specif, match_char::specificity, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01979 { 01980 struct match_char *m; 01981 01982 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) { 01983 return NULL; 01984 } 01985 01986 /* strcpy is safe here since we know its size and have allocated 01987 * just enough space for when we allocated m 01988 */ 01989 strcpy(m->x, pattern->buf); 01990 01991 /* the specificity scores are the same as used in the old 01992 pattern matcher. */ 01993 m->is_pattern = is_pattern; 01994 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') { 01995 m->specificity = 0x0832; 01996 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') { 01997 m->specificity = 0x0931; 01998 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') { 01999 m->specificity = 0x0a30; 02000 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') { 02001 m->specificity = 0x18000; 02002 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') { 02003 m->specificity = 0x28000; 02004 } else { 02005 m->specificity = pattern->specif; 02006 } 02007 02008 if (!con->pattern_tree) { 02009 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 02010 } else { 02011 if (already) { /* switch to the new regime (traversing vs appending)*/ 02012 insert_in_next_chars_alt_char_list(nextcharptr, m); 02013 } else { 02014 insert_in_next_chars_alt_char_list(¤t->next_char, m); 02015 } 02016 } 02017 02018 return m; 02019 }
static int add_priority | ( | struct ast_context * | con, | |
struct ast_exten * | tmp, | |||
struct ast_exten * | el, | |||
struct ast_exten * | e, | |||
int | replace | |||
) | [static] |
add the extension in the priority chain.
0 | on success. | |
-1 | on failure. |
Definition at line 8810 of file pbx.c.
References add_exten_to_pattern_tree(), ast_add_hint(), ast_change_hint(), ast_free, ast_hashtab_insert_safe(), ast_hashtab_remove_object_via_lookup(), ast_log(), ast_exten::data, ast_exten::datad, match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_WARNING, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by ast_add_extension2_lockopt().
08812 { 08813 struct ast_exten *ep; 08814 struct ast_exten *eh=e; 08815 int repeated_label = 0; /* Track if this label is a repeat, assume no. */ 08816 08817 for (ep = NULL; e ; ep = e, e = e->peer) { 08818 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) { 08819 if (strcmp(e->exten, tmp->exten)) { 08820 ast_log(LOG_WARNING, 08821 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n", 08822 tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority); 08823 } else { 08824 ast_log(LOG_WARNING, 08825 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n", 08826 tmp->exten, tmp->priority, con->name, tmp->label, e->priority); 08827 } 08828 repeated_label = 1; 08829 } 08830 if (e->priority >= tmp->priority) { 08831 break; 08832 } 08833 } 08834 08835 if (repeated_label) { /* Discard the label since it's a repeat. */ 08836 tmp->label = NULL; 08837 } 08838 08839 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 08840 ast_hashtab_insert_safe(eh->peer_table, tmp); 08841 08842 if (tmp->label) { 08843 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08844 } 08845 ep->peer = tmp; 08846 return 0; /* success */ 08847 } 08848 if (e->priority == tmp->priority) { 08849 /* Can't have something exactly the same. Is this a 08850 replacement? If so, replace, otherwise, bonk. */ 08851 if (!replace) { 08852 if (strcmp(e->exten, tmp->exten)) { 08853 ast_log(LOG_WARNING, 08854 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n", 08855 tmp->exten, tmp->priority, con->name, e->exten); 08856 } else { 08857 ast_log(LOG_WARNING, 08858 "Unable to register extension '%s' priority %d in '%s', already in use\n", 08859 tmp->exten, tmp->priority, con->name); 08860 } 08861 if (tmp->datad) { 08862 tmp->datad(tmp->data); 08863 /* if you free this, null it out */ 08864 tmp->data = NULL; 08865 } 08866 08867 ast_free(tmp); 08868 return -1; 08869 } 08870 /* we are replacing e, so copy the link fields and then update 08871 * whoever pointed to e to point to us 08872 */ 08873 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 08874 tmp->peer = e->peer; /* always meaningful */ 08875 if (ep) { /* We're in the peer list, just insert ourselves */ 08876 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 08877 08878 if (e->label) { 08879 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 08880 } 08881 08882 ast_hashtab_insert_safe(eh->peer_table,tmp); 08883 if (tmp->label) { 08884 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 08885 } 08886 08887 ep->peer = tmp; 08888 } else if (el) { /* We're the first extension. Take over e's functions */ 08889 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08890 tmp->peer_table = e->peer_table; 08891 tmp->peer_label_table = e->peer_label_table; 08892 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 08893 ast_hashtab_insert_safe(tmp->peer_table,tmp); 08894 if (e->label) { 08895 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08896 } 08897 if (tmp->label) { 08898 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08899 } 08900 08901 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08902 ast_hashtab_insert_safe(con->root_table, tmp); 08903 el->next = tmp; 08904 /* The pattern trie points to this exten; replace the pointer, 08905 and all will be well */ 08906 if (x) { /* if the trie isn't formed yet, don't sweat this */ 08907 if (x->exten) { /* this test for safety purposes */ 08908 x->exten = tmp; /* replace what would become a bad pointer */ 08909 } else { 08910 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08911 } 08912 } 08913 } else { /* We're the very first extension. */ 08914 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08915 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08916 ast_hashtab_insert_safe(con->root_table, tmp); 08917 tmp->peer_table = e->peer_table; 08918 tmp->peer_label_table = e->peer_label_table; 08919 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 08920 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08921 if (e->label) { 08922 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08923 } 08924 if (tmp->label) { 08925 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08926 } 08927 08928 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08929 ast_hashtab_insert_safe(con->root_table, tmp); 08930 con->root = tmp; 08931 /* The pattern trie points to this exten; replace the pointer, 08932 and all will be well */ 08933 if (x) { /* if the trie isn't formed yet; no problem */ 08934 if (x->exten) { /* this test for safety purposes */ 08935 x->exten = tmp; /* replace what would become a bad pointer */ 08936 } else { 08937 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08938 } 08939 } 08940 } 08941 if (tmp->priority == PRIORITY_HINT) 08942 ast_change_hint(e,tmp); 08943 /* Destroy the old one */ 08944 if (e->datad) 08945 e->datad(e->data); 08946 ast_free(e); 08947 } else { /* Slip ourselves in just before e */ 08948 tmp->peer = e; 08949 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 08950 if (ep) { /* Easy enough, we're just in the peer list */ 08951 if (tmp->label) { 08952 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08953 } 08954 ast_hashtab_insert_safe(eh->peer_table, tmp); 08955 ep->peer = tmp; 08956 } else { /* we are the first in some peer list, so link in the ext list */ 08957 tmp->peer_table = e->peer_table; 08958 tmp->peer_label_table = e->peer_label_table; 08959 e->peer_table = 0; 08960 e->peer_label_table = 0; 08961 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08962 if (tmp->label) { 08963 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08964 } 08965 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08966 ast_hashtab_insert_safe(con->root_table, tmp); 08967 if (el) 08968 el->next = tmp; /* in the middle... */ 08969 else 08970 con->root = tmp; /* ... or at the head */ 08971 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 08972 } 08973 /* And immediately return success. */ 08974 if (tmp->priority == PRIORITY_HINT) { 08975 ast_add_hint(tmp); 08976 } 08977 } 08978 return 0; 08979 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat, | |||
int | is_pattern | |||
) | [static, read] |
Definition at line 1916 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01917 { 01918 struct match_char *t; 01919 01920 if (!current) { 01921 return 0; 01922 } 01923 01924 for (t = current; t; t = t->alt_char) { 01925 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01926 return t; 01927 } 01928 } 01929 01930 return 0; 01931 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5885 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05886 { 05887 return countcalls; 05888 }
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 8645 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().
08648 { 08649 int ret = -1; 08650 struct ast_context *c; 08651 08652 c = find_context_locked(context); 08653 if (c) { 08654 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08655 application, data, datad, registrar); 08656 ast_unlock_contexts(); 08657 } 08658 08659 return ret; 08660 }
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 9006 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
09010 { 09011 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 09012 application, data, datad, registrar, 1); 09013 }
static int ast_add_extension2_lockopt | ( | struct ast_context * | con, | |
int | replace, | |||
const char * | extension, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
const char * | application, | |||
void * | data, | |||
void(*)(void *) | datad, | |||
const char * | registrar, | |||
int | lock_context | |||
) | [static] |
Same as ast_add_extension2() but controls the context locking.
Does all the work of ast_add_extension2, but adds an arg to determine if context locking should be done.
Definition at line 9022 of file pbx.c.
References add_exten_to_pattern_tree(), add_priority(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, AST_EXT_MATCHCID_OFF, AST_EXT_MATCHCID_ON, ast_hashtab_create(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_channel::context, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_channel::exten, hashtab_compare_exten_labels(), hashtab_compare_exten_numbers(), hashtab_compare_extens(), hashtab_hash_extens(), hashtab_hash_labels(), hashtab_hash_priority(), ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::next, option_debug, ast_exten::parent, ast_context::pattern_tree, pbx_substitute_variables_helper(), ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_context::root_table, ast_exten::stuff, and VAR_BUF_SIZE.
Referenced by ast_add_extension2(), and ast_add_extension_nolock().
09026 { 09027 /* 09028 * Sort extensions (or patterns) according to the rules indicated above. 09029 * These are implemented by the function ext_cmp()). 09030 * All priorities for the same ext/pattern/cid are kept in a list, 09031 * using the 'peer' field as a link field.. 09032 */ 09033 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 09034 int res; 09035 int length; 09036 char *p; 09037 char expand_buf[VAR_BUF_SIZE]; 09038 struct ast_exten dummy_exten = {0}; 09039 char dummy_name[1024]; 09040 09041 if (ast_strlen_zero(extension)) { 09042 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", 09043 con->name); 09044 return -1; 09045 } 09046 09047 /* If we are adding a hint evalulate in variables and global variables */ 09048 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') { 09049 struct ast_channel *c = ast_dummy_channel_alloc(); 09050 09051 if (c) { 09052 ast_copy_string(c->exten, extension, sizeof(c->exten)); 09053 ast_copy_string(c->context, con->name, sizeof(c->context)); 09054 } 09055 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 09056 application = expand_buf; 09057 if (c) { 09058 ast_channel_unref(c); 09059 } 09060 } 09061 09062 length = sizeof(struct ast_exten); 09063 length += strlen(extension) + 1; 09064 length += strlen(application) + 1; 09065 if (label) 09066 length += strlen(label) + 1; 09067 if (callerid) 09068 length += strlen(callerid) + 1; 09069 else 09070 length ++; /* just the '\0' */ 09071 09072 /* Be optimistic: Build the extension structure first */ 09073 if (!(tmp = ast_calloc(1, length))) 09074 return -1; 09075 09076 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 09077 label = 0; 09078 09079 /* use p as dst in assignments, as the fields are const char * */ 09080 p = tmp->stuff; 09081 if (label) { 09082 tmp->label = p; 09083 strcpy(p, label); 09084 p += strlen(label) + 1; 09085 } 09086 tmp->exten = p; 09087 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 09088 tmp->priority = priority; 09089 tmp->cidmatch = p; /* but use p for assignments below */ 09090 09091 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 09092 if (callerid) { 09093 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 09094 tmp->matchcid = AST_EXT_MATCHCID_ON; 09095 } else { 09096 *p++ = '\0'; 09097 tmp->matchcid = AST_EXT_MATCHCID_OFF; 09098 } 09099 tmp->app = p; 09100 strcpy(p, application); 09101 tmp->parent = con; 09102 tmp->data = data; 09103 tmp->datad = datad; 09104 tmp->registrar = registrar; 09105 09106 if (lock_context) { 09107 ast_wrlock_context(con); 09108 } 09109 09110 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 09111 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 09112 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 09113 dummy_exten.exten = dummy_name; 09114 dummy_exten.matchcid = AST_EXT_MATCHCID_OFF; 09115 dummy_exten.cidmatch = 0; 09116 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 09117 if (!tmp2) { 09118 /* hmmm, not in the trie; */ 09119 add_exten_to_pattern_tree(con, tmp, 0); 09120 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 09121 } 09122 } 09123 res = 0; /* some compilers will think it is uninitialized otherwise */ 09124 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 09125 res = ext_cmp(e->exten, tmp->exten); 09126 if (res == 0) { /* extension match, now look at cidmatch */ 09127 if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF) 09128 res = 0; 09129 else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF) 09130 res = 1; 09131 else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF) 09132 res = -1; 09133 else 09134 res = ext_cmp(e->cidmatch, tmp->cidmatch); 09135 } 09136 if (res >= 0) 09137 break; 09138 } 09139 if (e && res == 0) { /* exact match, insert in the priority chain */ 09140 res = add_priority(con, tmp, el, e, replace); 09141 if (lock_context) { 09142 ast_unlock_context(con); 09143 } 09144 if (res < 0) { 09145 errno = EEXIST; /* XXX do we care ? */ 09146 return 0; /* XXX should we return -1 maybe ? */ 09147 } 09148 } else { 09149 /* 09150 * not an exact match, this is the first entry with this pattern, 09151 * so insert in the main list right before 'e' (if any) 09152 */ 09153 tmp->next = e; 09154 if (el) { /* there is another exten already in this context */ 09155 el->next = tmp; 09156 tmp->peer_table = ast_hashtab_create(13, 09157 hashtab_compare_exten_numbers, 09158 ast_hashtab_resize_java, 09159 ast_hashtab_newsize_java, 09160 hashtab_hash_priority, 09161 0); 09162 tmp->peer_label_table = ast_hashtab_create(7, 09163 hashtab_compare_exten_labels, 09164 ast_hashtab_resize_java, 09165 ast_hashtab_newsize_java, 09166 hashtab_hash_labels, 09167 0); 09168 if (label) { 09169 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 09170 } 09171 ast_hashtab_insert_safe(tmp->peer_table, tmp); 09172 } else { /* this is the first exten in this context */ 09173 if (!con->root_table) 09174 con->root_table = ast_hashtab_create(27, 09175 hashtab_compare_extens, 09176 ast_hashtab_resize_java, 09177 ast_hashtab_newsize_java, 09178 hashtab_hash_extens, 09179 0); 09180 con->root = tmp; 09181 con->root->peer_table = ast_hashtab_create(13, 09182 hashtab_compare_exten_numbers, 09183 ast_hashtab_resize_java, 09184 ast_hashtab_newsize_java, 09185 hashtab_hash_priority, 09186 0); 09187 con->root->peer_label_table = ast_hashtab_create(7, 09188 hashtab_compare_exten_labels, 09189 ast_hashtab_resize_java, 09190 ast_hashtab_newsize_java, 09191 hashtab_hash_labels, 09192 0); 09193 if (label) { 09194 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 09195 } 09196 ast_hashtab_insert_safe(con->root->peer_table, tmp); 09197 09198 } 09199 ast_hashtab_insert_safe(con->root_table, tmp); 09200 if (lock_context) { 09201 ast_unlock_context(con); 09202 } 09203 if (tmp->priority == PRIORITY_HINT) { 09204 ast_add_hint(tmp); 09205 } 09206 } 09207 if (option_debug) { 09208 if (tmp->matchcid == AST_EXT_MATCHCID_ON) { 09209 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 09210 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 09211 } else { 09212 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 09213 tmp->exten, tmp->priority, con->name, con); 09214 } 09215 } 09216 09217 if (tmp->matchcid == AST_EXT_MATCHCID_ON) { 09218 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 09219 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 09220 } else { 09221 ast_verb(3, "Added extension '%s' priority %d to %s\n", 09222 tmp->exten, tmp->priority, con->name); 09223 } 09224 09225 return 0; 09226 }
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 8625 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
08628 { 08629 int ret = -1; 08630 struct ast_context *c; 08631 08632 c = find_context(context); 08633 if (c) { 08634 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 08635 application, data, datad, registrar, 1); 08636 } 08637 08638 return ret; 08639 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 5224 of file pbx.c.
References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_debug, AST_DEVICE_INVALID, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), ast_hint::callbacks, destroy_hint(), ast_exten::exten, ast_hint::exten, hint_id_cmp(), hints, and ast_hint::laststate.
Referenced by add_priority(), and ast_add_extension2_lockopt().
05225 { 05226 struct ast_hint *hint_new; 05227 struct ast_hint *hint_found; 05228 05229 if (!e) { 05230 return -1; 05231 } 05232 05233 /* 05234 * We must create the hint we wish to add before determining if 05235 * it is already in the hints container to avoid possible 05236 * deadlock when getting the current extension state. 05237 */ 05238 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint); 05239 if (!hint_new) { 05240 return -1; 05241 } 05242 05243 /* Initialize new hint. */ 05244 hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); 05245 if (!hint_new->callbacks) { 05246 ao2_ref(hint_new, -1); 05247 return -1; 05248 } 05249 hint_new->exten = e; 05250 if (strstr(e->app, "${") && e->exten[0] == '_') { 05251 hint_new->laststate = AST_DEVICE_INVALID; 05252 } else { 05253 hint_new->laststate = ast_extension_state2(e); 05254 } 05255 05256 /* Prevent multiple add hints from adding the same hint at the same time. */ 05257 ao2_lock(hints); 05258 05259 /* Search if hint exists, do nothing */ 05260 hint_found = ao2_find(hints, e, 0); 05261 if (hint_found) { 05262 ao2_ref(hint_found, -1); 05263 ao2_unlock(hints); 05264 ao2_ref(hint_new, -1); 05265 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", 05266 ast_get_extension_name(e), ast_get_extension_app(e)); 05267 return -1; 05268 } 05269 05270 /* Add new hint to the hints container */ 05271 ast_debug(2, "HINTS: Adding hint %s: %s\n", 05272 ast_get_extension_name(e), ast_get_extension_app(e)); 05273 ao2_link(hints, hint_new); 05274 05275 ao2_unlock(hints); 05276 ao2_ref(hint_new, -1); 05277 05278 return 0; 05279 }
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 8685 of file pbx.c.
References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmf(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().
08686 { 08687 int res = 0; 08688 struct ast_channel *tmpchan; 08689 struct { 08690 char *accountcode; 08691 char *exten; 08692 char *context; 08693 char *linkedid; 08694 char *name; 08695 struct ast_cdr *cdr; 08696 int amaflags; 08697 int state; 08698 format_t readformat; 08699 format_t writeformat; 08700 } tmpvars = { 0, }; 08701 08702 ast_channel_lock(chan); 08703 if (chan->pbx) { /* This channel is currently in the PBX */ 08704 ast_explicit_goto(chan, context, exten, priority + 1); 08705 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08706 ast_channel_unlock(chan); 08707 return res; 08708 } 08709 08710 /* In order to do it when the channel doesn't really exist within 08711 * the PBX, we have to make a new channel, masquerade, and start the PBX 08712 * at the new location */ 08713 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08714 tmpvars.exten = ast_strdupa(chan->exten); 08715 tmpvars.context = ast_strdupa(chan->context); 08716 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08717 tmpvars.name = ast_strdupa(chan->name); 08718 tmpvars.amaflags = chan->amaflags; 08719 tmpvars.state = chan->_state; 08720 tmpvars.writeformat = chan->writeformat; 08721 tmpvars.readformat = chan->readformat; 08722 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08723 08724 ast_channel_unlock(chan); 08725 08726 /* Do not hold any channel locks while calling channel_alloc() since the function 08727 * locks the channel container when linking the new channel in. */ 08728 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08729 ast_cdr_discard(tmpvars.cdr); 08730 return -1; 08731 } 08732 08733 /* copy the cdr info over */ 08734 if (tmpvars.cdr) { 08735 ast_cdr_discard(tmpchan->cdr); 08736 tmpchan->cdr = tmpvars.cdr; 08737 tmpvars.cdr = NULL; 08738 } 08739 08740 /* Make formats okay */ 08741 tmpchan->readformat = tmpvars.readformat; 08742 tmpchan->writeformat = tmpvars.writeformat; 08743 08744 /* Setup proper location. Never hold another channel lock while calling this function. */ 08745 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08746 08747 /* Masquerade into tmp channel */ 08748 if (ast_channel_masquerade(tmpchan, chan)) { 08749 /* Failed to set up the masquerade. It's probably chan_local 08750 * in the middle of optimizing itself out. Sad. :( */ 08751 ast_hangup(tmpchan); 08752 tmpchan = NULL; 08753 res = -1; 08754 } else { 08755 ast_do_masquerade(tmpchan); 08756 /* Start the PBX going on our stolen channel */ 08757 if (ast_pbx_start(tmpchan)) { 08758 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08759 ast_hangup(tmpchan); 08760 res = -1; 08761 } 08762 } 08763 08764 return res; 08765 }
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 8767 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08768 { 08769 struct ast_channel *chan; 08770 int res = -1; 08771 08772 if ((chan = ast_channel_get_by_name(channame))) { 08773 res = ast_async_goto(chan, context, exten, priority); 08774 chan = ast_channel_unref(chan); 08775 } 08776 08777 return res; 08778 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11125 of file pbx.c.
References __ast_goto_if_exists().
11126 { 11127 return __ast_goto_if_exists(chan, context, exten, priority, 1); 11128 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11190 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
11191 { 11192 return pbx_parseable_goto(chan, goto_string, 1); 11193 }
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 8268 of file pbx.c.
References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
08269 { 08270 char *info; 08271 int j, num_fields, last_sep = -1; 08272 08273 i->timezone = NULL; 08274 08275 /* Check for empty just in case */ 08276 if (ast_strlen_zero(info_in)) { 08277 return 0; 08278 } 08279 08280 /* make a copy just in case we were passed a static string */ 08281 info = ast_strdupa(info_in); 08282 08283 /* count the number of fields in the timespec */ 08284 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08285 if (info[j] == ',') { 08286 last_sep = j; 08287 num_fields++; 08288 } 08289 } 08290 08291 /* save the timezone, if it is specified */ 08292 if (num_fields == 5) { 08293 i->timezone = ast_strdup(info + last_sep + 1); 08294 } 08295 08296 /* Assume everything except time */ 08297 i->monthmask = 0xfff; /* 12 bits */ 08298 i->daymask = 0x7fffffffU; /* 31 bits */ 08299 i->dowmask = 0x7f; /* 7 bits */ 08300 /* on each call, use strsep() to move info to the next argument */ 08301 get_timerange(i, strsep(&info, "|,")); 08302 if (info) 08303 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08304 if (info) 08305 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08306 if (info) 08307 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08308 return 1; 08309 }
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 5369 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
05370 { 05371 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05372 }
Change hint for an extension.
Definition at line 5282 of file pbx.c.
References ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_hint::exten, hints, and OBJ_UNLINK.
Referenced by add_priority().
05283 { 05284 struct ast_hint *hint; 05285 05286 if (!oe || !ne) { 05287 return -1; 05288 } 05289 05290 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */ 05291 05292 /* 05293 * Unlink the hint from the hints container as the extension 05294 * name (which is the hash value) could change. 05295 */ 05296 hint = ao2_find(hints, oe, OBJ_UNLINK); 05297 if (!hint) { 05298 ao2_unlock(hints); 05299 return -1; 05300 } 05301 05302 /* Update the hint and put it back in the hints container. */ 05303 ao2_lock(hint); 05304 hint->exten = ne; 05305 ao2_unlock(hint); 05306 ao2_link(hints, hint); 05307 05308 ao2_unlock(hints); 05309 ao2_ref(hint, -1); 05310 05311 return 0; 05312 }
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 8311 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08312 { 08313 return ast_check_timing2(i, ast_tvnow()); 08314 }
int ast_check_timing2 | ( | const struct ast_timing * | i, | |
const struct timeval | tv | |||
) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
i | Pointer to an ast_timing structure. | |
tv | Specified time |
Returns | 1, if the time matches or 0, if the time falls outside of the specified range. |
Definition at line 8316 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by ast_check_timing(), and pbx_builtin_gotoiftime().
08317 { 08318 struct ast_tm tm; 08319 08320 ast_localtime(&tv, &tm, i->timezone); 08321 08322 /* If it's not the right month, return */ 08323 if (!(i->monthmask & (1 << tm.tm_mon))) 08324 return 0; 08325 08326 /* If it's not that time of the month.... */ 08327 /* Warning, tm_mday has range 1..31! */ 08328 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08329 return 0; 08330 08331 /* If it's not the right day of the week */ 08332 if (!(i->dowmask & (1 << tm.tm_wday))) 08333 return 0; 08334 08335 /* Sanity check the hour just to be safe */ 08336 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08337 ast_log(LOG_WARNING, "Insane time...\n"); 08338 return 0; 08339 } 08340 08341 /* Now the tough part, we calculate if it fits 08342 in the right time based on min/hour */ 08343 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)))) 08344 return 0; 08345 08346 /* If we got this far, then we're good */ 08347 return 1; 08348 }
char* ast_complete_applications | ( | const char * | line, | |
const char * | word, | |||
int | state | |||
) |
Command completion for the list of installed applications.
This can be called from a CLI command completion function that wants to complete from the list of available applications.
Definition at line 11195 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::name.
Referenced by handle_orig(), and handle_show_application().
11196 { 11197 struct ast_app *app = NULL; 11198 int which = 0; 11199 char *ret = NULL; 11200 size_t wordlen = strlen(word); 11201 11202 AST_RWLIST_RDLOCK(&apps); 11203 AST_RWLIST_TRAVERSE(&apps, app, list) { 11204 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 11205 ret = ast_strdup(app->name); 11206 break; 11207 } 11208 } 11209 AST_RWLIST_UNLOCK(&apps); 11210 11211 return ret; 11212 }
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 8552 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08553 { 08554 int ret = -1; 08555 struct ast_context *c; 08556 08557 c = find_context_locked(context); 08558 if (c) { 08559 ret = ast_context_add_ignorepat2(c, value, registrar); 08560 ast_unlock_contexts(); 08561 } 08562 return ret; 08563 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 8565 of file pbx.c.
References ast_calloc, ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08566 { 08567 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08568 int length; 08569 char *pattern; 08570 length = sizeof(struct ast_ignorepat); 08571 length += strlen(value) + 1; 08572 if (!(ignorepat = ast_calloc(1, length))) 08573 return -1; 08574 /* The cast to char * is because we need to write the initial value. 08575 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08576 * sees the cast as dereferencing a type-punned pointer and warns about 08577 * it. This is the workaround (we're telling gcc, yes, that's really 08578 * what we wanted to do). 08579 */ 08580 pattern = (char *) ignorepat->pattern; 08581 strcpy(pattern, value); 08582 ignorepat->next = NULL; 08583 ignorepat->registrar = registrar; 08584 ast_wrlock_context(con); 08585 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08586 ignorepatl = ignorepatc; 08587 if (!strcasecmp(ignorepatc->pattern, value)) { 08588 /* Already there */ 08589 ast_unlock_context(con); 08590 ast_free(ignorepat); 08591 errno = EEXIST; 08592 return -1; 08593 } 08594 } 08595 if (ignorepatl) 08596 ignorepatl->next = ignorepat; 08597 else 08598 con->ignorepats = ignorepat; 08599 ast_unlock_context(con); 08600 return 0; 08601 08602 }
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 8096 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
08097 { 08098 int ret = -1; 08099 struct ast_context *c; 08100 08101 c = find_context_locked(context); 08102 if (c) { 08103 ret = ast_context_add_include2(c, include, registrar); 08104 ast_unlock_contexts(); 08105 } 08106 return ret; 08107 }
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 8365 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().
08367 { 08368 struct ast_include *new_include; 08369 char *c; 08370 struct ast_include *i, *il = NULL; /* include, include_last */ 08371 int length; 08372 char *p; 08373 08374 length = sizeof(struct ast_include); 08375 length += 2 * (strlen(value) + 1); 08376 08377 /* allocate new include structure ... */ 08378 if (!(new_include = ast_calloc(1, length))) 08379 return -1; 08380 /* Fill in this structure. Use 'p' for assignments, as the fields 08381 * in the structure are 'const char *' 08382 */ 08383 p = new_include->stuff; 08384 new_include->name = p; 08385 strcpy(p, value); 08386 p += strlen(value) + 1; 08387 new_include->rname = p; 08388 strcpy(p, value); 08389 /* Strip off timing info, and process if it is there */ 08390 if ( (c = strchr(p, ',')) ) { 08391 *c++ = '\0'; 08392 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08393 } 08394 new_include->next = NULL; 08395 new_include->registrar = registrar; 08396 08397 ast_wrlock_context(con); 08398 08399 /* ... go to last include and check if context is already included too... */ 08400 for (i = con->includes; i; i = i->next) { 08401 if (!strcasecmp(i->name, new_include->name)) { 08402 ast_destroy_timing(&(new_include->timing)); 08403 ast_free(new_include); 08404 ast_unlock_context(con); 08405 errno = EEXIST; 08406 return -1; 08407 } 08408 il = i; 08409 } 08410 08411 /* ... include new context into context list, unlock, return */ 08412 if (il) 08413 il->next = new_include; 08414 else 08415 con->includes = new_include; 08416 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08417 08418 ast_unlock_context(con); 08419 08420 return 0; 08421 }
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 8428 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08429 { 08430 int ret = -1; 08431 struct ast_context *c; 08432 08433 c = find_context_locked(context); 08434 if (c) { /* found, add switch to this context */ 08435 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08436 ast_unlock_contexts(); 08437 } 08438 return ret; 08439 }
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 8448 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().
08450 { 08451 struct ast_sw *new_sw; 08452 struct ast_sw *i; 08453 int length; 08454 char *p; 08455 08456 length = sizeof(struct ast_sw); 08457 length += strlen(value) + 1; 08458 if (data) 08459 length += strlen(data); 08460 length++; 08461 08462 /* allocate new sw structure ... */ 08463 if (!(new_sw = ast_calloc(1, length))) 08464 return -1; 08465 /* ... fill in this structure ... */ 08466 p = new_sw->stuff; 08467 new_sw->name = p; 08468 strcpy(new_sw->name, value); 08469 p += strlen(value) + 1; 08470 new_sw->data = p; 08471 if (data) { 08472 strcpy(new_sw->data, data); 08473 p += strlen(data) + 1; 08474 } else { 08475 strcpy(new_sw->data, ""); 08476 p++; 08477 } 08478 new_sw->eval = eval; 08479 new_sw->registrar = registrar; 08480 08481 /* ... try to lock this context ... */ 08482 ast_wrlock_context(con); 08483 08484 /* ... go to last sw and check if context is already swd too... */ 08485 AST_LIST_TRAVERSE(&con->alts, i, list) { 08486 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08487 ast_free(new_sw); 08488 ast_unlock_context(con); 08489 errno = EEXIST; 08490 return -1; 08491 } 08492 } 08493 08494 /* ... sw new context into context list, unlock, return */ 08495 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08496 08497 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08498 08499 ast_unlock_context(con); 08500 08501 return 0; 08502 }
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 9829 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), features_shutdown(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09830 { 09831 ast_wrlock_contexts(); 09832 __ast_context_destroy(contexts, contexts_table, con,registrar); 09833 ast_unlock_contexts(); 09834 }
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 2925 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().
02926 { 02927 struct ast_context *tmp; 02928 struct fake_context item; 02929 02930 if (!name) { 02931 return NULL; 02932 } 02933 ast_rdlock_contexts(); 02934 if (contexts_table) { 02935 ast_copy_string(item.name, name, sizeof(item.name)); 02936 tmp = ast_hashtab_lookup(contexts_table, &item); 02937 } else { 02938 tmp = NULL; 02939 while ((tmp = ast_walk_contexts(tmp))) { 02940 if (!strcasecmp(name, tmp->name)) { 02941 break; 02942 } 02943 } 02944 } 02945 ast_unlock_contexts(); 02946 return tmp; 02947 }
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 7680 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
07681 { 07682 struct ast_context *tmp, **local_contexts; 07683 struct fake_context search; 07684 int length = sizeof(struct ast_context) + strlen(name) + 1; 07685 07686 if (!contexts_table) { 07687 /* Protect creation of contexts_table from reentrancy. */ 07688 ast_wrlock_contexts(); 07689 if (!contexts_table) { 07690 contexts_table = ast_hashtab_create(17, 07691 ast_hashtab_compare_contexts, 07692 ast_hashtab_resize_java, 07693 ast_hashtab_newsize_java, 07694 ast_hashtab_hash_contexts, 07695 0); 07696 } 07697 ast_unlock_contexts(); 07698 } 07699 07700 ast_copy_string(search.name, name, sizeof(search.name)); 07701 if (!extcontexts) { 07702 ast_rdlock_contexts(); 07703 local_contexts = &contexts; 07704 tmp = ast_hashtab_lookup(contexts_table, &search); 07705 ast_unlock_contexts(); 07706 if (tmp) { 07707 tmp->refcount++; 07708 return tmp; 07709 } 07710 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07711 local_contexts = extcontexts; 07712 tmp = ast_hashtab_lookup(exttable, &search); 07713 if (tmp) { 07714 tmp->refcount++; 07715 return tmp; 07716 } 07717 } 07718 07719 if ((tmp = ast_calloc(1, length))) { 07720 ast_rwlock_init(&tmp->lock); 07721 ast_mutex_init(&tmp->macrolock); 07722 strcpy(tmp->name, name); 07723 tmp->root = NULL; 07724 tmp->root_table = NULL; 07725 tmp->registrar = ast_strdup(registrar); 07726 tmp->includes = NULL; 07727 tmp->ignorepats = NULL; 07728 tmp->refcount = 1; 07729 } else { 07730 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07731 return NULL; 07732 } 07733 07734 if (!extcontexts) { 07735 ast_wrlock_contexts(); 07736 tmp->next = *local_contexts; 07737 *local_contexts = tmp; 07738 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07739 ast_unlock_contexts(); 07740 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07741 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07742 } else { 07743 tmp->next = *local_contexts; 07744 if (exttable) 07745 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07746 07747 *local_contexts = tmp; 07748 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07749 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07750 } 07751 return tmp; 07752 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 6260 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06261 { 06262 struct ast_context *c; 06263 int ret = -1; 06264 06265 c = find_context_locked(context); 06266 if (c) { 06267 ast_unlock_contexts(); 06268 06269 /* if we found context, lock macrolock */ 06270 ret = ast_mutex_lock(&c->macrolock); 06271 } 06272 06273 return ret; 06274 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
Definition at line 6068 of file pbx.c.
References ast_context_remove_extension_callerid(), and AST_EXT_MATCHCID_ANY.
Referenced by register_peer_exten(), remove_exten_if_exist(), sla_station_destructor(), sla_trunk_destructor(), unregister_exten(), and UnregisterExtension().
06069 { 06070 return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar); 06071 }
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 6098 of file pbx.c.
References ast_context_remove_extension_callerid2(), and AST_EXT_MATCHCID_ANY.
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
06099 { 06100 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked); 06101 }
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 6073 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().
06074 { 06075 int ret = -1; /* default error return */ 06076 struct ast_context *c; 06077 06078 c = find_context_locked(context); 06079 if (c) { /* ... remove extension ... */ 06080 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 06081 matchcallerid, registrar, 0); 06082 ast_unlock_contexts(); 06083 } 06084 06085 return ret; 06086 }
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 6103 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
06104 { 06105 struct ast_exten *exten, *prev_exten = NULL; 06106 struct ast_exten *peer; 06107 struct ast_exten ex, *exten2, *exten3; 06108 char dummy_name[1024]; 06109 struct ast_exten *previous_peer = NULL; 06110 struct ast_exten *next_peer = NULL; 06111 int found = 0; 06112 06113 if (!already_locked) 06114 ast_wrlock_context(con); 06115 06116 #ifdef NEED_DEBUG 06117 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 06118 #endif 06119 #ifdef CONTEXT_DEBUG 06120 check_contexts(__FILE__, __LINE__); 06121 #endif 06122 /* find this particular extension */ 06123 ex.exten = dummy_name; 06124 ex.matchcid = matchcallerid; 06125 ex.cidmatch = callerid; 06126 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 06127 exten = ast_hashtab_lookup(con->root_table, &ex); 06128 if (exten) { 06129 if (priority == 0) { 06130 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06131 if (!exten2) 06132 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); 06133 if (con->pattern_tree) { 06134 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06135 06136 if (x->exten) { /* this test for safety purposes */ 06137 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06138 x->exten = 0; /* get rid of what will become a bad pointer */ 06139 } else { 06140 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 06141 } 06142 } 06143 } else { 06144 ex.priority = priority; 06145 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 06146 if (exten2) { 06147 if (exten2->label) { /* if this exten has a label, remove that, too */ 06148 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 06149 if (!exten3) 06150 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); 06151 } 06152 06153 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 06154 if (!exten3) 06155 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); 06156 if (exten2 == exten && exten2->peer) { 06157 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06158 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 06159 } 06160 if (ast_hashtab_size(exten->peer_table) == 0) { 06161 /* well, if the last priority of an exten is to be removed, 06162 then, the extension is removed, too! */ 06163 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 06164 if (!exten3) 06165 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 06166 if (con->pattern_tree) { 06167 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06168 if (x->exten) { /* this test for safety purposes */ 06169 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06170 x->exten = 0; /* get rid of what will become a bad pointer */ 06171 } 06172 } 06173 } 06174 } else { 06175 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 06176 priority, exten->exten, con->name); 06177 } 06178 } 06179 } else { 06180 /* hmmm? this exten is not in this pattern tree? */ 06181 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 06182 extension, con->name); 06183 } 06184 #ifdef NEED_DEBUG 06185 if (con->pattern_tree) { 06186 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 06187 log_match_char_tree(con->pattern_tree, " "); 06188 } 06189 #endif 06190 06191 /* scan the extension list to find first matching extension-registrar */ 06192 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 06193 if (!strcmp(exten->exten, extension) && 06194 (!registrar || !strcmp(exten->registrar, registrar)) && 06195 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 06196 break; 06197 } 06198 if (!exten) { 06199 /* we can't find right extension */ 06200 if (!already_locked) 06201 ast_unlock_context(con); 06202 return -1; 06203 } 06204 06205 /* scan the priority list to remove extension with exten->priority == priority */ 06206 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 06207 peer && !strcmp(peer->exten, extension) && 06208 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ; 06209 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 06210 06211 if ((priority == 0 || peer->priority == priority) && 06212 (!registrar || !strcmp(peer->registrar, registrar) )) { 06213 found = 1; 06214 06215 /* we are first priority extension? */ 06216 if (!previous_peer) { 06217 /* 06218 * We are first in the priority chain, so must update the extension chain. 06219 * The next node is either the next priority or the next extension 06220 */ 06221 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 06222 if (peer->peer) { 06223 /* move the peer_table and peer_label_table down to the next peer, if 06224 it is there */ 06225 peer->peer->peer_table = peer->peer_table; 06226 peer->peer->peer_label_table = peer->peer_label_table; 06227 peer->peer_table = NULL; 06228 peer->peer_label_table = NULL; 06229 } 06230 if (!prev_exten) { /* change the root... */ 06231 con->root = next_node; 06232 } else { 06233 prev_exten->next = next_node; /* unlink */ 06234 } 06235 if (peer->peer) { /* update the new head of the pri list */ 06236 peer->peer->next = peer->next; 06237 } 06238 } else { /* easy, we are not first priority in extension */ 06239 previous_peer->peer = peer->peer; 06240 } 06241 06242 06243 /* now, free whole priority extension */ 06244 destroy_exten(peer); 06245 } else { 06246 previous_peer = peer; 06247 } 06248 } 06249 if (!already_locked) 06250 ast_unlock_context(con); 06251 return found ? 0 : -1; 06252 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8508 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08509 { 08510 int ret = -1; 08511 struct ast_context *c; 08512 08513 c = find_context_locked(context); 08514 if (c) { 08515 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08516 ast_unlock_contexts(); 08517 } 08518 return ret; 08519 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8521 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().
08522 { 08523 struct ast_ignorepat *ip, *ipl = NULL; 08524 08525 ast_wrlock_context(con); 08526 08527 for (ip = con->ignorepats; ip; ip = ip->next) { 08528 if (!strcmp(ip->pattern, ignorepat) && 08529 (!registrar || (registrar == ip->registrar))) { 08530 if (ipl) { 08531 ipl->next = ip->next; 08532 ast_free(ip); 08533 } else { 08534 con->ignorepats = ip->next; 08535 ast_free(ip); 08536 } 08537 ast_unlock_context(con); 08538 return 0; 08539 } 08540 ipl = ip; 08541 } 08542 08543 ast_unlock_context(con); 08544 errno = EINVAL; 08545 return -1; 08546 }
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 5961 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05962 { 05963 int ret = -1; 05964 struct ast_context *c; 05965 05966 c = find_context_locked(context); 05967 if (c) { 05968 /* found, remove include from this context ... */ 05969 ret = ast_context_remove_include2(c, include, registrar); 05970 ast_unlock_contexts(); 05971 } 05972 return ret; 05973 }
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 5984 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().
05985 { 05986 struct ast_include *i, *pi = NULL; 05987 int ret = -1; 05988 05989 ast_wrlock_context(con); 05990 05991 /* find our include */ 05992 for (i = con->includes; i; pi = i, i = i->next) { 05993 if (!strcmp(i->name, include) && 05994 (!registrar || !strcmp(i->registrar, registrar))) { 05995 /* remove from list */ 05996 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05997 if (pi) 05998 pi->next = i->next; 05999 else 06000 con->includes = i->next; 06001 /* free include and return */ 06002 ast_destroy_timing(&(i->timing)); 06003 ast_free(i); 06004 ret = 0; 06005 break; 06006 } 06007 } 06008 06009 ast_unlock_context(con); 06010 06011 return ret; 06012 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 6019 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
06020 { 06021 int ret = -1; /* default error return */ 06022 struct ast_context *c; 06023 06024 c = find_context_locked(context); 06025 if (c) { 06026 /* remove switch from this context ... */ 06027 ret = ast_context_remove_switch2(c, sw, data, registrar); 06028 ast_unlock_contexts(); 06029 } 06030 return ret; 06031 }
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 6041 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().
06042 { 06043 struct ast_sw *i; 06044 int ret = -1; 06045 06046 ast_wrlock_context(con); 06047 06048 /* walk switches */ 06049 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 06050 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 06051 (!registrar || !strcmp(i->registrar, registrar))) { 06052 /* found, remove from list */ 06053 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 06054 AST_LIST_REMOVE_CURRENT(list); 06055 ast_free(i); /* free switch and return */ 06056 ret = 0; 06057 break; 06058 } 06059 } 06060 AST_LIST_TRAVERSE_SAFE_END; 06061 06062 ast_unlock_context(con); 06063 06064 return ret; 06065 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 6281 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06282 { 06283 struct ast_context *c; 06284 int ret = -1; 06285 06286 c = find_context_locked(context); 06287 if (c) { 06288 ast_unlock_contexts(); 06289 06290 /* if we found context, unlock macrolock */ 06291 ret = ast_mutex_unlock(&c->macrolock); 06292 } 06293 06294 return ret; 06295 }
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 11080 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().
11081 { 11082 struct ast_include *inc = NULL; 11083 int res = 0; 11084 11085 while ( (inc = ast_walk_context_includes(con, inc)) ) { 11086 if (ast_context_find(inc->rname)) 11087 continue; 11088 11089 res = -1; 11090 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 11091 ast_get_context_name(con), inc->rname); 11092 break; 11093 } 11094 11095 return res; 11096 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3754 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_compile_ael2(), ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03755 { 03756 struct ast_custom_function *acf = NULL; 03757 03758 AST_RWLIST_RDLOCK(&acf_root); 03759 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03760 if (!strcmp(name, acf->name)) 03761 break; 03762 } 03763 AST_RWLIST_UNLOCK(&acf_root); 03764 03765 return acf; 03766 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3768 of file pbx.c.
References ast_custom_escalating_function::acf, ast_free, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by __ast_custom_function_register_escalating(), _unload_module(), load_module(), reload(), unload_module(), and unload_pbx().
03769 { 03770 struct ast_custom_function *cur; 03771 struct ast_custom_escalating_function *cur_escalation; 03772 03773 if (!acf) { 03774 return -1; 03775 } 03776 03777 AST_RWLIST_WRLOCK(&acf_root); 03778 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03779 #ifdef AST_XML_DOCS 03780 if (cur->docsrc == AST_XML_DOC) { 03781 ast_string_field_free_memory(acf); 03782 } 03783 #endif 03784 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03785 } 03786 AST_RWLIST_UNLOCK(&acf_root); 03787 03788 /* Remove from the escalation list */ 03789 AST_RWLIST_WRLOCK(&escalation_root); 03790 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) { 03791 if (cur_escalation->acf == acf) { 03792 AST_RWLIST_REMOVE_CURRENT(list); 03793 ast_free(cur_escalation); 03794 break; 03795 } 03796 } 03797 AST_RWLIST_TRAVERSE_SAFE_END; 03798 AST_RWLIST_UNLOCK(&escalation_root); 03799 03800 return cur ? 0 : -1; 03801 }
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 8350 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
[in] | devstate | device state |
Definition at line 4798 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.
Referenced by ast_extension_state3().
04799 { 04800 switch (devstate) { 04801 case AST_DEVICE_ONHOLD: 04802 return AST_EXTENSION_ONHOLD; 04803 case AST_DEVICE_BUSY: 04804 return AST_EXTENSION_BUSY; 04805 case AST_DEVICE_UNKNOWN: 04806 return AST_EXTENSION_NOT_INUSE; 04807 case AST_DEVICE_UNAVAILABLE: 04808 case AST_DEVICE_INVALID: 04809 return AST_EXTENSION_UNAVAILABLE; 04810 case AST_DEVICE_RINGINUSE: 04811 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04812 case AST_DEVICE_RINGING: 04813 return AST_EXTENSION_RINGING; 04814 case AST_DEVICE_INUSE: 04815 return AST_EXTENSION_INUSE; 04816 case AST_DEVICE_NOT_INUSE: 04817 return AST_EXTENSION_NOT_INUSE; 04818 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04819 break; 04820 } 04821 04822 return AST_EXTENSION_NOT_INUSE; 04823 }
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 5354 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().
05355 { 05356 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05357 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8662 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(), and pbx_parseable_goto().
08663 { 08664 if (!chan) 08665 return -1; 08666 08667 ast_channel_lock(chan); 08668 08669 if (!ast_strlen_zero(context)) 08670 ast_copy_string(chan->context, context, sizeof(chan->context)); 08671 if (!ast_strlen_zero(exten)) 08672 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08673 if (priority > -1) { 08674 chan->priority = priority; 08675 /* see flag description in channel.h for explanation */ 08676 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08677 chan->priority--; 08678 } 08679 08680 ast_channel_unlock(chan); 08681 08682 return 0; 08683 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2902 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().
02903 { 02904 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02905 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02906 return extension_match_core(pattern, data, needmore); 02907 }
int ast_extension_cmp | ( | const char * | a, | |
const char * | b | |||
) |
Determine if one extension should match before another.
Checks whether or extension a should match before extension b
0 | if the two extensions have equal matching priority | |
1 | on a > b | |
-1 | on a < b |
Definition at line 2667 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02668 { 02669 int cmp; 02670 02671 cmp = ext_cmp(a, b); 02672 if (cmp < 0) { 02673 return -1; 02674 } 02675 if (cmp > 0) { 02676 return 1; 02677 } 02678 return 0; 02679 }
int ast_extension_match | ( | const char * | pattern, | |
const char * | extension | |||
) |
Determine if a given extension matches a given pattern (in NXX format).
Checks whether or not the given extension matches the given pattern.
1 | on match | |
0 | on failure |
Definition at line 2897 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().
02898 { 02899 return extension_match_core(pattern, data, E_MATCH); 02900 }
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 4868 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.
Referenced by action_extensionstate(), extstate_read(), get_queue_member_status(), and handle_request_subscribe().
04869 { 04870 struct ast_exten *e; 04871 04872 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04873 return -1; /* No hint, return -1 */ 04874 } 04875 04876 if (e->exten[0] == '_') { 04877 /* Create this hint on-the-fly */ 04878 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04879 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04880 e->registrar); 04881 if (!(e = ast_hint_extension(c, context, exten))) { 04882 /* Improbable, but not impossible */ 04883 return -1; 04884 } 04885 } 04886 04887 return ast_extension_state2(e); /* Check all devices in the hint */ 04888 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4843 of file pbx.c.
References ast_extension_state3(), ast_get_extension_app(), ast_str_set(), ast_str_thread_get(), and extensionstate_buf.
Referenced by ast_add_hint(), and ast_extension_state().
04844 { 04845 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32); 04846 04847 if (!e || !hint_app) { 04848 return -1; 04849 } 04850 04851 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e)); 04852 return ast_extension_state3(hint_app); 04853 }
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 4856 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), and show_channels_cb().
04857 { 04858 int i; 04859 04860 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04861 if (extension_states[i].extension_state == extension_state) 04862 return extension_states[i].text; 04863 } 04864 return "Unknown"; 04865 }
static int ast_extension_state3 | ( | struct ast_str * | hint_app | ) | [static] |
Definition at line 4825 of file pbx.c.
References ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), and ast_str_buffer().
Referenced by ast_extension_state2(), and handle_statechange().
04826 { 04827 char *cur; 04828 char *rest; 04829 struct ast_devstate_aggregate agg; 04830 04831 /* One or more devices separated with a & character */ 04832 rest = ast_str_buffer(hint_app); 04833 04834 ast_devstate_aggregate_init(&agg); 04835 while ((cur = strsep(&rest, "&"))) { 04836 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04837 } 04838 04839 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04840 }
int ast_extension_state_add | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
void * | data | |||
) |
Add watcher for extension states.
Registers a state change callback.
Definition at line 5089 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
05091 { 05092 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 05093 }
int ast_extension_state_add_destroy | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
ast_state_cb_destroy_type | destroy_cb, | |||
void * | data | |||
) |
Add watcher for extension states with destructor.
Registers a state change callback with destructor.
Definition at line 5002 of file pbx.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, hints, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.
Referenced by ast_extension_state_add(), and handle_request_subscribe().
05004 { 05005 struct ast_hint *hint; 05006 struct ast_state_cb *state_cb; 05007 struct ast_exten *e; 05008 int id; 05009 05010 /* If there's no context and extension: add callback to statecbs list */ 05011 if (!context && !exten) { 05012 /* Prevent multiple adds from adding the same change_cb at the same time. */ 05013 ao2_lock(statecbs); 05014 05015 /* Remove any existing change_cb. */ 05016 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 05017 05018 /* Now insert the change_cb */ 05019 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05020 ao2_unlock(statecbs); 05021 return -1; 05022 } 05023 state_cb->id = 0; 05024 state_cb->change_cb = change_cb; 05025 state_cb->destroy_cb = destroy_cb; 05026 state_cb->data = data; 05027 ao2_link(statecbs, state_cb); 05028 05029 ao2_ref(state_cb, -1); 05030 ao2_unlock(statecbs); 05031 return 0; 05032 } 05033 05034 if (!context || !exten) 05035 return -1; 05036 05037 /* This callback type is for only one hint, so get the hint */ 05038 e = ast_hint_extension(NULL, context, exten); 05039 if (!e) { 05040 return -1; 05041 } 05042 05043 /* If this is a pattern, dynamically create a new extension for this 05044 * particular match. Note that this will only happen once for each 05045 * individual extension, because the pattern will no longer match first. 05046 */ 05047 if (e->exten[0] == '_') { 05048 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 05049 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 05050 e->registrar); 05051 e = ast_hint_extension(NULL, context, exten); 05052 if (!e || e->exten[0] == '_') { 05053 return -1; 05054 } 05055 } 05056 05057 /* Find the hint in the hints container */ 05058 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05059 hint = ao2_find(hints, e, 0); 05060 if (!hint) { 05061 ao2_unlock(hints); 05062 return -1; 05063 } 05064 05065 /* Now insert the callback in the callback list */ 05066 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05067 ao2_ref(hint, -1); 05068 ao2_unlock(hints); 05069 return -1; 05070 } 05071 do { 05072 id = stateid++; /* Unique ID for this callback */ 05073 /* Do not allow id to ever be -1 or 0. */ 05074 } while (id == -1 || id == 0); 05075 state_cb->id = id; 05076 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 05077 state_cb->destroy_cb = destroy_cb; 05078 state_cb->data = data; /* Data for the callback */ 05079 ao2_link(hint->callbacks, state_cb); 05080 05081 ao2_ref(state_cb, -1); 05082 ao2_ref(hint, -1); 05083 ao2_unlock(hints); 05084 05085 return id; 05086 }
int ast_extension_state_del | ( | int | id, | |
ast_state_cb_type | change_cb | |||
) |
ast_extension_state_del: Remove a watcher from the callback list
Deletes a registered state change callback by ID.
Definition at line 5111 of file pbx.c.
References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::callbacks, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
05112 { 05113 struct ast_state_cb *p_cur; 05114 int ret = -1; 05115 05116 if (!id) { /* id == 0 is a callback without extension */ 05117 if (!change_cb) { 05118 return ret; 05119 } 05120 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 05121 if (p_cur) { 05122 ret = 0; 05123 ao2_ref(p_cur, -1); 05124 } 05125 } else { /* callback with extension, find the callback based on ID */ 05126 struct ast_hint *hint; 05127 05128 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05129 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 05130 if (hint) { 05131 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 05132 if (p_cur) { 05133 ret = 0; 05134 ao2_ref(p_cur, -1); 05135 } 05136 ao2_ref(hint, -1); 05137 } 05138 ao2_unlock(hints); 05139 } 05140 05141 return ret; 05142 }
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 5359 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().
05360 { 05361 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05362 }
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 5364 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05365 { 05366 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05367 }
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 4131 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
04132 { 04133 char *copy = ast_strdupa(function); 04134 char *args = func_args(copy); 04135 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04136 int res; 04137 struct ast_module_user *u = NULL; 04138 04139 if (acfptr == NULL) { 04140 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04141 } else if (!acfptr->read && !acfptr->read2) { 04142 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04143 } else if (!is_read_allowed(acfptr)) { 04144 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04145 } else if (acfptr->read) { 04146 if (acfptr->mod) { 04147 u = __ast_module_user_add(acfptr->mod, chan); 04148 } 04149 res = acfptr->read(chan, copy, args, workspace, len); 04150 if (acfptr->mod && u) { 04151 __ast_module_user_remove(acfptr->mod, u); 04152 } 04153 return res; 04154 } else { 04155 struct ast_str *str = ast_str_create(16); 04156 if (acfptr->mod) { 04157 u = __ast_module_user_add(acfptr->mod, chan); 04158 } 04159 res = acfptr->read2(chan, copy, args, &str, 0); 04160 if (acfptr->mod && u) { 04161 __ast_module_user_remove(acfptr->mod, u); 04162 } 04163 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 04164 ast_free(str); 04165 return res; 04166 } 04167 return -1; 04168 }
int ast_func_read2 | ( | struct ast_channel * | chan, | |
const char * | function, | |||
struct ast_str ** | str, | |||
ssize_t | maxlen | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
str | A dynamic string buffer into which to place the result. | |
maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 4170 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
04171 { 04172 char *copy = ast_strdupa(function); 04173 char *args = func_args(copy); 04174 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04175 int res; 04176 struct ast_module_user *u = NULL; 04177 04178 if (acfptr == NULL) { 04179 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04180 } else if (!acfptr->read && !acfptr->read2) { 04181 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04182 } else if (!is_read_allowed(acfptr)) { 04183 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04184 } else { 04185 if (acfptr->mod) { 04186 u = __ast_module_user_add(acfptr->mod, chan); 04187 } 04188 ast_str_reset(*str); 04189 if (acfptr->read2) { 04190 /* ast_str enabled */ 04191 res = acfptr->read2(chan, copy, args, str, maxlen); 04192 } else { 04193 /* Legacy function pointer, allocate buffer for result */ 04194 int maxsize = ast_str_size(*str); 04195 if (maxlen > -1) { 04196 if (maxlen == 0) { 04197 if (acfptr->read_max) { 04198 maxsize = acfptr->read_max; 04199 } else { 04200 maxsize = VAR_BUF_SIZE; 04201 } 04202 } else { 04203 maxsize = maxlen; 04204 } 04205 ast_str_make_space(str, maxsize); 04206 } 04207 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 04208 } 04209 if (acfptr->mod && u) { 04210 __ast_module_user_remove(acfptr->mod, u); 04211 } 04212 return res; 04213 } 04214 return -1; 04215 }
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 4217 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), is_write_allowed(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
04218 { 04219 char *copy = ast_strdupa(function); 04220 char *args = func_args(copy); 04221 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04222 04223 if (acfptr == NULL) { 04224 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04225 } else if (!acfptr->write) { 04226 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 04227 } else if (!is_write_allowed(acfptr)) { 04228 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy); 04229 } else { 04230 int res; 04231 struct ast_module_user *u = NULL; 04232 if (acfptr->mod) 04233 u = __ast_module_user_add(acfptr->mod, chan); 04234 res = acfptr->write(chan, copy, args, value); 04235 if (acfptr->mod && u) 04236 __ast_module_user_remove(acfptr->mod, u); 04237 return res; 04238 } 04239 04240 return -1; 04241 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10932 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_compile_ael2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), ast_remove_hint(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10933 { 10934 return con ? con->name : NULL; 10935 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10970 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10971 { 10972 return c ? c->registrar : NULL; 10973 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 11000 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), get_parking_exten(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
11001 { 11002 return e ? e->app : NULL; 11003 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 11005 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_masq_park_call_exten(), ast_park_call_exten(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), print_ext(), and xfer_park_call_helper().
11006 { 11007 return e ? e->data : NULL; 11008 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10995 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10996 { 10997 return e ? e->cidmatch : NULL; 10998 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10937 of file pbx.c.
References ast_exten::parent.
Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
10938 { 10939 return exten ? exten->parent : NULL; 10940 }
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 10947 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10948 { 10949 return exten ? exten->label : NULL; 10950 }
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 10990 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10991 { 10992 return e ? e->matchcid : 0; 10993 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10942 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint(), ast_remove_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), destroy_hint(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().
10943 { 10944 return exten ? exten->exten : NULL; 10945 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10962 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().
10963 { 10964 return exten ? exten->priority : -1; 10965 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10975 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10976 { 10977 return e ? e->registrar : NULL; 10978 }
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 5316 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().
05317 { 05318 struct ast_exten *e = ast_hint_extension(c, context, exten); 05319 05320 if (e) { 05321 if (hint) 05322 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05323 if (name) { 05324 const char *tmp = ast_get_extension_app_data(e); 05325 if (tmp) 05326 ast_copy_string(name, tmp, namesize); 05327 } 05328 return -1; 05329 } 05330 return 0; 05331 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10957 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().
10958 { 10959 return ip ? ip->pattern : NULL; 10960 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10985 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().
10986 { 10987 return ip ? ip->registrar : NULL; 10988 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 10952 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().
10953 { 10954 return inc ? inc->name : NULL; 10955 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 10980 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().
10981 { 10982 return i ? i->registrar : NULL; 10983 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 11015 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().
11016 { 11017 return sw ? sw->data : NULL; 11018 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 11020 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
11021 { 11022 return sw->eval; 11023 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 11010 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().
11011 { 11012 return sw ? sw->name : NULL; 11013 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 11025 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().
11026 { 11027 return sw ? sw->registrar : NULL; 11028 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11120 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
11121 { 11122 return __ast_goto_if_exists(chan, context, exten, priority, 0); 11123 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1092 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01093 { 01094 const struct ast_context *ac = ah_a; 01095 const struct ast_context *bc = ah_b; 01096 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01097 return 1; 01098 /* assume context names are registered in a string table! */ 01099 return strcmp(ac->name, bc->name); 01100 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1144 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01145 { 01146 const struct ast_context *ac = obj; 01147 return ast_hashtab_hash_string(ac->name); 01148 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static, read] |
Definition at line 4789 of file pbx.c.
References ast_hint_extension_nolock(), ast_rdlock_contexts(), and ast_unlock_contexts().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), ast_get_hint(), and ast_str_get_hint().
04790 { 04791 struct ast_exten *e; 04792 ast_rdlock_contexts(); 04793 e = ast_hint_extension_nolock(c, context, exten); 04794 ast_unlock_contexts(); 04795 return e; 04796 }
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 4783 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().
04784 { 04785 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04786 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04787 }
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 8604 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), and skinny_ss().
08605 { 08606 struct ast_context *con = ast_context_find(context); 08607 08608 if (con) { 08609 struct ast_ignorepat *pat; 08610 08611 for (pat = con->ignorepats; pat; pat = pat->next) { 08612 if (ast_extension_match(pat->pattern, pattern)) 08613 return 1; 08614 } 08615 } 08616 08617 return 0; 08618 }
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 5374 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().
05375 { 05376 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05377 }
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 7891 of file pbx.c.
References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07892 { 07893 double ft; 07894 struct ast_context *tmp; 07895 struct ast_context *oldcontextslist; 07896 struct ast_hashtab *oldtable; 07897 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07898 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07899 struct store_hint *saved_hint; 07900 struct ast_hint *hint; 07901 struct ast_exten *exten; 07902 int length; 07903 struct ast_state_cb *thiscb; 07904 struct ast_hashtab_iter *iter; 07905 struct ao2_iterator i; 07906 struct timeval begintime; 07907 struct timeval writelocktime; 07908 struct timeval endlocktime; 07909 struct timeval enddeltime; 07910 07911 /* 07912 * It is very important that this function hold the hints 07913 * container lock _and_ the conlock during its operation; not 07914 * only do we need to ensure that the list of contexts and 07915 * extensions does not change, but also that no hint callbacks 07916 * (watchers) are added or removed during the merge/delete 07917 * process 07918 * 07919 * In addition, the locks _must_ be taken in this order, because 07920 * there are already other code paths that use this order 07921 */ 07922 07923 begintime = ast_tvnow(); 07924 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07925 ast_wrlock_contexts(); 07926 07927 if (!contexts_table) { 07928 /* Well, that's odd. There are no contexts. */ 07929 contexts_table = exttable; 07930 contexts = *extcontexts; 07931 ast_unlock_contexts(); 07932 ast_mutex_unlock(&context_merge_lock); 07933 return; 07934 } 07935 07936 iter = ast_hashtab_start_traversal(contexts_table); 07937 while ((tmp = ast_hashtab_next(iter))) { 07938 context_merge(extcontexts, exttable, tmp, registrar); 07939 } 07940 ast_hashtab_end_traversal(iter); 07941 07942 ao2_lock(hints); 07943 writelocktime = ast_tvnow(); 07944 07945 /* preserve all watchers for hints */ 07946 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07947 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07948 if (ao2_container_count(hint->callbacks)) { 07949 ao2_lock(hint); 07950 if (!hint->exten) { 07951 /* The extension has already been destroyed. (Should never happen here) */ 07952 ao2_unlock(hint); 07953 continue; 07954 } 07955 07956 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07957 + sizeof(*saved_hint); 07958 if (!(saved_hint = ast_calloc(1, length))) { 07959 ao2_unlock(hint); 07960 continue; 07961 } 07962 07963 /* This removes all the callbacks from the hint into saved_hint. */ 07964 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07965 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07966 /* 07967 * We intentionally do not unref thiscb to account for the 07968 * non-ao2 reference in saved_hint->callbacks 07969 */ 07970 } 07971 07972 saved_hint->laststate = hint->laststate; 07973 saved_hint->context = saved_hint->data; 07974 strcpy(saved_hint->data, hint->exten->parent->name); 07975 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07976 strcpy(saved_hint->exten, hint->exten->exten); 07977 ao2_unlock(hint); 07978 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07979 } 07980 } 07981 ao2_iterator_destroy(&i); 07982 07983 /* save the old table and list */ 07984 oldtable = contexts_table; 07985 oldcontextslist = contexts; 07986 07987 /* move in the new table and list */ 07988 contexts_table = exttable; 07989 contexts = *extcontexts; 07990 07991 /* 07992 * Restore the watchers for hints that can be found; notify 07993 * those that cannot be restored. 07994 */ 07995 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07996 struct pbx_find_info q = { .stacklen = 0 }; 07997 07998 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07999 PRIORITY_HINT, NULL, "", E_MATCH); 08000 /* 08001 * If this is a pattern, dynamically create a new extension for this 08002 * particular match. Note that this will only happen once for each 08003 * individual extension, because the pattern will no longer match first. 08004 */ 08005 if (exten && exten->exten[0] == '_') { 08006 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 08007 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 08008 exten->registrar); 08009 /* rwlocks are not recursive locks */ 08010 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 08011 saved_hint->exten); 08012 } 08013 08014 /* Find the hint in the hints container */ 08015 hint = exten ? ao2_find(hints, exten, 0) : NULL; 08016 if (!hint) { 08017 /* 08018 * Notify watchers of this removed hint later when we aren't 08019 * encumberd by so many locks. 08020 */ 08021 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 08022 } else { 08023 ao2_lock(hint); 08024 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08025 ao2_link(hint->callbacks, thiscb); 08026 /* Ref that we added when putting into saved_hint->callbacks */ 08027 ao2_ref(thiscb, -1); 08028 } 08029 hint->laststate = saved_hint->laststate; 08030 ao2_unlock(hint); 08031 ao2_ref(hint, -1); 08032 ast_free(saved_hint); 08033 } 08034 } 08035 08036 ao2_unlock(hints); 08037 ast_unlock_contexts(); 08038 08039 /* 08040 * Notify watchers of all removed hints with the same lock 08041 * environment as handle_statechange(). 08042 */ 08043 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 08044 /* this hint has been removed, notify the watchers */ 08045 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08046 thiscb->change_cb(saved_hint->context, saved_hint->exten, 08047 AST_EXTENSION_REMOVED, thiscb->data); 08048 /* Ref that we added when putting into saved_hint->callbacks */ 08049 ao2_ref(thiscb, -1); 08050 } 08051 ast_free(saved_hint); 08052 } 08053 08054 ast_mutex_unlock(&context_merge_lock); 08055 endlocktime = ast_tvnow(); 08056 08057 /* 08058 * The old list and hashtab no longer are relevant, delete them 08059 * while the rest of asterisk is now freely using the new stuff 08060 * instead. 08061 */ 08062 08063 ast_hashtab_destroy(oldtable, NULL); 08064 08065 for (tmp = oldcontextslist; tmp; ) { 08066 struct ast_context *next; /* next starting point */ 08067 08068 next = tmp->next; 08069 __ast_internal_context_destroy(tmp); 08070 tmp = next; 08071 } 08072 enddeltime = ast_tvnow(); 08073 08074 ft = ast_tvdiff_us(writelocktime, begintime); 08075 ft /= 1000000.0; 08076 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 08077 08078 ft = ast_tvdiff_us(endlocktime, writelocktime); 08079 ft /= 1000000.0; 08080 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 08081 08082 ft = ast_tvdiff_us(enddeltime, endlocktime); 08083 ft /= 1000000.0; 08084 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 08085 08086 ft = ast_tvdiff_us(enddeltime, begintime); 08087 ft /= 1000000.0; 08088 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 08089 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11185 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().
11186 { 11187 return pbx_parseable_goto(chan, goto_string, 0); 11188 }
int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 11266 of file pbx.c.
References ao2_container_alloc, ast_register_atexit(), HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hints, pbx_shutdown(), statecbs, and statecbs_cmp().
Referenced by main().
11267 { 11268 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 11269 statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); 11270 11271 ast_register_atexit(pbx_shutdown); 11272 11273 return (hints && statecbs) ? 0 : -1; 11274 }
int ast_pbx_outgoing_app | ( | const char * | type, | |
format_t | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | app, | |||
const char * | appdata, | |||
int * | reason, | |||
int | sync, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular application with given extension
Definition at line 9498 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
09499 { 09500 struct ast_channel *chan; 09501 struct app_tmp *tmp; 09502 int res = -1, cdr_res = -1; 09503 struct outgoing_helper oh; 09504 09505 memset(&oh, 0, sizeof(oh)); 09506 oh.vars = vars; 09507 oh.account = account; 09508 09509 if (locked_channel) 09510 *locked_channel = NULL; 09511 if (ast_strlen_zero(app)) { 09512 res = -1; 09513 goto outgoing_app_cleanup; 09514 } 09515 if (synchronous) { 09516 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09517 if (chan) { 09518 ast_set_variables(chan, vars); 09519 if (account) 09520 ast_cdr_setaccount(chan, account); 09521 if (chan->_state == AST_STATE_UP) { 09522 res = 0; 09523 ast_verb(4, "Channel %s was answered.\n", chan->name); 09524 tmp = ast_calloc(1, sizeof(*tmp)); 09525 if (!tmp || ast_string_field_init(tmp, 252)) { 09526 if (tmp) { 09527 ast_free(tmp); 09528 } 09529 res = -1; 09530 } else { 09531 ast_string_field_set(tmp, app, app); 09532 ast_string_field_set(tmp, data, appdata); 09533 tmp->chan = chan; 09534 if (synchronous > 1) { 09535 if (locked_channel) 09536 ast_channel_unlock(chan); 09537 ast_pbx_run_app(tmp); 09538 } else { 09539 if (locked_channel) 09540 ast_channel_lock(chan); 09541 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09542 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09543 ast_string_field_free_memory(tmp); 09544 ast_free(tmp); 09545 if (locked_channel) 09546 ast_channel_unlock(chan); 09547 ast_hangup(chan); 09548 res = -1; 09549 } else { 09550 if (locked_channel) 09551 *locked_channel = chan; 09552 } 09553 } 09554 } 09555 } else { 09556 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09557 if (chan->cdr) { /* update the cdr */ 09558 /* here we update the status of the call, which sould be busy. 09559 * if that fails then we set the status to failed */ 09560 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09561 ast_cdr_failed(chan->cdr); 09562 } 09563 ast_hangup(chan); 09564 } 09565 } 09566 09567 if (res < 0) { /* the call failed for some reason */ 09568 if (*reason == 0) { /* if the call failed (not busy or no answer) 09569 * update the cdr with the failed message */ 09570 cdr_res = ast_pbx_outgoing_cdr_failed(); 09571 if (cdr_res != 0) { 09572 res = cdr_res; 09573 goto outgoing_app_cleanup; 09574 } 09575 } 09576 } 09577 09578 } else { 09579 struct async_stat *as; 09580 if (!(as = ast_calloc(1, sizeof(*as)))) { 09581 res = -1; 09582 goto outgoing_app_cleanup; 09583 } 09584 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09585 if (!chan) { 09586 ast_free(as); 09587 res = -1; 09588 goto outgoing_app_cleanup; 09589 } 09590 as->chan = chan; 09591 ast_copy_string(as->app, app, sizeof(as->app)); 09592 if (appdata) 09593 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09594 as->timeout = timeout; 09595 ast_set_variables(chan, vars); 09596 if (account) 09597 ast_cdr_setaccount(chan, account); 09598 /* Start a new thread, and get something handling this channel. */ 09599 if (locked_channel) 09600 ast_channel_lock(chan); 09601 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09602 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09603 ast_free(as); 09604 if (locked_channel) 09605 ast_channel_unlock(chan); 09606 ast_hangup(chan); 09607 res = -1; 09608 goto outgoing_app_cleanup; 09609 } else { 09610 if (locked_channel) 09611 *locked_channel = chan; 09612 } 09613 res = 0; 09614 } 09615 outgoing_app_cleanup: 09616 ast_variables_destroy(vars); 09617 return res; 09618 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 9302 of file pbx.c.
References ast_cdr_alloc(), ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_unref, ast_dummy_channel_alloc, and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
09303 { 09304 /* allocate a channel */ 09305 struct ast_channel *chan = ast_dummy_channel_alloc(); 09306 09307 if (!chan) 09308 return -1; /* failure */ 09309 09310 chan->cdr = ast_cdr_alloc(); 09311 if (!chan->cdr) { 09312 /* allocation of the cdr failed */ 09313 chan = ast_channel_unref(chan); /* free the channel */ 09314 return -1; /* return failure */ 09315 } 09316 09317 /* allocation of the cdr was successful */ 09318 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 09319 ast_cdr_start(chan->cdr); /* record the start and stop time */ 09320 ast_cdr_end(chan->cdr); 09321 ast_cdr_failed(chan->cdr); /* set the status to failed */ 09322 ast_cdr_detach(chan->cdr); /* post and free the record */ 09323 chan->cdr = NULL; 09324 chan = ast_channel_unref(chan); /* free the channel */ 09325 09326 return 0; /* success */ 09327 }
int ast_pbx_outgoing_exten | ( | const char * | type, | |
format_t | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int * | reason, | |||
int | sync, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular extension
Definition at line 9329 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
09330 { 09331 struct ast_channel *chan; 09332 struct async_stat *as; 09333 int res = -1, cdr_res = -1; 09334 struct outgoing_helper oh; 09335 09336 if (synchronous) { 09337 oh.context = context; 09338 oh.exten = exten; 09339 oh.priority = priority; 09340 oh.cid_num = cid_num; 09341 oh.cid_name = cid_name; 09342 oh.account = account; 09343 oh.vars = vars; 09344 oh.parent_channel = NULL; 09345 09346 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09347 if (channel) { 09348 *channel = chan; 09349 if (chan) 09350 ast_channel_lock(chan); 09351 } 09352 if (chan) { 09353 if (chan->_state == AST_STATE_UP) { 09354 res = 0; 09355 ast_verb(4, "Channel %s was answered.\n", chan->name); 09356 09357 if (synchronous > 1) { 09358 if (channel) 09359 ast_channel_unlock(chan); 09360 if (ast_pbx_run(chan)) { 09361 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09362 if (channel) 09363 *channel = NULL; 09364 ast_hangup(chan); 09365 chan = NULL; 09366 res = -1; 09367 } 09368 } else { 09369 if (ast_pbx_start(chan)) { 09370 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09371 if (channel) { 09372 *channel = NULL; 09373 ast_channel_unlock(chan); 09374 } 09375 ast_hangup(chan); 09376 res = -1; 09377 } 09378 chan = NULL; 09379 } 09380 } else { 09381 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09382 09383 if (chan->cdr) { /* update the cdr */ 09384 /* here we update the status of the call, which sould be busy. 09385 * if that fails then we set the status to failed */ 09386 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09387 ast_cdr_failed(chan->cdr); 09388 } 09389 09390 if (channel) { 09391 *channel = NULL; 09392 ast_channel_unlock(chan); 09393 } 09394 ast_hangup(chan); 09395 chan = NULL; 09396 } 09397 } 09398 09399 if (res < 0) { /* the call failed for some reason */ 09400 if (*reason == 0) { /* if the call failed (not busy or no answer) 09401 * update the cdr with the failed message */ 09402 cdr_res = ast_pbx_outgoing_cdr_failed(); 09403 if (cdr_res != 0) { 09404 res = cdr_res; 09405 goto outgoing_exten_cleanup; 09406 } 09407 } 09408 09409 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09410 /* check if "failed" exists */ 09411 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09412 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09413 if (chan) { 09414 char failed_reason[4] = ""; 09415 if (!ast_strlen_zero(context)) 09416 ast_copy_string(chan->context, context, sizeof(chan->context)); 09417 set_ext_pri(chan, "failed", 1); 09418 ast_set_variables(chan, vars); 09419 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09420 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09421 if (account) 09422 ast_cdr_setaccount(chan, account); 09423 if (ast_pbx_run(chan)) { 09424 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09425 ast_hangup(chan); 09426 } 09427 chan = NULL; 09428 } 09429 } 09430 } 09431 } else { 09432 if (!(as = ast_calloc(1, sizeof(*as)))) { 09433 res = -1; 09434 goto outgoing_exten_cleanup; 09435 } 09436 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09437 if (channel) { 09438 *channel = chan; 09439 if (chan) 09440 ast_channel_lock(chan); 09441 } 09442 if (!chan) { 09443 ast_free(as); 09444 res = -1; 09445 goto outgoing_exten_cleanup; 09446 } 09447 as->chan = chan; 09448 ast_copy_string(as->context, context, sizeof(as->context)); 09449 set_ext_pri(as->chan, exten, priority); 09450 as->timeout = timeout; 09451 ast_set_variables(chan, vars); 09452 if (account) 09453 ast_cdr_setaccount(chan, account); 09454 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09455 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09456 ast_free(as); 09457 if (channel) { 09458 *channel = NULL; 09459 ast_channel_unlock(chan); 09460 } 09461 ast_hangup(chan); 09462 res = -1; 09463 goto outgoing_exten_cleanup; 09464 } 09465 res = 0; 09466 } 09467 outgoing_exten_cleanup: 09468 ast_variables_destroy(vars); 09469 return res; 09470 }
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 5880 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_notify(), mgcp_ss(), skinny_newcall(), and unistim_ss().
05881 { 05882 return ast_pbx_run_args(c, NULL); 05883 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 9482 of file pbx.c.
References app_tmp::app, ast_free, ast_hangup(), ast_log(), ast_string_field_free_memory, ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, pbx_exec(), and pbx_findapp().
Referenced by ast_pbx_outgoing_app().
09483 { 09484 struct app_tmp *tmp = data; 09485 struct ast_app *app; 09486 app = pbx_findapp(tmp->app); 09487 if (app) { 09488 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 09489 pbx_exec(tmp->chan, app, tmp->data); 09490 } else 09491 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 09492 ast_hangup(tmp->chan); 09493 ast_string_field_free_memory(tmp); 09494 ast_free(tmp); 09495 return NULL; 09496 }
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 5860 of file pbx.c.
References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
05861 { 05862 enum ast_pbx_result res = AST_PBX_SUCCESS; 05863 05864 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05865 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05866 return AST_PBX_FAILED; 05867 } 05868 05869 if (increase_call_count(c)) { 05870 return AST_PBX_CALL_LIMIT; 05871 } 05872 05873 res = __ast_pbx_run(c, args); 05874 05875 decrease_call_count(); 05876 05877 return res; 05878 }
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 5833 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), skinny_new(), and unistim_new().
05834 { 05835 pthread_t t; 05836 05837 if (!c) { 05838 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05839 return AST_PBX_FAILED; 05840 } 05841 05842 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05843 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05844 return AST_PBX_FAILED; 05845 } 05846 05847 if (increase_call_count(c)) 05848 return AST_PBX_CALL_LIMIT; 05849 05850 /* Start a new thread, and get something handling this channel. */ 05851 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05852 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05853 decrease_call_count(); 05854 return AST_PBX_FAILED; 05855 } 05856 05857 return AST_PBX_SUCCESS; 05858 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5890 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05891 { 05892 return totalcalls; 05893 }
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 10919 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().
10920 { 10921 return ast_rwlock_rdlock(&con->lock); 10922 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10901 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_hint_extension(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10902 { 10903 return ast_mutex_lock(&conlock); 10904 }
int ast_register_application2 | ( | const char * | app, | |
int(*)(struct ast_channel *, const char *) | execute, | |||
const char * | synopsis, | |||
const char * | description, | |||
void * | mod | |||
) |
Dynamically register a new dial plan application.
Register an application.
Definition at line 6298 of file pbx.c.
References ast_app::arguments, ast_calloc, ast_free, ast_log(), ast_module_name(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_verb, AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), COLOR_BRCYAN, ast_app::docsrc, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, ast_app::seealso, ast_app::syntax, and term_color().
Referenced by ast_cc_init(), ast_features_init(), and load_pbx().
06299 { 06300 struct ast_app *tmp, *cur = NULL; 06301 char tmps[80]; 06302 int length, res; 06303 #ifdef AST_XML_DOCS 06304 char *tmpxml; 06305 #endif 06306 06307 AST_RWLIST_WRLOCK(&apps); 06308 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 06309 if (!(res = strcasecmp(app, tmp->name))) { 06310 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 06311 AST_RWLIST_UNLOCK(&apps); 06312 return -1; 06313 } else if (res < 0) 06314 break; 06315 } 06316 06317 length = sizeof(*tmp) + strlen(app) + 1; 06318 06319 if (!(tmp = ast_calloc(1, length))) { 06320 AST_RWLIST_UNLOCK(&apps); 06321 return -1; 06322 } 06323 06324 if (ast_string_field_init(tmp, 128)) { 06325 AST_RWLIST_UNLOCK(&apps); 06326 ast_free(tmp); 06327 return -1; 06328 } 06329 06330 strcpy(tmp->name, app); 06331 tmp->execute = execute; 06332 tmp->module = mod; 06333 06334 #ifdef AST_XML_DOCS 06335 /* Try to lookup the docs in our XML documentation database */ 06336 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 06337 /* load synopsis */ 06338 tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module)); 06339 ast_string_field_set(tmp, synopsis, tmpxml); 06340 ast_free(tmpxml); 06341 06342 /* load description */ 06343 tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); 06344 ast_string_field_set(tmp, description, tmpxml); 06345 ast_free(tmpxml); 06346 06347 /* load syntax */ 06348 tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module)); 06349 ast_string_field_set(tmp, syntax, tmpxml); 06350 ast_free(tmpxml); 06351 06352 /* load arguments */ 06353 tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module)); 06354 ast_string_field_set(tmp, arguments, tmpxml); 06355 ast_free(tmpxml); 06356 06357 /* load seealso */ 06358 tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module)); 06359 ast_string_field_set(tmp, seealso, tmpxml); 06360 ast_free(tmpxml); 06361 tmp->docsrc = AST_XML_DOC; 06362 } else { 06363 #endif 06364 ast_string_field_set(tmp, synopsis, synopsis); 06365 ast_string_field_set(tmp, description, description); 06366 #ifdef AST_XML_DOCS 06367 tmp->docsrc = AST_STATIC_DOC; 06368 } 06369 #endif 06370 06371 /* Store in alphabetical order */ 06372 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 06373 if (strcasecmp(tmp->name, cur->name) < 0) { 06374 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 06375 break; 06376 } 06377 } 06378 AST_RWLIST_TRAVERSE_SAFE_END; 06379 if (!cur) 06380 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 06381 06382 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 06383 06384 AST_RWLIST_UNLOCK(&apps); 06385 06386 return 0; 06387 }
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 6393 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().
06394 { 06395 struct ast_switch *tmp; 06396 06397 AST_RWLIST_WRLOCK(&switches); 06398 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06399 if (!strcasecmp(tmp->name, sw->name)) { 06400 AST_RWLIST_UNLOCK(&switches); 06401 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06402 return -1; 06403 } 06404 } 06405 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06406 AST_RWLIST_UNLOCK(&switches); 06407 06408 return 0; 06409 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 5191 of file pbx.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::context_name, ast_hint::exten, ast_hint::exten_name, hints, and OBJ_UNLINK.
Referenced by destroy_exten().
05192 { 05193 /* Cleanup the Notifys if hint is removed */ 05194 struct ast_hint *hint; 05195 05196 if (!e) { 05197 return -1; 05198 } 05199 05200 hint = ao2_find(hints, e, OBJ_UNLINK); 05201 if (!hint) { 05202 return -1; 05203 } 05204 05205 /* 05206 * The extension is being destroyed so we must save some 05207 * information to notify that the extension is deactivated. 05208 */ 05209 ao2_lock(hint); 05210 ast_copy_string(hint->context_name, 05211 ast_get_context_name(ast_get_extension_context(hint->exten)), 05212 sizeof(hint->context_name)); 05213 ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten), 05214 sizeof(hint->exten_name)); 05215 hint->exten = NULL; 05216 ao2_unlock(hint); 05217 05218 ao2_ref(hint, -1); 05219 05220 return 0; 05221 }
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 5379 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), gosub_run(), and loopback_exec().
05380 { 05381 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05382 }
int ast_str_get_hint | ( | struct ast_str ** | hint, | |
ssize_t | hintsize, | |||
struct ast_str ** | name, | |||
ssize_t | namesize, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
Get hint for channel.
If an extension hint exists, return non-zero.
Definition at line 5334 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and ast_str_set().
Referenced by ast_str_retrieve_variable().
05335 { 05336 struct ast_exten *e = ast_hint_extension(c, context, exten); 05337 05338 if (!e) { 05339 return 0; 05340 } 05341 05342 if (hint) { 05343 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05344 } 05345 if (name) { 05346 const char *tmp = ast_get_extension_app_data(e); 05347 if (tmp) { 05348 ast_str_set(name, namesize, "%s", tmp); 05349 } 05350 } 05351 return -1; 05352 }
const char* ast_str_retrieve_variable | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
struct varshead * | headp, | |||
const char * | var | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
var | Variable name to retrieve. |
Definition at line 3399 of file pbx.c.
References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03400 { 03401 const char not_found = '\0'; 03402 char *tmpvar; 03403 const char *ret; 03404 const char *s; /* the result */ 03405 int offset, length; 03406 int i, need_substring; 03407 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03408 char workspace[20]; 03409 03410 if (c) { 03411 ast_channel_lock(c); 03412 places[0] = &c->varshead; 03413 } 03414 /* 03415 * Make a copy of var because parse_variable_name() modifies the string. 03416 * Then if called directly, we might need to run substring() on the result; 03417 * remember this for later in 'need_substring', 'offset' and 'length' 03418 */ 03419 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03420 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03421 03422 /* 03423 * Look first into predefined variables, then into variable lists. 03424 * Variable 's' points to the result, according to the following rules: 03425 * s == ¬_found (set at the beginning) means that we did not find a 03426 * matching variable and need to look into more places. 03427 * If s != ¬_found, s is a valid result string as follows: 03428 * s = NULL if the variable does not have a value; 03429 * you typically do this when looking for an unset predefined variable. 03430 * s = workspace if the result has been assembled there; 03431 * typically done when the result is built e.g. with an snprintf(), 03432 * so we don't need to do an additional copy. 03433 * s != workspace in case we have a string, that needs to be copied 03434 * (the ast_copy_string is done once for all at the end). 03435 * Typically done when the result is already available in some string. 03436 */ 03437 s = ¬_found; /* default value */ 03438 if (c) { /* This group requires a valid channel */ 03439 /* Names with common parts are looked up a piece at a time using strncmp. */ 03440 if (!strncmp(var, "CALL", 4)) { 03441 if (!strncmp(var + 4, "ING", 3)) { 03442 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03443 ast_str_set(str, maxlen, "%d", 03444 ast_party_id_presentation(&c->caller.id)); 03445 s = ast_str_buffer(*str); 03446 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03447 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03448 s = ast_str_buffer(*str); 03449 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03450 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03451 s = ast_str_buffer(*str); 03452 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03453 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03454 s = ast_str_buffer(*str); 03455 } 03456 } 03457 } else if (!strcmp(var, "HINT")) { 03458 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03459 } else if (!strcmp(var, "HINTNAME")) { 03460 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03461 } else if (!strcmp(var, "EXTEN")) { 03462 s = c->exten; 03463 } else if (!strcmp(var, "CONTEXT")) { 03464 s = c->context; 03465 } else if (!strcmp(var, "PRIORITY")) { 03466 ast_str_set(str, maxlen, "%d", c->priority); 03467 s = ast_str_buffer(*str); 03468 } else if (!strcmp(var, "CHANNEL")) { 03469 s = c->name; 03470 } else if (!strcmp(var, "UNIQUEID")) { 03471 s = c->uniqueid; 03472 } else if (!strcmp(var, "HANGUPCAUSE")) { 03473 ast_str_set(str, maxlen, "%d", c->hangupcause); 03474 s = ast_str_buffer(*str); 03475 } 03476 } 03477 if (s == ¬_found) { /* look for more */ 03478 if (!strcmp(var, "EPOCH")) { 03479 ast_str_set(str, maxlen, "%d", (int) time(NULL)); 03480 s = ast_str_buffer(*str); 03481 } else if (!strcmp(var, "SYSTEMNAME")) { 03482 s = ast_config_AST_SYSTEM_NAME; 03483 } else if (!strcmp(var, "ENTITYID")) { 03484 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03485 s = workspace; 03486 } 03487 } 03488 /* if not found, look into chanvars or global vars */ 03489 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03490 struct ast_var_t *variables; 03491 if (!places[i]) 03492 continue; 03493 if (places[i] == &globals) 03494 ast_rwlock_rdlock(&globalslock); 03495 AST_LIST_TRAVERSE(places[i], variables, entries) { 03496 if (!strcasecmp(ast_var_name(variables), var)) { 03497 s = ast_var_value(variables); 03498 break; 03499 } 03500 } 03501 if (places[i] == &globals) 03502 ast_rwlock_unlock(&globalslock); 03503 } 03504 if (s == ¬_found || s == NULL) { 03505 ast_debug(5, "Result of '%s' is NULL\n", var); 03506 ret = NULL; 03507 } else { 03508 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03509 if (s != ast_str_buffer(*str)) { 03510 ast_str_set(str, maxlen, "%s", s); 03511 } 03512 ret = ast_str_buffer(*str); 03513 if (need_substring) { 03514 ret = ast_str_substring(*str, offset, length); 03515 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03516 } 03517 } 03518 03519 if (c) { 03520 ast_channel_unlock(c); 03521 } 03522 return ret; 03523 }
void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
templ | Variable template to expand. |
Definition at line 4422 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().
04423 { 04424 size_t used; 04425 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04426 }
void ast_str_substitute_variables_full | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | c, | |||
struct varshead * | headp, | |||
const char * | templ, | |||
size_t * | used | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
c | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. | |
used | Number of bytes read from the template. |
Definition at line 4243 of file pbx.c.
References ast_channel_unref, ast_debug, ast_dummy_channel_alloc, ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().
04244 { 04245 /* Substitutes variables into buf, based on string templ */ 04246 char *cp4 = NULL; 04247 const char *tmp, *whereweare; 04248 int orig_size = 0; 04249 int offset, offset2, isfunction; 04250 const char *nextvar, *nextexp, *nextthing; 04251 const char *vars, *vare; 04252 char *finalvars; 04253 int pos, brackets, needsub, len; 04254 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04255 04256 ast_str_reset(*buf); 04257 whereweare = tmp = templ; 04258 while (!ast_strlen_zero(whereweare)) { 04259 /* reset our buffer */ 04260 ast_str_reset(substr3); 04261 04262 /* Assume we're copying the whole remaining string */ 04263 pos = strlen(whereweare); 04264 nextvar = NULL; 04265 nextexp = NULL; 04266 nextthing = strchr(whereweare, '$'); 04267 if (nextthing) { 04268 switch (nextthing[1]) { 04269 case '{': 04270 nextvar = nextthing; 04271 pos = nextvar - whereweare; 04272 break; 04273 case '[': 04274 nextexp = nextthing; 04275 pos = nextexp - whereweare; 04276 break; 04277 default: 04278 pos = 1; 04279 } 04280 } 04281 04282 if (pos) { 04283 /* Copy that many bytes */ 04284 ast_str_append_substr(buf, maxlen, whereweare, pos); 04285 04286 templ += pos; 04287 whereweare += pos; 04288 } 04289 04290 if (nextvar) { 04291 /* We have a variable. Find the start and end, and determine 04292 if we are going to have to recursively call ourselves on the 04293 contents */ 04294 vars = vare = nextvar + 2; 04295 brackets = 1; 04296 needsub = 0; 04297 04298 /* Find the end of it */ 04299 while (brackets && *vare) { 04300 if ((vare[0] == '$') && (vare[1] == '{')) { 04301 needsub++; 04302 } else if (vare[0] == '{') { 04303 brackets++; 04304 } else if (vare[0] == '}') { 04305 brackets--; 04306 } else if ((vare[0] == '$') && (vare[1] == '[')) 04307 needsub++; 04308 vare++; 04309 } 04310 if (brackets) 04311 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04312 len = vare - vars - 1; 04313 04314 /* Skip totally over variable string */ 04315 whereweare += (len + 3); 04316 04317 /* Store variable name (and truncate) */ 04318 ast_str_set_substr(&substr1, 0, vars, len); 04319 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04320 04321 /* Substitute if necessary */ 04322 if (needsub) { 04323 size_t used; 04324 if (!substr2) { 04325 substr2 = ast_str_create(16); 04326 } 04327 04328 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04329 finalvars = ast_str_buffer(substr2); 04330 } else { 04331 finalvars = ast_str_buffer(substr1); 04332 } 04333 04334 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04335 if (isfunction) { 04336 /* Evaluate function */ 04337 if (c || !headp) { 04338 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04339 } else { 04340 struct varshead old; 04341 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04342 if (bogus) { 04343 memcpy(&old, &bogus->varshead, sizeof(old)); 04344 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04345 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04346 /* Don't deallocate the varshead that was passed in */ 04347 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04348 ast_channel_unref(bogus); 04349 } else { 04350 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04351 } 04352 } 04353 ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)"); 04354 } else { 04355 /* Retrieve variable value */ 04356 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04357 cp4 = ast_str_buffer(substr3); 04358 } 04359 if (cp4) { 04360 ast_str_substring(substr3, offset, offset2); 04361 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04362 } 04363 } else if (nextexp) { 04364 /* We have an expression. Find the start and end, and determine 04365 if we are going to have to recursively call ourselves on the 04366 contents */ 04367 vars = vare = nextexp + 2; 04368 brackets = 1; 04369 needsub = 0; 04370 04371 /* Find the end of it */ 04372 while (brackets && *vare) { 04373 if ((vare[0] == '$') && (vare[1] == '[')) { 04374 needsub++; 04375 brackets++; 04376 vare++; 04377 } else if (vare[0] == '[') { 04378 brackets++; 04379 } else if (vare[0] == ']') { 04380 brackets--; 04381 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04382 needsub++; 04383 vare++; 04384 } 04385 vare++; 04386 } 04387 if (brackets) 04388 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04389 len = vare - vars - 1; 04390 04391 /* Skip totally over expression */ 04392 whereweare += (len + 3); 04393 04394 /* Store variable name (and truncate) */ 04395 ast_str_set_substr(&substr1, 0, vars, len); 04396 04397 /* Substitute if necessary */ 04398 if (needsub) { 04399 size_t used; 04400 if (!substr2) { 04401 substr2 = ast_str_create(16); 04402 } 04403 04404 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04405 finalvars = ast_str_buffer(substr2); 04406 } else { 04407 finalvars = ast_str_buffer(substr1); 04408 } 04409 04410 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04411 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04412 } 04413 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04414 } 04415 } 04416 *used = ast_str_strlen(*buf) - orig_size; 04417 ast_free(substr1); 04418 ast_free(substr2); 04419 ast_free(substr3); 04420 }
void ast_str_substitute_variables_varshead | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct varshead * | headp, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. |
Definition at line 4428 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().
04429 { 04430 size_t used; 04431 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04432 }
static const char* ast_str_substring | ( | struct ast_str * | value, | |
int | offset, | |||
int | length | |||
) | [static] |
Definition at line 3334 of file pbx.c.
References ast_str_buffer(), ast_str_reset(), ast_str_strlen(), and ast_str_update().
Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().
03335 { 03336 int lr; /* length of the input string after the copy */ 03337 03338 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 03339 03340 /* Quick check if no need to do anything */ 03341 if (offset == 0 && length >= lr) /* take the whole string */ 03342 return ast_str_buffer(value); 03343 03344 if (offset < 0) { /* translate negative offset into positive ones */ 03345 offset = lr + offset; 03346 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03347 offset = 0; 03348 } 03349 03350 /* too large offset result in empty string so we know what to return */ 03351 if (offset >= lr) { 03352 ast_str_reset(value); 03353 return ast_str_buffer(value); 03354 } 03355 03356 if (offset > 0) { 03357 /* Go ahead and chop off the beginning */ 03358 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 03359 lr -= offset; 03360 } 03361 03362 if (length >= 0 && length < lr) { /* truncate if necessary */ 03363 char *tmp = ast_str_buffer(value); 03364 tmp[length] = '\0'; 03365 ast_str_update(value); 03366 } else if (length < 0) { 03367 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 03368 char *tmp = ast_str_buffer(value); 03369 tmp[lr + length] = '\0'; 03370 ast_str_update(value); 03371 } else { 03372 ast_str_reset(value); 03373 } 03374 } else { 03375 /* Nothing to do, but update the buffer length */ 03376 ast_str_update(value); 03377 } 03378 03379 return ast_str_buffer(value); 03380 }
int ast_thread_inhibit_escalations | ( | void | ) |
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.
Definition at line 4026 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by handle_tcptls_connection().
04027 { 04028 int *thread_inhibit_escalations; 04029 04030 thread_inhibit_escalations = ast_threadstorage_get( 04031 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04032 04033 if (thread_inhibit_escalations == NULL) { 04034 ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n"); 04035 return -1; 04036 } 04037 04038 *thread_inhibit_escalations = 1; 04039 return 0; 04040 }
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 10924 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().
10925 { 10926 return ast_rwlock_unlock(&con->lock); 10927 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10906 of file pbx.c.
References ast_mutex_unlock, and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10907 { 10908 return ast_mutex_unlock(&conlock); 10909 }
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 7659 of file pbx.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, ast_app::name, and unreference_cached_app().
Referenced by __unload_module(), cc_shutdown(), features_shutdown(), load_module(), unload_module(), and unload_pbx().
07660 { 07661 struct ast_app *tmp; 07662 07663 AST_RWLIST_WRLOCK(&apps); 07664 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 07665 if (!strcasecmp(app, tmp->name)) { 07666 unreference_cached_app(tmp); 07667 AST_RWLIST_REMOVE_CURRENT(list); 07668 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 07669 ast_string_field_free_memory(tmp); 07670 ast_free(tmp); 07671 break; 07672 } 07673 } 07674 AST_RWLIST_TRAVERSE_SAFE_END; 07675 AST_RWLIST_UNLOCK(&apps); 07676 07677 return tmp ? 0 : -1; 07678 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6411 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06412 { 06413 AST_RWLIST_WRLOCK(&switches); 06414 AST_RWLIST_REMOVE(&switches, sw, list); 06415 AST_RWLIST_UNLOCK(&switches); 06416 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) | [read] |
Definition at line 11038 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), context_used(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) | [read] |
Definition at line 11071 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
11073 { 11074 if (!ip) 11075 return con ? con->ignorepats : NULL; 11076 else 11077 return ip->next; 11078 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 11062 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), context_used(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) | [read] |
Definition at line 11047 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11049 { 11050 if (!sw) 11051 return con ? AST_LIST_FIRST(&con->alts) : NULL; 11052 else 11053 return AST_LIST_NEXT(sw, list); 11054 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 11033 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 11056 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
11058 { 11059 return priority ? priority->peer : exten; 11060 }
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 10914 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().
10915 { 10916 return ast_rwlock_wrlock(&con->lock); 10917 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10896 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
10897 { 10898 return ast_mutex_lock(&conlock); 10899 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 9239 of file pbx.c.
References ast_channel::_state, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_free, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_remaining_ms(), AST_STATE_UP, ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, ast_frame::subclass, and async_stat::timeout.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
09240 { 09241 struct async_stat *as = data; 09242 struct ast_channel *chan = as->chan; 09243 int timeout = as->timeout; 09244 int res; 09245 struct ast_frame *f; 09246 struct ast_app *app; 09247 struct timeval start = ast_tvnow(); 09248 int ms; 09249 09250 while ((ms = ast_remaining_ms(start, timeout)) && 09251 chan->_state != AST_STATE_UP) { 09252 res = ast_waitfor(chan, ms); 09253 if (res < 1) 09254 break; 09255 09256 f = ast_read(chan); 09257 if (!f) 09258 break; 09259 if (f->frametype == AST_FRAME_CONTROL) { 09260 if ((f->subclass.integer == AST_CONTROL_BUSY) || 09261 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 09262 ast_frfree(f); 09263 break; 09264 } 09265 } 09266 ast_frfree(f); 09267 } 09268 if (chan->_state == AST_STATE_UP) { 09269 if (!ast_strlen_zero(as->app)) { 09270 app = pbx_findapp(as->app); 09271 if (app) { 09272 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 09273 pbx_exec(chan, app, as->appdata); 09274 } else 09275 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 09276 } else { 09277 if (!ast_strlen_zero(as->context)) 09278 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 09279 if (!ast_strlen_zero(as->exten)) 09280 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 09281 if (as->priority > 0) 09282 chan->priority = as->priority; 09283 /* Run the PBX */ 09284 if (ast_pbx_run(chan)) { 09285 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 09286 } else { 09287 /* PBX will have taken care of this */ 09288 chan = NULL; 09289 } 09290 } 09291 } 09292 ast_free(as); 09293 if (chan) 09294 ast_hangup(chan); 09295 return NULL; 09296 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1653 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().
01654 { 01655 char extenstr[40]; 01656 struct ast_str *my_prefix = ast_str_alloca(1024); 01657 01658 extenstr[0] = '\0'; 01659 01660 if (node->exten) { 01661 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01662 } 01663 01664 if (strlen(node->x) > 1) { 01665 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01666 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01667 node->exten ? node->exten->exten : "", extenstr); 01668 } else { 01669 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01670 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01671 node->exten ? node->exten->exten : "", extenstr); 01672 } 01673 01674 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01675 01676 if (node->next_char) 01677 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01678 01679 if (node->alt_char) 01680 cli_match_char_tree(node->alt_char, prefix, fd); 01681 }
static int collect_digits | ( | struct ast_channel * | c, | |
int | waittime, | |||
char * | buf, | |||
int | buflen, | |||
int | pos | |||
) | [static] |
collect digits from the channel into the buffer.
c,buf,buflen,pos | ||
waittime | is in milliseconds |
0 | on timeout or done. | |
-1 | on error. |
Definition at line 5400 of file pbx.c.
References ast_channel::_softhangup, ast_channel_clear_softhangup(), ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::caller, ast_channel::context, ast_pbx::dtimeoutms, ast_party_caller::id, ast_party_id::number, ast_channel::pbx, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by __ast_pbx_run().
05401 { 05402 int digit; 05403 05404 buf[pos] = '\0'; /* make sure it is properly terminated */ 05405 while (ast_matchmore_extension(c, c->context, buf, 1, 05406 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05407 /* As long as we're willing to wait, and as long as it's not defined, 05408 keep reading digits until we can't possibly get a right answer anymore. */ 05409 digit = ast_waitfordigit(c, waittime); 05410 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05411 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05412 } else { 05413 if (!digit) /* No entry */ 05414 break; 05415 if (digit < 0) /* Error, maybe a hangup */ 05416 return -1; 05417 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 05418 buf[pos++] = digit; 05419 buf[pos] = '\0'; 05420 } 05421 waittime = c->pbx->dtimeoutms; 05422 } 05423 } 05424 return 0; 05425 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 1083 of file pbx.c.
Referenced by get_pattern_node().
static char* complete_core_show_hint | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
autocomplete for CLI command 'core show hint'
Definition at line 6603 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_get_extension_name(), ast_strdup, ast_hint::exten, and hints.
Referenced by handle_show_hint().
06604 { 06605 struct ast_hint *hint; 06606 char *ret = NULL; 06607 int which = 0; 06608 int wordlen; 06609 struct ao2_iterator i; 06610 06611 if (pos != 3) 06612 return NULL; 06613 06614 wordlen = strlen(word); 06615 06616 /* walk through all hints */ 06617 i = ao2_iterator_init(hints, 0); 06618 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06619 ao2_lock(hint); 06620 if (!hint->exten) { 06621 /* The extension has already been destroyed */ 06622 ao2_unlock(hint); 06623 continue; 06624 } 06625 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 06626 ret = ast_strdup(ast_get_extension_name(hint->exten)); 06627 ao2_unlock(hint); 06628 ao2_ref(hint, -1); 06629 break; 06630 } 06631 ao2_unlock(hint); 06632 } 06633 ao2_iterator_destroy(&i); 06634 06635 return ret; 06636 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 6819 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().
06821 { 06822 struct ast_context *c = NULL; 06823 char *ret = NULL; 06824 int which = 0; 06825 int wordlen; 06826 06827 /* we are do completion of [exten@]context on second position only */ 06828 if (pos != 2) 06829 return NULL; 06830 06831 ast_rdlock_contexts(); 06832 06833 wordlen = strlen(word); 06834 06835 /* walk through all contexts and return the n-th match */ 06836 while ( (c = ast_walk_contexts(c)) ) { 06837 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06838 ret = ast_strdup(ast_get_context_name(c)); 06839 break; 06840 } 06841 } 06842 06843 ast_unlock_contexts(); 06844 06845 return ret; 06846 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7800 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().
07801 { 07802 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 07803 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 07804 struct ast_hashtab_iter *exten_iter; 07805 struct ast_hashtab_iter *prio_iter; 07806 int insert_count = 0; 07807 int first = 1; 07808 07809 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 07810 the current registrar, and copy them to the new context. If the new context does not 07811 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 07812 only create the empty matching context if the old one meets the criteria */ 07813 07814 if (context->root_table) { 07815 exten_iter = ast_hashtab_start_traversal(context->root_table); 07816 while ((exten_item=ast_hashtab_next(exten_iter))) { 07817 if (new) { 07818 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 07819 } else { 07820 new_exten_item = NULL; 07821 } 07822 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07823 while ((prio_item=ast_hashtab_next(prio_iter))) { 07824 int res1; 07825 char *dupdstr; 07826 07827 if (new_exten_item) { 07828 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 07829 } else { 07830 new_prio_item = NULL; 07831 } 07832 if (strcmp(prio_item->registrar,registrar) == 0) { 07833 continue; 07834 } 07835 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 07836 if (!new) { 07837 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 */ 07838 } 07839 07840 /* copy in the includes, switches, and ignorepats */ 07841 if (first) { /* but, only need to do this once */ 07842 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07843 first = 0; 07844 } 07845 07846 if (!new) { 07847 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07848 ast_hashtab_end_traversal(prio_iter); 07849 ast_hashtab_end_traversal(exten_iter); 07850 return; /* no sense continuing. */ 07851 } 07852 /* we will not replace existing entries in the new context with stuff from the old context. 07853 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07854 07855 dupdstr = ast_strdup(prio_item->data); 07856 07857 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07858 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07859 if (!res1 && new_exten_item && new_prio_item){ 07860 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07861 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07862 } else { 07863 /* 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, 07864 and no double frees take place, either! */ 07865 insert_count++; 07866 } 07867 } 07868 ast_hashtab_end_traversal(prio_iter); 07869 } 07870 ast_hashtab_end_traversal(exten_iter); 07871 } else if (new) { 07872 /* If the context existed but had no extensions, we still want to merge 07873 * the includes, switches and ignore patterns. 07874 */ 07875 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07876 } 07877 07878 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07879 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07880 /* we could have given it the registrar of the other module who incremented the refcount, 07881 but that's not available, so we give it the registrar we know about */ 07882 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07883 07884 /* copy in the includes, switches, and ignorepats */ 07885 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07886 } 07887 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7767 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().
07768 { 07769 struct ast_include *i; 07770 struct ast_ignorepat *ip; 07771 struct ast_sw *sw; 07772 07773 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); 07774 /* copy in the includes, switches, and ignorepats */ 07775 /* walk through includes */ 07776 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 07777 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 07778 continue; /* not mine */ 07779 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 07780 } 07781 07782 /* walk through switches */ 07783 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 07784 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 07785 continue; /* not mine */ 07786 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)); 07787 } 07788 07789 /* walk thru ignorepats ... */ 07790 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 07791 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 07792 continue; /* not mine */ 07793 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 07794 } 07795 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2275 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().
02276 { 02277 struct ast_hashtab_iter *t1; 02278 struct ast_exten *e1; 02279 #ifdef NEED_DEBUG 02280 int biggest_bucket, resizes, numobjs, numbucks; 02281 02282 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02283 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02284 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02285 numobjs, numbucks, biggest_bucket, resizes); 02286 #endif 02287 t1 = ast_hashtab_start_traversal(con->root_table); 02288 while ((e1 = ast_hashtab_next(t1))) { 02289 if (e1->exten) { 02290 add_exten_to_pattern_tree(con, e1, 0); 02291 } else { 02292 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02293 } 02294 } 02295 ast_hashtab_end_traversal(t1); 02296 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 5791 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().
05792 { 05793 ast_mutex_lock(&maxcalllock); 05794 if (countcalls > 0) 05795 countcalls--; 05796 ast_mutex_unlock(&maxcalllock); 05797 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 5799 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().
05800 { 05801 if (e->priority == PRIORITY_HINT) 05802 ast_remove_hint(e); 05803 05804 if (e->peer_table) 05805 ast_hashtab_destroy(e->peer_table,0); 05806 if (e->peer_label_table) 05807 ast_hashtab_destroy(e->peer_label_table, 0); 05808 if (e->datad) 05809 e->datad(e->data); 05810 ast_free(e); 05811 }
static void destroy_hint | ( | void * | obj | ) | [static] |
Definition at line 5161 of file pbx.c.
References ao2_callback, ao2_ref, AST_EXTENSION_DEACTIVATED, ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_state_cb::change_cb, ast_hint::context_name, ast_state_cb::data, ast_hint::exten, ast_hint::exten_name, and OBJ_UNLINK.
Referenced by ast_add_hint().
05162 { 05163 struct ast_hint *hint = obj; 05164 05165 if (hint->callbacks) { 05166 struct ast_state_cb *state_cb; 05167 const char *context_name; 05168 const char *exten_name; 05169 05170 if (hint->exten) { 05171 context_name = ast_get_context_name(ast_get_extension_context(hint->exten)); 05172 exten_name = ast_get_extension_name(hint->exten); 05173 hint->exten = NULL; 05174 } else { 05175 /* The extension has already been destroyed */ 05176 context_name = hint->context_name; 05177 exten_name = hint->exten_name; 05178 } 05179 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 05180 /* Notify with -1 and remove all callbacks */ 05181 /* NOTE: The casts will not be needed for v1.10 and later */ 05182 state_cb->change_cb((char *) context_name, (char *) exten_name, 05183 AST_EXTENSION_DEACTIVATED, state_cb->data); 05184 ao2_ref(state_cb, -1); 05185 } 05186 ao2_ref(hint->callbacks, -1); 05187 } 05188 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2298 of file pbx.c.
References match_char::alt_char, ast_free, match_char::exten, and match_char::next_char.
Referenced by __ast_internal_context_destroy().
02299 { 02300 /* destroy all the alternates */ 02301 if (pattern_tree->alt_char) { 02302 destroy_pattern_tree(pattern_tree->alt_char); 02303 pattern_tree->alt_char = 0; 02304 } 02305 /* destroy all the nexts */ 02306 if (pattern_tree->next_char) { 02307 destroy_pattern_tree(pattern_tree->next_char); 02308 pattern_tree->next_char = 0; 02309 } 02310 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02311 ast_free(pattern_tree); 02312 }
static void destroy_state_cb | ( | void * | doomed | ) | [static] |
Definition at line 4992 of file pbx.c.
References ast_state_cb::data, ast_state_cb::destroy_cb, and ast_state_cb::id.
Referenced by ast_extension_state_add_destroy().
04993 { 04994 struct ast_state_cb *state_cb = doomed; 04995 04996 if (state_cb->destroy_cb) { 04997 state_cb->destroy_cb(state_cb->id, state_cb->data); 04998 } 04999 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 10764 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().
10765 { 10766 const char *device; 10767 struct statechange *sc; 10768 10769 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 10770 if (ast_strlen_zero(device)) { 10771 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 10772 return; 10773 } 10774 10775 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 10776 return; 10777 strcpy(sc->dev, device); 10778 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 10779 ast_free(sc); 10780 } 10781 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3525 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03526 { 03527 struct pbx_exception *exception = data; 03528 ast_string_field_free_memory(exception); 03529 ast_free(exception); 03530 }
static int ext_cmp | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2645 of file pbx.c.
References ext_cmp_exten(), and ext_cmp_pattern().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02646 { 02647 /* Make sure non-pattern extens come first. */ 02648 if (left[0] != '_') { 02649 if (right[0] == '_') { 02650 return -1; 02651 } 02652 /* Compare two non-pattern extens. */ 02653 return ext_cmp_exten(left, right); 02654 } 02655 if (right[0] != '_') { 02656 return 1; 02657 } 02658 02659 /* 02660 * OK, we need full pattern sorting routine. 02661 * 02662 * Skip past the underscores 02663 */ 02664 return ext_cmp_pattern(left + 1, right + 1); 02665 }
static int ext_cmp_exten | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2395 of file pbx.c.
Referenced by _extension_match_core(), and ext_cmp().
02396 { 02397 int cmp; 02398 02399 for (;;) { 02400 /* Ignore '-' chars as eye candy fluff. */ 02401 while (*left == '-') { 02402 ++left; 02403 } 02404 while (*right == '-') { 02405 ++right; 02406 } 02407 02408 cmp = *left - *right; 02409 if (cmp) { 02410 break; 02411 } 02412 if (!*left) { 02413 /* 02414 * Get here only if both strings ended at the same time. cmp 02415 * would be non-zero if only one string ended. 02416 */ 02417 break; 02418 } 02419 ++left; 02420 ++right; 02421 } 02422 return cmp; 02423 }
static int ext_cmp_exten_partial | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2352 of file pbx.c.
Referenced by _extension_match_core().
02353 { 02354 int cmp; 02355 02356 for (;;) { 02357 /* Ignore '-' chars as eye candy fluff. */ 02358 while (*left == '-') { 02359 ++left; 02360 } 02361 while (*right == '-') { 02362 ++right; 02363 } 02364 02365 if (!*right) { 02366 /* 02367 * Right ended first for partial match or both ended at the same 02368 * time for a match. 02369 */ 02370 cmp = 0; 02371 break; 02372 } 02373 02374 cmp = *left - *right; 02375 if (cmp) { 02376 break; 02377 } 02378 ++left; 02379 ++right; 02380 } 02381 return cmp; 02382 }
static int ext_cmp_exten_strlen | ( | const char * | str | ) | [static] |
static int ext_cmp_pattern | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2597 of file pbx.c.
References ARRAY_LEN, and ext_cmp_pattern_pos().
Referenced by _extension_match_core(), and ext_cmp().
02598 { 02599 int cmp; 02600 int left_pos; 02601 int right_pos; 02602 02603 for (;;) { 02604 unsigned char left_bitwise[32] = { 0, }; 02605 unsigned char right_bitwise[32] = { 0, }; 02606 02607 left_pos = ext_cmp_pattern_pos(&left, left_bitwise); 02608 right_pos = ext_cmp_pattern_pos(&right, right_bitwise); 02609 cmp = left_pos - right_pos; 02610 if (!cmp) { 02611 /* 02612 * Are the character sets different, even though they score the same? 02613 * 02614 * Note: Must swap left and right to get the sense of the 02615 * comparison correct. Otherwise, we would need to multiply by 02616 * -1 instead. 02617 */ 02618 cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise)); 02619 } 02620 if (cmp) { 02621 break; 02622 } 02623 if (!left) { 02624 /* 02625 * Get here only if both patterns ended at the same time. cmp 02626 * would be non-zero if only one pattern ended. 02627 */ 02628 break; 02629 } 02630 } 02631 return cmp; 02632 }
static int ext_cmp_pattern_pos | ( | const char ** | p, | |
unsigned char * | bitwise | |||
) | [static] |
helper functions to sort extension patterns in the desired way, so that more specific patterns appear first.
The function compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, bits 8-15 are the number of characters in the set, and bits 16-20 are for special cases. This way more specific patterns (smaller character sets) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x001xx one character, character set starting with xx 0x0yyxx yy characters, character set starting with xx 0x18000 '.' (one or more of anything) 0x28000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is ignored. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.
Definition at line 2482 of file pbx.c.
References ast_log(), BITS_PER, and LOG_WARNING.
Referenced by ext_cmp_pattern().
02483 { 02484 #define BITS_PER 8 /* Number of bits per unit (byte). */ 02485 unsigned char c; 02486 unsigned char cmin; 02487 int count; 02488 const char *end; 02489 02490 do { 02491 /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */ 02492 do { 02493 c = *(*p)++; 02494 } while (c == '-'); 02495 02496 /* always return unless we have a set of chars */ 02497 switch (c) { 02498 default: 02499 /* ordinary character */ 02500 bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER)); 02501 return 0x0100 | c; 02502 02503 case 'n': 02504 case 'N': 02505 /* 2..9 */ 02506 bitwise[6] = 0x3f; 02507 bitwise[7] = 0xc0; 02508 return 0x0800 | '2'; 02509 02510 case 'x': 02511 case 'X': 02512 /* 0..9 */ 02513 bitwise[6] = 0xff; 02514 bitwise[7] = 0xc0; 02515 return 0x0A00 | '0'; 02516 02517 case 'z': 02518 case 'Z': 02519 /* 1..9 */ 02520 bitwise[6] = 0x7f; 02521 bitwise[7] = 0xc0; 02522 return 0x0900 | '1'; 02523 02524 case '.': 02525 /* wildcard */ 02526 return 0x18000; 02527 02528 case '!': 02529 /* earlymatch */ 02530 return 0x28000; /* less specific than '.' */ 02531 02532 case '\0': 02533 /* empty string */ 02534 *p = NULL; 02535 return 0x30000; 02536 02537 case '[': 02538 /* char set */ 02539 break; 02540 } 02541 /* locate end of set */ 02542 end = strchr(*p, ']'); 02543 02544 if (!end) { 02545 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02546 return 0x40000; /* XXX make this entry go last... */ 02547 } 02548 02549 count = 0; 02550 cmin = 0xFF; 02551 for (; *p < end; ++*p) { 02552 unsigned char c1; /* first char in range */ 02553 unsigned char c2; /* last char in range */ 02554 02555 c1 = (*p)[0]; 02556 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02557 c2 = (*p)[2]; 02558 *p += 2; /* skip a total of 3 chars */ 02559 } else { /* individual character */ 02560 c2 = c1; 02561 } 02562 if (c1 < cmin) { 02563 cmin = c1; 02564 } 02565 for (; c1 <= c2; ++c1) { 02566 unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER)); 02567 02568 /* 02569 * Note: If two character sets score the same, the one with the 02570 * lowest ASCII values will compare as coming first. Must fill 02571 * in most significant bits for lower ASCII values to accomplish 02572 * the desired sort order. 02573 */ 02574 if (!(bitwise[c1 / BITS_PER] & mask)) { 02575 /* Add the character to the set. */ 02576 bitwise[c1 / BITS_PER] |= mask; 02577 count += 0x100; 02578 } 02579 } 02580 } 02581 ++*p; 02582 } while (!count);/* While the char set was empty. */ 02583 return count | cmin; 02584 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 8781 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
08782 { 08783 int count = 0; 08784 int insquares = 0; 08785 08786 while (*src && (count < len - 1)) { 08787 if (*src == '[') { 08788 insquares = 1; 08789 } else if (*src == ']') { 08790 insquares = 0; 08791 } else if (*src == ' ' && !insquares) { 08792 src++; 08793 continue; 08794 } 08795 *dst = *src; 08796 dst++; 08797 src++; 08798 count++; 08799 } 08800 *dst = '\0'; 08801 08802 return count; 08803 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2884 of file pbx.c.
References _extension_match_core(), ast_add_profile(), ast_mark(), and ast_strlen_zero().
Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().
02885 { 02886 int i; 02887 static int prof_id = -2; /* marker for 'unallocated' id */ 02888 if (prof_id == -2) { 02889 prof_id = ast_add_profile("ext_match", 0); 02890 } 02891 ast_mark(prof_id, 1); 02892 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode); 02893 ast_mark(prof_id, 0); 02894 return i; 02895 }
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 5925 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05926 { 05927 struct fake_context item; 05928 05929 ast_copy_string(item.name, context, sizeof(item.name)); 05930 05931 return ast_hashtab_lookup(contexts_table, &item); 05932 }
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 5939 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, and fake_context::name.
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), and ast_context_unlockmacro().
05940 { 05941 struct ast_context *c; 05942 struct fake_context item; 05943 05944 ast_copy_string(item.name, context, sizeof(item.name)); 05945 05946 ast_rdlock_contexts(); 05947 c = ast_hashtab_lookup(contexts_table, &item); 05948 if (!c) { 05949 ast_unlock_contexts(); 05950 } 05951 05952 return c; 05953 }
static int find_hint_by_cb_id | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Remove a watcher from the callback list.
Definition at line 5096 of file pbx.c.
References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.
Referenced by ast_extension_state_del().
static char* func_args | ( | char * | function | ) | [static] |
return a pointer to the arguments of the function, and terminates the function name with '\0'
Definition at line 3995 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03996 { 03997 char *args = strchr(function, '('); 03998 03999 if (!args) { 04000 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 04001 } else { 04002 char *p; 04003 *args++ = '\0'; 04004 if ((p = strrchr(args, ')'))) { 04005 *p = '\0'; 04006 } else { 04007 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 04008 } 04009 } 04010 return args; 04011 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1683 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.
01684 { 01685 /* find the exten at the end of the rope */ 01686 struct match_char *node2 = node; 01687 01688 for (node2 = node; node2; node2 = node2->next_char) { 01689 if (node2->exten) { 01690 #ifdef NEED_DEBUG_HERE 01691 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01692 #endif 01693 return node2->exten; 01694 } 01695 } 01696 #ifdef NEED_DEBUG_HERE 01697 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01698 #endif 01699 return 0; 01700 }
static const char* get_pattern_node | ( | struct pattern_node * | node, | |
const char * | src, | |||
int | pattern, | |||
const char * | extenbuf | |||
) | [static] |
Definition at line 2032 of file pbx.c.
References ast_log(), pattern_node::buf, compare_char(), first, INC_DST_OVERFLOW_CHECK, last, LOG_ERROR, LOG_WARNING, and pattern_node::specif.
Referenced by add_exten_to_pattern_tree().
02033 { 02034 #define INC_DST_OVERFLOW_CHECK \ 02035 do { \ 02036 if (dst - node->buf < sizeof(node->buf) - 1) { \ 02037 ++dst; \ 02038 } else { \ 02039 overflow = 1; \ 02040 } \ 02041 } while (0) 02042 02043 node->specif = 0; 02044 node->buf[0] = '\0'; 02045 while (*src) { 02046 if (*src == '[' && pattern) { 02047 char *dst = node->buf; 02048 const char *src_next; 02049 int length; 02050 int overflow = 0; 02051 02052 /* get past the '[' */ 02053 ++src; 02054 for (;;) { 02055 if (*src == '\\') { 02056 /* Escaped character. */ 02057 ++src; 02058 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') { 02059 *dst = *src++; 02060 INC_DST_OVERFLOW_CHECK; 02061 } 02062 } else if (*src == '-') { 02063 unsigned char first; 02064 unsigned char last; 02065 02066 src_next = src; 02067 first = *(src_next - 1); 02068 last = *++src_next; 02069 02070 if (last == '\\') { 02071 /* Escaped character. */ 02072 last = *++src_next; 02073 } 02074 02075 /* Possible char range. */ 02076 if (node->buf[0] && last) { 02077 /* Expand the char range. */ 02078 while (++first <= last) { 02079 *dst = first; 02080 INC_DST_OVERFLOW_CHECK; 02081 } 02082 src = src_next + 1; 02083 } else { 02084 /* 02085 * There was no left or right char for the range. 02086 * It is just a '-'. 02087 */ 02088 *dst = *src++; 02089 INC_DST_OVERFLOW_CHECK; 02090 } 02091 } else if (*src == '\0') { 02092 ast_log(LOG_WARNING, 02093 "A matching ']' was not found for '[' in exten pattern '%s'\n", 02094 extenbuf); 02095 break; 02096 } else if (*src == ']') { 02097 ++src; 02098 break; 02099 } else { 02100 *dst = *src++; 02101 INC_DST_OVERFLOW_CHECK; 02102 } 02103 } 02104 /* null terminate the exploded range */ 02105 *dst = '\0'; 02106 02107 if (overflow) { 02108 ast_log(LOG_ERROR, 02109 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n", 02110 extenbuf); 02111 node->buf[0] = '\0'; 02112 continue; 02113 } 02114 02115 /* Sort the characters in character set. */ 02116 length = strlen(node->buf); 02117 if (!length) { 02118 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n", 02119 extenbuf); 02120 node->buf[0] = '\0'; 02121 continue; 02122 } 02123 qsort(node->buf, length, 1, compare_char); 02124 02125 /* Remove duplicate characters from character set. */ 02126 dst = node->buf; 02127 src_next = node->buf; 02128 while (*src_next++) { 02129 if (*dst != *src_next) { 02130 *++dst = *src_next; 02131 } 02132 } 02133 02134 length = strlen(node->buf); 02135 length <<= 8; 02136 node->specif = length | (unsigned char) node->buf[0]; 02137 break; 02138 } else if (*src == '-') { 02139 /* Skip dashes in all extensions. */ 02140 ++src; 02141 } else { 02142 if (*src == '\\') { 02143 /* 02144 * XXX The escape character here does not remove any special 02145 * meaning to characters except the '[', '\\', and '-' 02146 * characters since they are special only in this function. 02147 */ 02148 node->buf[0] = *++src; 02149 if (!node->buf[0]) { 02150 break; 02151 } 02152 } else { 02153 node->buf[0] = *src; 02154 if (pattern) { 02155 /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02156 if (node->buf[0] == 'n') { 02157 node->buf[0] = 'N'; 02158 } else if (node->buf[0] == 'x') { 02159 node->buf[0] = 'X'; 02160 } else if (node->buf[0] == 'z') { 02161 node->buf[0] = 'Z'; 02162 } 02163 } 02164 } 02165 node->buf[1] = '\0'; 02166 node->specif = 1; 02167 ++src; 02168 break; 02169 } 02170 } 02171 return src; 02172 02173 #undef INC_DST_OVERFLOW_CHECK 02174 }
static unsigned get_range | ( | char * | src, | |
int | max, | |||
const char *const | names[], | |||
const char * | msg | |||
) | [static] |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
Definition at line 8136 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and lookup_name().
Referenced by ast_build_timing().
08137 { 08138 int start, end; /* start and ending position */ 08139 unsigned int mask = 0; 08140 char *part; 08141 08142 /* Check for whole range */ 08143 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 08144 return (1 << max) - 1; 08145 } 08146 08147 while ((part = strsep(&src, "&"))) { 08148 /* Get start and ending position */ 08149 char *endpart = strchr(part, '-'); 08150 if (endpart) { 08151 *endpart++ = '\0'; 08152 } 08153 /* Find the start */ 08154 if ((start = lookup_name(part, names, max)) < 0) { 08155 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 08156 continue; 08157 } 08158 if (endpart) { /* find end of range */ 08159 if ((end = lookup_name(endpart, names, max)) < 0) { 08160 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 08161 continue; 08162 } 08163 } else { 08164 end = start; 08165 } 08166 /* Fill the mask. Remember that ranges are cyclic */ 08167 mask |= (1 << end); /* initialize with last element */ 08168 while (start != end) { 08169 mask |= (1 << start); 08170 if (++start >= max) { 08171 start = 0; 08172 } 08173 } 08174 } 08175 return mask; 08176 }
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 8179 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
08180 { 08181 char *endpart, *part; 08182 int x; 08183 int st_h, st_m; 08184 int endh, endm; 08185 int minute_start, minute_end; 08186 08187 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 08188 memset(i->minmask, 0, sizeof(i->minmask)); 08189 08190 /* 1-minute per bit */ 08191 /* Star is all times */ 08192 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 08193 /* 48, because each hour takes 2 integers; 30 bits each */ 08194 for (x = 0; x < 48; x++) { 08195 i->minmask[x] = 0x3fffffff; /* 30 bits */ 08196 } 08197 return; 08198 } 08199 /* Otherwise expect a range */ 08200 while ((part = strsep(×, "&"))) { 08201 if (!(endpart = strchr(part, '-'))) { 08202 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 08203 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 08204 continue; 08205 } 08206 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 08207 continue; 08208 } 08209 *endpart++ = '\0'; 08210 /* why skip non digits? Mostly to skip spaces */ 08211 while (*endpart && !isdigit(*endpart)) { 08212 endpart++; 08213 } 08214 if (!*endpart) { 08215 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 08216 continue; 08217 } 08218 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 08219 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 08220 continue; 08221 } 08222 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 08223 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 08224 continue; 08225 } 08226 minute_start = st_h * 60 + st_m; 08227 minute_end = endh * 60 + endm; 08228 /* Go through the time and enable each appropriate bit */ 08229 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 08230 i->minmask[x / 30] |= (1 << (x % 30)); 08231 } 08232 /* Do the last one */ 08233 i->minmask[x / 30] |= (1 << (x % 30)); 08234 } 08235 /* All done */ 08236 return; 08237 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 7150 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), dialplan_counters::total_context, ast_cli_entry::usage, and ast_cli_args::word.
07151 { 07152 char *exten = NULL, *context = NULL; 07153 /* Variables used for different counters */ 07154 struct dialplan_counters counters; 07155 const char *incstack[AST_PBX_MAX_STACK]; 07156 07157 switch (cmd) { 07158 case CLI_INIT: 07159 e->command = "dialplan debug"; 07160 e->usage = 07161 "Usage: dialplan debug [context]\n" 07162 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 07163 return NULL; 07164 case CLI_GENERATE: 07165 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 07166 } 07167 07168 memset(&counters, 0, sizeof(counters)); 07169 07170 if (a->argc != 2 && a->argc != 3) 07171 return CLI_SHOWUSAGE; 07172 07173 /* we obtain [exten@]context? if yes, split them ... */ 07174 /* note: we ignore the exten totally here .... */ 07175 if (a->argc == 3) { 07176 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 07177 context = ast_strdupa(a->argv[2]); 07178 exten = strsep(&context, "@"); 07179 /* change empty strings to NULL */ 07180 if (ast_strlen_zero(exten)) 07181 exten = NULL; 07182 } else { /* no '@' char, only context given */ 07183 context = ast_strdupa(a->argv[2]); 07184 } 07185 if (ast_strlen_zero(context)) 07186 context = NULL; 07187 } 07188 /* else Show complete dial plan, context and exten are NULL */ 07189 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 07190 07191 /* check for input failure and throw some error messages */ 07192 if (context && !counters.context_existence) { 07193 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 07194 return CLI_FAILURE; 07195 } 07196 07197 07198 ast_cli(a->fd,"-= %d %s. =-\n", 07199 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 07200 07201 /* everything ok */ 07202 return CLI_SUCCESS; 07203 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7523 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_setvar_helper(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
07524 { 07525 struct ast_channel *chan; 07526 const char *chan_name, *var_name, *var_value; 07527 07528 switch (cmd) { 07529 case CLI_INIT: 07530 e->command = "dialplan set chanvar"; 07531 e->usage = 07532 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 07533 " Set channel variable <varname> to <value>\n"; 07534 return NULL; 07535 case CLI_GENERATE: 07536 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07537 } 07538 07539 if (a->argc != e->args + 3) 07540 return CLI_SHOWUSAGE; 07541 07542 chan_name = a->argv[e->args]; 07543 var_name = a->argv[e->args + 1]; 07544 var_value = a->argv[e->args + 2]; 07545 07546 if (!(chan = ast_channel_get_by_name(chan_name))) { 07547 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 07548 return CLI_FAILURE; 07549 } 07550 07551 pbx_builtin_setvar_helper(chan, var_name, var_value); 07552 07553 chan = ast_channel_unref(chan); 07554 07555 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 07556 07557 return CLI_SUCCESS; 07558 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7560 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.
07561 { 07562 int oldval = 0; 07563 07564 switch (cmd) { 07565 case CLI_INIT: 07566 e->command = "dialplan set extenpatternmatchnew true"; 07567 e->usage = 07568 "Usage: dialplan set extenpatternmatchnew true|false\n" 07569 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07570 return NULL; 07571 case CLI_GENERATE: 07572 return NULL; 07573 } 07574 07575 if (a->argc != 4) 07576 return CLI_SHOWUSAGE; 07577 07578 oldval = pbx_set_extenpatternmatchnew(1); 07579 07580 if (oldval) 07581 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07582 else 07583 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07584 07585 return CLI_SUCCESS; 07586 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7501 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.
07502 { 07503 switch (cmd) { 07504 case CLI_INIT: 07505 e->command = "dialplan set global"; 07506 e->usage = 07507 "Usage: dialplan set global <name> <value>\n" 07508 " Set global dialplan variable <name> to <value>\n"; 07509 return NULL; 07510 case CLI_GENERATE: 07511 return NULL; 07512 } 07513 07514 if (a->argc != e->args + 2) 07515 return CLI_SHOWUSAGE; 07516 07517 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 07518 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 07519 07520 return CLI_SUCCESS; 07521 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6497 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_complete_applications(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.
06498 { 06499 struct ast_app *aa; 06500 int app, no_registered_app = 1; 06501 06502 switch (cmd) { 06503 case CLI_INIT: 06504 e->command = "core show application"; 06505 e->usage = 06506 "Usage: core show application <application> [<application> [<application> [...]]]\n" 06507 " Describes a particular application.\n"; 06508 return NULL; 06509 case CLI_GENERATE: 06510 /* 06511 * There is a possibility to show informations about more than one 06512 * application at one time. You can type 'show application Dial Echo' and 06513 * you will see informations about these two applications ... 06514 */ 06515 return ast_complete_applications(a->line, a->word, a->n); 06516 } 06517 06518 if (a->argc < 4) { 06519 return CLI_SHOWUSAGE; 06520 } 06521 06522 AST_RWLIST_RDLOCK(&apps); 06523 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06524 /* Check for each app that was supplied as an argument */ 06525 for (app = 3; app < a->argc; app++) { 06526 if (strcasecmp(aa->name, a->argv[app])) { 06527 continue; 06528 } 06529 06530 /* We found it! */ 06531 no_registered_app = 0; 06532 06533 print_app_docs(aa, a->fd); 06534 } 06535 } 06536 AST_RWLIST_UNLOCK(&apps); 06537 06538 /* we found at least one app? no? */ 06539 if (no_registered_app) { 06540 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 06541 return CLI_FAILURE; 06542 } 06543 06544 return CLI_SUCCESS; 06545 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6733 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.
06734 { 06735 struct ast_app *aa; 06736 int like = 0, describing = 0; 06737 int total_match = 0; /* Number of matches in like clause */ 06738 int total_apps = 0; /* Number of apps registered */ 06739 static const char * const choices[] = { "like", "describing", NULL }; 06740 06741 switch (cmd) { 06742 case CLI_INIT: 06743 e->command = "core show applications [like|describing]"; 06744 e->usage = 06745 "Usage: core show applications [{like|describing} <text>]\n" 06746 " List applications which are currently available.\n" 06747 " If 'like', <text> will be a substring of the app name\n" 06748 " If 'describing', <text> will be a substring of the description\n"; 06749 return NULL; 06750 case CLI_GENERATE: 06751 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 06752 } 06753 06754 AST_RWLIST_RDLOCK(&apps); 06755 06756 if (AST_RWLIST_EMPTY(&apps)) { 06757 ast_cli(a->fd, "There are no registered applications\n"); 06758 AST_RWLIST_UNLOCK(&apps); 06759 return CLI_SUCCESS; 06760 } 06761 06762 /* core list applications like <keyword> */ 06763 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 06764 like = 1; 06765 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 06766 describing = 1; 06767 } 06768 06769 /* core list applications describing <keyword1> [<keyword2>] [...] */ 06770 if ((!like) && (!describing)) { 06771 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 06772 } else { 06773 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 06774 } 06775 06776 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06777 int printapp = 0; 06778 total_apps++; 06779 if (like) { 06780 if (strcasestr(aa->name, a->argv[4])) { 06781 printapp = 1; 06782 total_match++; 06783 } 06784 } else if (describing) { 06785 if (aa->description) { 06786 /* Match all words on command line */ 06787 int i; 06788 printapp = 1; 06789 for (i = 4; i < a->argc; i++) { 06790 if (!strcasestr(aa->description, a->argv[i])) { 06791 printapp = 0; 06792 } else { 06793 total_match++; 06794 } 06795 } 06796 } 06797 } else { 06798 printapp = 1; 06799 } 06800 06801 if (printapp) { 06802 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 06803 } 06804 } 06805 if ((!like) && (!describing)) { 06806 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 06807 } else { 06808 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 06809 } 06810 06811 AST_RWLIST_UNLOCK(&apps); 06812 06813 return CLI_SUCCESS; 06814 }
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 7466 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), ast_str_alloca, ast_str_buffer(), ast_str_strlen(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_serialize_variables(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
07467 { 07468 struct ast_channel *chan = NULL; 07469 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 07470 07471 switch (cmd) { 07472 case CLI_INIT: 07473 e->command = "dialplan show chanvar"; 07474 e->usage = 07475 "Usage: dialplan show chanvar <channel>\n" 07476 " List current channel variables and their values\n"; 07477 return NULL; 07478 case CLI_GENERATE: 07479 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07480 } 07481 07482 if (a->argc != e->args + 1) 07483 return CLI_SHOWUSAGE; 07484 07485 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 07486 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 07487 return CLI_FAILURE; 07488 } 07489 07490 pbx_builtin_serialize_variables(chan, &vars); 07491 07492 if (ast_str_strlen(vars)) { 07493 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 07494 } 07495 07496 chan = ast_channel_unref(chan); 07497 07498 return CLI_SUCCESS; 07499 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7083 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, ast_cli_entry::usage, and ast_cli_args::word.
07084 { 07085 char *exten = NULL, *context = NULL; 07086 /* Variables used for different counters */ 07087 struct dialplan_counters counters; 07088 const char *incstack[AST_PBX_MAX_STACK]; 07089 07090 switch (cmd) { 07091 case CLI_INIT: 07092 e->command = "dialplan show"; 07093 e->usage = 07094 "Usage: dialplan show [[exten@]context]\n" 07095 " Show dialplan\n"; 07096 return NULL; 07097 case CLI_GENERATE: 07098 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 07099 } 07100 07101 memset(&counters, 0, sizeof(counters)); 07102 07103 if (a->argc != 2 && a->argc != 3) 07104 return CLI_SHOWUSAGE; 07105 07106 /* we obtain [exten@]context? if yes, split them ... */ 07107 if (a->argc == 3) { 07108 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 07109 context = ast_strdupa(a->argv[2]); 07110 exten = strsep(&context, "@"); 07111 /* change empty strings to NULL */ 07112 if (ast_strlen_zero(exten)) 07113 exten = NULL; 07114 } else { /* no '@' char, only context given */ 07115 context = ast_strdupa(a->argv[2]); 07116 } 07117 if (ast_strlen_zero(context)) 07118 context = NULL; 07119 } 07120 /* else Show complete dial plan, context and exten are NULL */ 07121 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 07122 07123 /* check for input failure and throw some error messages */ 07124 if (context && !counters.context_existence) { 07125 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 07126 return CLI_FAILURE; 07127 } 07128 07129 if (exten && !counters.extension_existence) { 07130 if (context) 07131 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 07132 exten, context); 07133 else 07134 ast_cli(a->fd, 07135 "There is no existence of '%s' extension in all contexts\n", 07136 exten); 07137 return CLI_FAILURE; 07138 } 07139 07140 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 07141 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 07142 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 07143 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 07144 07145 /* everything ok */ 07146 return CLI_SUCCESS; 07147 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3647 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), ast_free, ast_malloc, AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_custom_function::docsrc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, S_OR, synopsis, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
03648 { 03649 struct ast_custom_function *acf; 03650 /* Maximum number of characters added by terminal coloring is 22 */ 03651 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03652 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03653 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03654 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03655 char *ret = NULL; 03656 int which = 0; 03657 int wordlen; 03658 03659 switch (cmd) { 03660 case CLI_INIT: 03661 e->command = "core show function"; 03662 e->usage = 03663 "Usage: core show function <function>\n" 03664 " Describe a particular dialplan function.\n"; 03665 return NULL; 03666 case CLI_GENERATE: 03667 wordlen = strlen(a->word); 03668 /* case-insensitive for convenience in this 'complete' function */ 03669 AST_RWLIST_RDLOCK(&acf_root); 03670 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03671 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03672 ret = ast_strdup(acf->name); 03673 break; 03674 } 03675 } 03676 AST_RWLIST_UNLOCK(&acf_root); 03677 03678 return ret; 03679 } 03680 03681 if (a->argc < 4) { 03682 return CLI_SHOWUSAGE; 03683 } 03684 03685 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03686 ast_cli(a->fd, "No function by that name registered.\n"); 03687 return CLI_FAILURE; 03688 } 03689 03690 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03691 if (!(syntax = ast_malloc(syntax_size))) { 03692 ast_cli(a->fd, "Memory allocation failure!\n"); 03693 return CLI_FAILURE; 03694 } 03695 03696 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03697 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03698 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03699 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03700 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03701 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03702 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03703 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03704 #ifdef AST_XML_DOCS 03705 if (acf->docsrc == AST_XML_DOC) { 03706 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03707 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03708 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03709 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03710 } else 03711 #endif 03712 { 03713 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03714 synopsis = ast_malloc(synopsis_size); 03715 03716 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03717 description = ast_malloc(description_size); 03718 03719 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03720 arguments = ast_malloc(arguments_size); 03721 03722 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03723 seealso = ast_malloc(seealso_size); 03724 03725 /* check allocated memory. */ 03726 if (!synopsis || !description || !arguments || !seealso) { 03727 ast_free(synopsis); 03728 ast_free(description); 03729 ast_free(arguments); 03730 ast_free(seealso); 03731 ast_free(syntax); 03732 return CLI_FAILURE; 03733 } 03734 03735 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03736 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03737 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03738 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03739 } 03740 03741 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03742 infotitle, syntitle, synopsis, destitle, description, 03743 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03744 03745 ast_free(arguments); 03746 ast_free(synopsis); 03747 ast_free(description); 03748 ast_free(seealso); 03749 ast_free(syntax); 03750 03751 return CLI_SUCCESS; 03752 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3605 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, S_OR, and ast_cli_entry::usage.
03606 { 03607 struct ast_custom_function *acf; 03608 int count_acf = 0; 03609 int like = 0; 03610 03611 switch (cmd) { 03612 case CLI_INIT: 03613 e->command = "core show functions [like]"; 03614 e->usage = 03615 "Usage: core show functions [like <text>]\n" 03616 " List builtin functions, optionally only those matching a given string\n"; 03617 return NULL; 03618 case CLI_GENERATE: 03619 return NULL; 03620 } 03621 03622 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03623 like = 1; 03624 } else if (a->argc != 3) { 03625 return CLI_SHOWUSAGE; 03626 } 03627 03628 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03629 03630 AST_RWLIST_RDLOCK(&acf_root); 03631 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03632 if (!like || strstr(acf->name, a->argv[4])) { 03633 count_acf++; 03634 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03635 S_OR(acf->name, ""), 03636 S_OR(acf->syntax, ""), 03637 S_OR(acf->synopsis, "")); 03638 } 03639 } 03640 AST_RWLIST_UNLOCK(&acf_root); 03641 03642 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03643 03644 return CLI_SUCCESS; 03645 }
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 7408 of file pbx.c.
References ast_cli(), AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, globals, globalslock, and ast_cli_entry::usage.
07409 { 07410 int i = 0; 07411 struct ast_var_t *newvariable; 07412 07413 switch (cmd) { 07414 case CLI_INIT: 07415 e->command = "dialplan show globals"; 07416 e->usage = 07417 "Usage: dialplan show globals\n" 07418 " List current global dialplan variables and their values\n"; 07419 return NULL; 07420 case CLI_GENERATE: 07421 return NULL; 07422 } 07423 07424 ast_rwlock_rdlock(&globalslock); 07425 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 07426 i++; 07427 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 07428 } 07429 ast_rwlock_unlock(&globalslock); 07430 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 07431 07432 return CLI_SUCCESS; 07433 }
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 6639 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
06640 { 06641 struct ast_hint *hint; 06642 int watchers; 06643 int num = 0, extenlen; 06644 struct ao2_iterator i; 06645 06646 switch (cmd) { 06647 case CLI_INIT: 06648 e->command = "core show hint"; 06649 e->usage = 06650 "Usage: core show hint <exten>\n" 06651 " List registered hint.\n" 06652 " Hint details are shown in four columns. In order from left to right, they are:\n" 06653 " 1. Hint extension URI.\n" 06654 " 2. Mapped device state identifiers.\n" 06655 " 3. Current extension state. The aggregate of mapped device states.\n" 06656 " 4. Watchers - number of subscriptions and other entities watching this hint.\n"; 06657 06658 return NULL; 06659 case CLI_GENERATE: 06660 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 06661 } 06662 06663 if (a->argc < 4) 06664 return CLI_SHOWUSAGE; 06665 06666 if (ao2_container_count(hints) == 0) { 06667 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06668 return CLI_SUCCESS; 06669 } 06670 06671 extenlen = strlen(a->argv[3]); 06672 i = ao2_iterator_init(hints, 0); 06673 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06674 ao2_lock(hint); 06675 if (!hint->exten) { 06676 /* The extension has already been destroyed */ 06677 ao2_unlock(hint); 06678 continue; 06679 } 06680 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 06681 watchers = ao2_container_count(hint->callbacks); 06682 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06683 ast_get_extension_name(hint->exten), 06684 ast_get_context_name(ast_get_extension_context(hint->exten)), 06685 ast_get_extension_app(hint->exten), 06686 ast_extension_state2str(hint->laststate), watchers); 06687 num++; 06688 } 06689 ao2_unlock(hint); 06690 } 06691 ao2_iterator_destroy(&i); 06692 if (!num) 06693 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 06694 else 06695 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 06696 return CLI_SUCCESS; 06697 }
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 6548 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, and ast_cli_entry::usage.
06549 { 06550 struct ast_hint *hint; 06551 int num = 0; 06552 int watchers; 06553 struct ao2_iterator i; 06554 06555 switch (cmd) { 06556 case CLI_INIT: 06557 e->command = "core show hints"; 06558 e->usage = 06559 "Usage: core show hints\n" 06560 " List registered hints.\n" 06561 " Hint details are shown in four columns. In order from left to right, they are:\n" 06562 " 1. Hint extension URI.\n" 06563 " 2. Mapped device state identifiers.\n" 06564 " 3. Current extension state. The aggregate of mapped device states.\n" 06565 " 4. Watchers - number of subscriptions and other entities watching this hint.\n"; 06566 return NULL; 06567 case CLI_GENERATE: 06568 return NULL; 06569 } 06570 06571 if (ao2_container_count(hints) == 0) { 06572 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06573 return CLI_SUCCESS; 06574 } 06575 /* ... we have hints ... */ 06576 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 06577 06578 i = ao2_iterator_init(hints, 0); 06579 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06580 ao2_lock(hint); 06581 if (!hint->exten) { 06582 /* The extension has already been destroyed */ 06583 ao2_unlock(hint); 06584 continue; 06585 } 06586 watchers = ao2_container_count(hint->callbacks); 06587 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06588 ast_get_extension_name(hint->exten), 06589 ast_get_context_name(ast_get_extension_context(hint->exten)), 06590 ast_get_extension_app(hint->exten), 06591 ast_extension_state2str(hint->laststate), watchers); 06592 ao2_unlock(hint); 06593 num++; 06594 } 06595 ao2_iterator_destroy(&i); 06596 06597 ast_cli(a->fd, "----------------\n"); 06598 ast_cli(a->fd, "- %d hints registered\n", num); 06599 return CLI_SUCCESS; 06600 }
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 6701 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.
06702 { 06703 struct ast_switch *sw; 06704 06705 switch (cmd) { 06706 case CLI_INIT: 06707 e->command = "core show switches"; 06708 e->usage = 06709 "Usage: core show switches\n" 06710 " List registered switches\n"; 06711 return NULL; 06712 case CLI_GENERATE: 06713 return NULL; 06714 } 06715 06716 AST_RWLIST_RDLOCK(&switches); 06717 06718 if (AST_RWLIST_EMPTY(&switches)) { 06719 AST_RWLIST_UNLOCK(&switches); 06720 ast_cli(a->fd, "There are no registered alternative switches\n"); 06721 return CLI_SUCCESS; 06722 } 06723 06724 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 06725 AST_RWLIST_TRAVERSE(&switches, sw, list) 06726 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 06727 06728 AST_RWLIST_UNLOCK(&switches); 06729 06730 return CLI_SUCCESS; 06731 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4890 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_extension_state3(), ast_free, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_hint::callbacks, ast_state_cb::change_cb, context_merge_lock, ast_state_cb::data, statechange::dev, ast_hint::exten, hints, ast_hint::laststate, parse(), and statecbs.
Referenced by device_state_cb().
04891 { 04892 struct ast_hint *hint; 04893 struct ast_str *hint_app; 04894 struct statechange *sc = datap; 04895 struct ao2_iterator i; 04896 struct ao2_iterator cb_iter; 04897 char context_name[AST_MAX_CONTEXT]; 04898 char exten_name[AST_MAX_EXTENSION]; 04899 04900 hint_app = ast_str_create(1024); 04901 if (!hint_app) { 04902 ast_free(sc); 04903 return -1; 04904 } 04905 04906 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ 04907 i = ao2_iterator_init(hints, 0); 04908 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 04909 struct ast_state_cb *state_cb; 04910 char *cur, *parse; 04911 int state; 04912 04913 ao2_lock(hint); 04914 if (!hint->exten) { 04915 /* The extension has already been destroyed */ 04916 ao2_unlock(hint); 04917 continue; 04918 } 04919 04920 /* Does this hint monitor the device that changed state? */ 04921 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04922 parse = ast_str_buffer(hint_app); 04923 while ((cur = strsep(&parse, "&"))) { 04924 if (!strcasecmp(cur, sc->dev)) { 04925 /* The hint monitors the device. */ 04926 break; 04927 } 04928 } 04929 if (!cur) { 04930 /* The hint does not monitor the device. */ 04931 ao2_unlock(hint); 04932 continue; 04933 } 04934 04935 /* 04936 * Save off strings in case the hint extension gets destroyed 04937 * while we are notifying the watchers. 04938 */ 04939 ast_copy_string(context_name, 04940 ast_get_context_name(ast_get_extension_context(hint->exten)), 04941 sizeof(context_name)); 04942 ast_copy_string(exten_name, ast_get_extension_name(hint->exten), 04943 sizeof(exten_name)); 04944 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04945 ao2_unlock(hint); 04946 04947 /* 04948 * Get device state for this hint. 04949 * 04950 * NOTE: We cannot hold any locks while determining the hint 04951 * device state or notifying the watchers without causing a 04952 * deadlock. (conlock, hints, and hint) 04953 */ 04954 state = ast_extension_state3(hint_app); 04955 if (state == hint->laststate) { 04956 continue; 04957 } 04958 04959 /* Device state changed since last check - notify the watchers. */ 04960 hint->laststate = state; /* record we saw the change */ 04961 04962 /* For general callbacks */ 04963 cb_iter = ao2_iterator_init(statecbs, 0); 04964 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04965 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04966 } 04967 ao2_iterator_destroy(&cb_iter); 04968 04969 /* For extension callbacks */ 04970 cb_iter = ao2_iterator_init(hint->callbacks, 0); 04971 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04972 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04973 } 04974 ao2_iterator_destroy(&cb_iter); 04975 } 04976 ao2_iterator_destroy(&i); 04977 ast_mutex_unlock(&context_merge_lock); 04978 04979 ast_free(hint_app); 04980 ast_free(sc); 04981 return 0; 04982 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7588 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.
07589 { 07590 int oldval = 0; 07591 07592 switch (cmd) { 07593 case CLI_INIT: 07594 e->command = "dialplan set extenpatternmatchnew false"; 07595 e->usage = 07596 "Usage: dialplan set extenpatternmatchnew true|false\n" 07597 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07598 return NULL; 07599 case CLI_GENERATE: 07600 return NULL; 07601 } 07602 07603 if (a->argc != 4) 07604 return CLI_SHOWUSAGE; 07605 07606 oldval = pbx_set_extenpatternmatchnew(0); 07607 07608 if (!oldval) 07609 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07610 else 07611 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07612 07613 return CLI_SUCCESS; 07614 }
static int hashtab_compare_exten_labels | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
static int hashtab_compare_exten_numbers | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1130 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1102 of file pbx.c.
References AST_EXT_MATCHCID_ANY, AST_EXT_MATCHCID_OFF, ast_strlen_zero(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01103 { 01104 const struct ast_exten *ac = ah_a; 01105 const struct ast_exten *bc = ah_b; 01106 int x = strcmp(ac->exten, bc->exten); 01107 if (x) { /* if exten names are diff, then return */ 01108 return x; 01109 } 01110 01111 /* but if they are the same, do the cidmatch values match? */ 01112 /* not sure which side may be using ast_ext_matchcid_types, so check both */ 01113 if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) { 01114 return 0; 01115 } 01116 if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) { 01117 return 0; 01118 } 01119 if (ac->matchcid != bc->matchcid) { 01120 return 1; 01121 } 01122 /* all other cases already disposed of, match now required on callerid string (cidmatch) */ 01123 /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */ 01124 if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) { 01125 return 0; 01126 } 01127 return strcmp(ac->cidmatch, bc->cidmatch); 01128 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1150 of file pbx.c.
References AST_EXT_MATCHCID_ON, ast_hashtab_hash_string(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01151 { 01152 const struct ast_exten *ac = obj; 01153 unsigned int x = ast_hashtab_hash_string(ac->exten); 01154 unsigned int y = 0; 01155 if (ac->matchcid == AST_EXT_MATCHCID_ON) 01156 y = ast_hashtab_hash_string(ac->cidmatch); 01157 return x+y; 01158 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1166 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01167 { 01168 const struct ast_exten *ac = obj; 01169 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01170 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1160 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01161 { 01162 const struct ast_exten *ac = obj; 01163 return ast_hashtab_hash_int(ac->priority); 01164 }
static int hint_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
static int hint_hash | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 11214 of file pbx.c.
References ast_get_extension_name(), ast_str_case_hash(), ast_strlen_zero(), ast_hint::exten, and ast_hint::exten_name.
Referenced by ast_pbx_init().
11215 { 11216 const struct ast_hint *hint = obj; 11217 const char *exten_name; 11218 int res; 11219 11220 exten_name = ast_get_extension_name(hint->exten); 11221 if (ast_strlen_zero(exten_name)) { 11222 /* 11223 * If the exten or extension name isn't set, return 0 so that 11224 * the ao2_find() search will start in the first bucket. 11225 */ 11226 res = 0; 11227 } else { 11228 res = ast_str_case_hash(exten_name); 11229 } 11230 11231 return res; 11232 }
static int hint_id_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 5145 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
05146 { 05147 const struct ast_state_cb *cb = obj; 05148 int *id = arg; 05149 05150 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 05151 }
static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 10787 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_hint::exten, hints, and ast_hint::laststate.
10789 { 10790 struct ast_data *data_hint; 10791 struct ast_hint *hint; 10792 int watchers; 10793 struct ao2_iterator i; 10794 10795 if (ao2_container_count(hints) == 0) { 10796 return 0; 10797 } 10798 10799 i = ao2_iterator_init(hints, 0); 10800 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 10801 watchers = ao2_container_count(hint->callbacks); 10802 data_hint = ast_data_add_node(data_root, "hint"); 10803 if (!data_hint) { 10804 continue; 10805 } 10806 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 10807 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 10808 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 10809 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 10810 ast_data_add_int(data_hint, "watchers", watchers); 10811 10812 if (!ast_data_search_match(search, data_hint)) { 10813 ast_data_remove_node(data_root, data_hint); 10814 } 10815 } 10816 ao2_iterator_destroy(&i); 10817 10818 return 0; 10819 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1519 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01520 { 01521 if (!i->hastime) 01522 return 1; 01523 01524 return ast_check_timing(&(i->timing)); 01525 }
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 5744 of file pbx.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, countcalls, LOG_WARNING, maxcalllock, option_maxcalls, option_maxload, option_minmemfree, and totalcalls.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
05745 { 05746 int failed = 0; 05747 double curloadavg; 05748 #if defined(HAVE_SYSINFO) 05749 long curfreemem; 05750 struct sysinfo sys_info; 05751 #endif 05752 05753 ast_mutex_lock(&maxcalllock); 05754 if (option_maxcalls) { 05755 if (countcalls >= option_maxcalls) { 05756 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 05757 failed = -1; 05758 } 05759 } 05760 if (option_maxload) { 05761 getloadavg(&curloadavg, 1); 05762 if (curloadavg >= option_maxload) { 05763 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 05764 failed = -1; 05765 } 05766 } 05767 #if defined(HAVE_SYSINFO) 05768 if (option_minmemfree) { 05769 if (!sysinfo(&sys_info)) { 05770 /* make sure that the free system memory is above the configured low watermark 05771 * convert the amount of freeram from mem_units to MB */ 05772 curfreemem = sys_info.freeram * sys_info.mem_unit; 05773 curfreemem /= 1024 * 1024; 05774 if (curfreemem < option_minmemfree) { 05775 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 05776 failed = -1; 05777 } 05778 } 05779 } 05780 #endif 05781 05782 if (!failed) { 05783 countcalls++; 05784 totalcalls++; 05785 } 05786 ast_mutex_unlock(&maxcalllock); 05787 05788 return failed; 05789 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1937 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01938 { 01939 struct match_char *curr, *lcurr; 01940 01941 /* insert node into the tree at "current", so the alt_char list from current is 01942 sorted in increasing value as you go to the leaves */ 01943 if (!(*parent_ptr)) { 01944 *parent_ptr = node; 01945 return; 01946 } 01947 01948 if ((*parent_ptr)->specificity > node->specificity) { 01949 /* insert at head */ 01950 node->alt_char = (*parent_ptr); 01951 *parent_ptr = node; 01952 return; 01953 } 01954 01955 lcurr = *parent_ptr; 01956 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01957 if (curr->specificity > node->specificity) { 01958 node->alt_char = curr; 01959 lcurr->alt_char = node; 01960 break; 01961 } 01962 lcurr = curr; 01963 } 01964 01965 if (!curr) { 01966 lcurr->alt_char = node; 01967 } 01968 01969 }
static int is_read_allowed | ( | struct ast_custom_function * | acfptr | ) | [static] |
Determines whether execution of a custom function's read function is allowed.
acfptr | Custom function to check |
Definition at line 4073 of file pbx.c.
References ast_debug, ast_custom_function::name, read_escalates(), and thread_inhibits_escalations().
Referenced by ast_func_read(), and ast_func_read2().
04074 { 04075 if (!acfptr) { 04076 return 1; 04077 } 04078 04079 if (!read_escalates(acfptr)) { 04080 return 1; 04081 } 04082 04083 if (!thread_inhibits_escalations()) { 04084 return 1; 04085 } 04086 04087 if (live_dangerously) { 04088 /* Global setting overrides the thread's preference */ 04089 ast_debug(2, "Reading %s from a dangerous context\n", 04090 acfptr->name); 04091 return 1; 04092 } 04093 04094 /* We have no reason to allow this function to execute */ 04095 return 0; 04096 }
static int is_write_allowed | ( | struct ast_custom_function * | acfptr | ) | [static] |
Determines whether execution of a custom function's write function is allowed.
acfptr | Custom function to check |
Definition at line 4106 of file pbx.c.
References ast_debug, ast_custom_function::name, thread_inhibits_escalations(), and write_escalates().
Referenced by ast_func_write().
04107 { 04108 if (!acfptr) { 04109 return 1; 04110 } 04111 04112 if (!write_escalates(acfptr)) { 04113 return 1; 04114 } 04115 04116 if (!thread_inhibits_escalations()) { 04117 return 1; 04118 } 04119 04120 if (live_dangerously) { 04121 /* Global setting overrides the thread's preference */ 04122 ast_debug(2, "Writing %s from a dangerous context\n", 04123 acfptr->name); 04124 return 1; 04125 } 04126 04127 /* We have no reason to allow this function to execute */ 04128 return 0; 04129 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 10855 of file pbx.c.
References __ast_custom_function_register(), ARRAY_LEN, ast_cli_register_multiple(), ast_data_register_multiple_core, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register_xml, ast_register_application2(), ast_register_atexit(), ast_taskprocessor_get(), ast_verb, builtins, device_state_cb(), device_state_sub, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), pbx_cli, pbx_data_providers, testtime_function, and unload_pbx().
Referenced by main().
10856 { 10857 int x; 10858 10859 ast_register_atexit(unload_pbx); 10860 10861 /* Initialize the PBX */ 10862 ast_verb(1, "Asterisk PBX Core Initializing\n"); 10863 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 10864 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 10865 } 10866 10867 ast_verb(1, "Registering builtin applications:\n"); 10868 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10869 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 10870 __ast_custom_function_register(&exception_function, NULL); 10871 __ast_custom_function_register(&testtime_function, NULL); 10872 10873 /* Register builtin applications */ 10874 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10875 ast_verb(1, "[%s]\n", builtins[x].name); 10876 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 10877 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 10878 return -1; 10879 } 10880 } 10881 10882 /* Register manager application */ 10883 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 10884 10885 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 10886 AST_EVENT_IE_END))) { 10887 return -1; 10888 } 10889 10890 return 0; 10891 }
static int lookup_name | ( | const char * | s, | |
const char *const | names[], | |||
int | max | |||
) | [static] |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
Definition at line 8113 of file pbx.c.
Referenced by get_range().
08114 { 08115 int i; 08116 08117 if (names && *s > '9') { 08118 for (i = 0; names[i]; i++) { 08119 if (!strcasecmp(s, names[i])) { 08120 return i; 08121 } 08122 } 08123 } 08124 08125 /* Allow months and weekdays to be specified as numbers, as well */ 08126 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 08127 /* What the array offset would have been: "1" would be at offset 0 */ 08128 return i - 1; 08129 } 08130 return -1; /* error return */ 08131 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 7206 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().
07207 { 07208 astman_send_listack(s, m, "DialPlan list will follow", "start"); 07209 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 7351 of file pbx.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, manager_dpsendack(), manager_show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.
Referenced by load_pbx().
07352 { 07353 const char *exten, *context; 07354 const char *id = astman_get_header(m, "ActionID"); 07355 char idtext[256]; 07356 07357 /* Variables used for different counters */ 07358 struct dialplan_counters counters; 07359 07360 if (!ast_strlen_zero(id)) 07361 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 07362 else 07363 idtext[0] = '\0'; 07364 07365 memset(&counters, 0, sizeof(counters)); 07366 07367 exten = astman_get_header(m, "Extension"); 07368 context = astman_get_header(m, "Context"); 07369 07370 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 07371 07372 if (!ast_strlen_zero(context) && !counters.context_existence) { 07373 char errorbuf[BUFSIZ]; 07374 07375 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 07376 astman_send_error(s, m, errorbuf); 07377 return 0; 07378 } 07379 if (!ast_strlen_zero(exten) && !counters.extension_existence) { 07380 char errorbuf[BUFSIZ]; 07381 07382 if (!ast_strlen_zero(context)) 07383 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 07384 else 07385 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 07386 astman_send_error(s, m, errorbuf); 07387 return 0; 07388 } 07389 07390 if (!counters.total_items) { 07391 manager_dpsendack(s, m); 07392 } 07393 07394 astman_append(s, "Event: ShowDialPlanComplete\r\n" 07395 "EventList: Complete\r\n" 07396 "ListItems: %d\r\n" 07397 "ListExtensions: %d\r\n" 07398 "ListPriorities: %d\r\n" 07399 "ListContexts: %d\r\n" 07400 "%s" 07401 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 07402 07403 /* everything ok */ 07404 return 0; 07405 }
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 7215 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().
07219 { 07220 struct ast_context *c; 07221 int res = 0, old_total_exten = dpc->total_exten; 07222 07223 if (ast_strlen_zero(exten)) 07224 exten = NULL; 07225 if (ast_strlen_zero(context)) 07226 context = NULL; 07227 07228 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 07229 07230 /* try to lock contexts */ 07231 if (ast_rdlock_contexts()) { 07232 astman_send_error(s, m, "Failed to lock contexts"); 07233 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 07234 return -1; 07235 } 07236 07237 c = NULL; /* walk all contexts ... */ 07238 while ( (c = ast_walk_contexts(c)) ) { 07239 struct ast_exten *e; 07240 struct ast_include *i; 07241 struct ast_ignorepat *ip; 07242 07243 if (context && strcmp(ast_get_context_name(c), context) != 0) 07244 continue; /* not the name we want */ 07245 07246 dpc->context_existence = 1; 07247 dpc->total_context++; 07248 07249 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 07250 07251 if (ast_rdlock_context(c)) { /* failed to lock */ 07252 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 07253 continue; 07254 } 07255 07256 /* XXX note- an empty context is not printed */ 07257 e = NULL; /* walk extensions in context */ 07258 while ( (e = ast_walk_context_extensions(c, e)) ) { 07259 struct ast_exten *p; 07260 07261 /* looking for extension? is this our extension? */ 07262 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 07263 /* not the one we are looking for, continue */ 07264 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 07265 continue; 07266 } 07267 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 07268 07269 dpc->extension_existence = 1; 07270 07271 dpc->total_exten++; 07272 07273 p = NULL; /* walk next extension peers */ 07274 while ( (p = ast_walk_extension_priorities(e, p)) ) { 07275 int prio = ast_get_extension_priority(p); 07276 07277 dpc->total_prio++; 07278 if (!dpc->total_items++) 07279 manager_dpsendack(s, m); 07280 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07281 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 07282 07283 /* XXX maybe make this conditional, if p != e ? */ 07284 if (ast_get_extension_label(p)) 07285 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 07286 07287 if (prio == PRIORITY_HINT) { 07288 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 07289 } else { 07290 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)); 07291 } 07292 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 07293 } 07294 } 07295 07296 i = NULL; /* walk included and write info ... */ 07297 while ( (i = ast_walk_context_includes(c, i)) ) { 07298 if (exten) { 07299 /* Check all includes for the requested extension */ 07300 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 07301 } else { 07302 if (!dpc->total_items++) 07303 manager_dpsendack(s, m); 07304 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07305 astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i)); 07306 astman_append(s, "\r\n"); 07307 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 07308 } 07309 } 07310 07311 ip = NULL; /* walk ignore patterns and write info ... */ 07312 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 07313 const char *ipname = ast_get_ignorepat_name(ip); 07314 char ignorepat[AST_MAX_EXTENSION]; 07315 07316 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 07317 if (!exten || ast_extension_match(ignorepat, exten)) { 07318 if (!dpc->total_items++) 07319 manager_dpsendack(s, m); 07320 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07321 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 07322 astman_append(s, "\r\n"); 07323 } 07324 } 07325 if (!rinclude) { 07326 struct ast_sw *sw = NULL; 07327 while ( (sw = ast_walk_context_switches(c, sw)) ) { 07328 if (!dpc->total_items++) 07329 manager_dpsendack(s, m); 07330 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07331 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)); 07332 astman_append(s, "\r\n"); 07333 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 07334 } 07335 } 07336 07337 ast_unlock_context(c); 07338 } 07339 ast_unlock_contexts(); 07340 07341 if (dpc->total_exten == old_total_exten) { 07342 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 07343 /* Nothing new under the sun */ 07344 return -1; 07345 } else { 07346 return res; 07347 } 07348 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2955 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02956 { 02957 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02958 failing to get a number should count as a match, otherwise not */ 02959 02960 if (ast_strlen_zero(callerid)) { 02961 return ast_strlen_zero(cidpattern) ? 1 : 0; 02962 } 02963 02964 return ast_extension_match(cidpattern, callerid); 02965 }
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 1761 of file pbx.c.
References match_char::alt_char, ast_debug, ast_log(), scoreboard::canmatch, match_char::deleted, E_CANMATCH, E_MATCHMORE, ast_exten::exten, scoreboard::exten, match_char::exten, match_char::is_pattern, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, NEW_MATCHER_RECURSE, match_char::next_char, match_char::specificity, update_scoreboard(), and match_char::x.
Referenced by pbx_find_extension().
01762 { 01763 struct match_char *p; /* note minimal stack storage requirements */ 01764 struct ast_exten pattern = { .label = label }; 01765 #ifdef DEBUG_THIS 01766 if (tree) 01767 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01768 else 01769 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01770 #endif 01771 for (p = tree; p; p = p->alt_char) { 01772 if (p->is_pattern) { 01773 if (p->x[0] == 'N') { 01774 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01775 #define NEW_MATCHER_CHK_MATCH \ 01776 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01777 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01778 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01779 if (!p->deleted) { \ 01780 if (action == E_FINDLABEL) { \ 01781 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01782 ast_debug(4, "Found label in preferred extension\n"); \ 01783 return; \ 01784 } \ 01785 } else { \ 01786 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01787 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01788 } \ 01789 } \ 01790 } \ 01791 } 01792 01793 #define NEW_MATCHER_RECURSE \ 01794 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01795 || p->next_char->x[0] == '!')) { \ 01796 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01797 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01798 if (score->exten) { \ 01799 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01800 return; /* the first match is all we need */ \ 01801 } \ 01802 } else { \ 01803 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01804 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01805 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01806 "NULL"); \ 01807 return; /* the first match is all we need */ \ 01808 } \ 01809 } \ 01810 } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \ 01811 score->canmatch = 1; \ 01812 score->canmatch_exten = get_canmatch_exten(p); \ 01813 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01814 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01815 return; \ 01816 } \ 01817 } 01818 01819 NEW_MATCHER_CHK_MATCH; 01820 NEW_MATCHER_RECURSE; 01821 } 01822 } else if (p->x[0] == 'Z') { 01823 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01824 NEW_MATCHER_CHK_MATCH; 01825 NEW_MATCHER_RECURSE; 01826 } 01827 } else if (p->x[0] == 'X') { 01828 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01829 NEW_MATCHER_CHK_MATCH; 01830 NEW_MATCHER_RECURSE; 01831 } 01832 } else if (p->x[0] == '.' && p->x[1] == 0) { 01833 /* how many chars will the . match against? */ 01834 int i = 0; 01835 const char *str2 = str; 01836 while (*str2 && *str2 != '/') { 01837 str2++; 01838 i++; 01839 } 01840 if (p->exten && *str2 != '/') { 01841 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01842 if (score->exten) { 01843 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01844 return; /* the first match is all we need */ 01845 } 01846 } 01847 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01848 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01849 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01850 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01851 return; /* the first match is all we need */ 01852 } 01853 } 01854 } else if (p->x[0] == '!' && p->x[1] == 0) { 01855 /* how many chars will the . match against? */ 01856 int i = 1; 01857 const char *str2 = str; 01858 while (*str2 && *str2 != '/') { 01859 str2++; 01860 i++; 01861 } 01862 if (p->exten && *str2 != '/') { 01863 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01864 if (score->exten) { 01865 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01866 return; /* the first match is all we need */ 01867 } 01868 } 01869 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01870 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01871 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01872 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01873 return; /* the first match is all we need */ 01874 } 01875 } 01876 } else if (p->x[0] == '/' && p->x[1] == 0) { 01877 /* the pattern in the tree includes the cid match! */ 01878 if (p->next_char && callerid && *callerid) { 01879 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01880 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01881 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01882 return; /* the first match is all we need */ 01883 } 01884 } 01885 } else if (strchr(p->x, *str)) { 01886 ast_debug(4, "Nothing strange about this match\n"); 01887 NEW_MATCHER_CHK_MATCH; 01888 NEW_MATCHER_RECURSE; 01889 } 01890 } else if (strchr(p->x, *str)) { 01891 ast_debug(4, "Nothing strange about this match\n"); 01892 NEW_MATCHER_CHK_MATCH; 01893 NEW_MATCHER_RECURSE; 01894 } 01895 } 01896 ast_debug(4, "return at end of func\n"); 01897 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 3265 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
03266 { 03267 int parens = 0; 03268 03269 *offset = 0; 03270 *length = INT_MAX; 03271 *isfunc = 0; 03272 for (; *var; var++) { 03273 if (*var == '(') { 03274 (*isfunc)++; 03275 parens++; 03276 } else if (*var == ')') { 03277 parens--; 03278 } else if (*var == ':' && parens == 0) { 03279 *var++ = '\0'; 03280 sscanf(var, "%30d:%30d", offset, length); 03281 return 1; /* offset:length valid */ 03282 } 03283 } 03284 return 0; 03285 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10663 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), pbx_shutdown(), and reload().
10664 { 10665 struct ast_var_t *vardata; 10666 10667 ast_rwlock_wrlock(&globalslock); 10668 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10669 ast_var_delete(vardata); 10670 ast_rwlock_unlock(&globalslock); 10671 }
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 10429 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), gosub_run(), handle_gosub(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_exec(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
10430 { 10431 struct ast_var_t *variables; 10432 const char *ret = NULL; 10433 int i; 10434 struct varshead *places[2] = { NULL, &globals }; 10435 10436 if (!name) 10437 return NULL; 10438 10439 if (chan) { 10440 ast_channel_lock(chan); 10441 places[0] = &chan->varshead; 10442 } 10443 10444 for (i = 0; i < 2; i++) { 10445 if (!places[i]) 10446 continue; 10447 if (places[i] == &globals) 10448 ast_rwlock_rdlock(&globalslock); 10449 AST_LIST_TRAVERSE(places[i], variables, entries) { 10450 if (!strcmp(name, ast_var_name(variables))) { 10451 ret = ast_var_value(variables); 10452 break; 10453 } 10454 } 10455 if (places[i] == &globals) 10456 ast_rwlock_unlock(&globalslock); 10457 if (ret) 10458 break; 10459 } 10460 10461 if (chan) 10462 ast_channel_unlock(chan); 10463 10464 return ret; 10465 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10685 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), and pbx_checkcondition().
10686 { 10687 char *condition, *branch1, *branch2, *branch; 10688 char *stringp; 10689 10690 if (ast_strlen_zero(data)) { 10691 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 10692 return 0; 10693 } 10694 10695 stringp = ast_strdupa(data); 10696 condition = strsep(&stringp,"?"); 10697 branch1 = strsep(&stringp,":"); 10698 branch2 = strsep(&stringp,""); 10699 branch = pbx_checkcondition(condition) ? branch1 : branch2; 10700 10701 if (ast_strlen_zero(branch)) { 10702 ast_debug(1, "Not taking any branch\n"); 10703 return 0; 10704 } 10705 10706 return pbx_builtin_goto(chan, branch); 10707 }
int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10623 of file pbx.c.
References ast_alloca, ast_channel_get_by_name(), ast_channel_unref, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), value, and VAR_BUF_SIZE.
10624 { 10625 char *name; 10626 char *value; 10627 char *channel; 10628 char tmp[VAR_BUF_SIZE]; 10629 static int deprecation_warning = 0; 10630 10631 if (ast_strlen_zero(data)) { 10632 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 10633 return 0; 10634 } 10635 tmp[0] = 0; 10636 if (!deprecation_warning) { 10637 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 10638 deprecation_warning = 1; 10639 } 10640 10641 value = ast_strdupa(data); 10642 name = strsep(&value,"="); 10643 channel = strsep(&value,","); 10644 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 10645 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 10646 if (chan2) { 10647 char *s = ast_alloca(strlen(value) + 4); 10648 sprintf(s, "${%s}", value); 10649 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 10650 chan2 = ast_channel_unref(chan2); 10651 } 10652 pbx_builtin_setvar_helper(chan, name, tmp); 10653 } 10654 10655 return(0); 10656 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 9950 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_CONTROL_INCOMPLETE, ast_indicate(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
09951 { 09952 const char *options = data; 09953 int answer = 1; 09954 09955 /* Some channels can receive DTMF in unanswered state; some cannot */ 09956 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 09957 answer = 0; 09958 } 09959 09960 /* If the channel is hungup, stop waiting */ 09961 if (ast_check_hangup(chan)) { 09962 return -1; 09963 } else if (chan->_state != AST_STATE_UP && answer) { 09964 __ast_answer(chan, 0, 1); 09965 } 09966 09967 ast_indicate(chan, AST_CONTROL_INCOMPLETE); 09968 09969 return AST_PBX_INCOMPLETE; 09970 }
static int pbx_builtin_noop | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Add a variable to the channel variable stack, without removing any previously set value.
Definition at line 10467 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
10468 { 10469 struct ast_var_t *newvariable; 10470 struct varshead *headp; 10471 10472 if (name[strlen(name)-1] == ')') { 10473 char *function = ast_strdupa(name); 10474 10475 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10476 ast_func_write(chan, function, value); 10477 return; 10478 } 10479 10480 if (chan) { 10481 ast_channel_lock(chan); 10482 headp = &chan->varshead; 10483 } else { 10484 ast_rwlock_wrlock(&globalslock); 10485 headp = &globals; 10486 } 10487 10488 if (value && (newvariable = ast_var_assign(name, value))) { 10489 if (headp == &globals) 10490 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10491 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10492 } 10493 10494 if (chan) 10495 ast_channel_unlock(chan); 10496 else 10497 ast_rwlock_unlock(&globalslock); 10498 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason | |||
) |
Definition at line 3574 of file pbx.c.
References raise_exception().
03575 { 03576 /* Priority will become 1, next time through the AUTOLOOP */ 03577 return raise_exception(chan, reason, 0); 03578 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10746 of file pbx.c.
References ast_say_character_str().
10747 { 10748 int res = 0; 10749 10750 if (data) 10751 res = ast_say_character_str(chan, data, "", chan->language); 10752 return res; 10753 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10737 of file pbx.c.
References ast_say_digit_str().
10738 { 10739 int res = 0; 10740 10741 if (data) 10742 res = ast_say_digit_str(chan, data, "", chan->language); 10743 return res; 10744 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10709 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), and LOG_WARNING.
10710 { 10711 char tmp[256]; 10712 char *number = tmp; 10713 char *options; 10714 10715 if (ast_strlen_zero(data)) { 10716 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 10717 return -1; 10718 } 10719 ast_copy_string(tmp, data, sizeof(tmp)); 10720 strsep(&number, ","); 10721 options = strsep(&number, ","); 10722 if (options) { 10723 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 10724 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 10725 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 10726 return -1; 10727 } 10728 } 10729 10730 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 10731 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 10732 } 10733 10734 return 0; 10735 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10755 of file pbx.c.
References ast_say_phonetic_str().
10756 { 10757 int res = 0; 10758 10759 if (data) 10760 res = ast_say_phonetic_str(chan, data, "", chan->language); 10761 return res; 10762 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
struct ast_str ** | buf | |||
) |
Create a human-readable string, specifying all variables and their corresponding values.
chan | Channel from which to read variables | |
buf | Dynamic string in which to place the result (should be allocated with ast_str_create). |
Definition at line 10398 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
10399 { 10400 struct ast_var_t *variables; 10401 const char *var, *val; 10402 int total = 0; 10403 10404 if (!chan) 10405 return 0; 10406 10407 ast_str_reset(*buf); 10408 10409 ast_channel_lock(chan); 10410 10411 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10412 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10413 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10414 ) { 10415 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10416 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10417 break; 10418 } else 10419 total++; 10420 } else 10421 break; 10422 } 10423 10424 ast_channel_unlock(chan); 10425 10426 return total; 10427 }
int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 10557 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), and value.
Referenced by ast_compile_ael2().
10558 { 10559 char *name, *value, *mydata; 10560 10561 if (ast_compat_app_set) { 10562 return pbx_builtin_setvar_multiple(chan, data); 10563 } 10564 10565 if (ast_strlen_zero(data)) { 10566 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10567 return 0; 10568 } 10569 10570 mydata = ast_strdupa(data); 10571 name = strsep(&mydata, "="); 10572 value = mydata; 10573 if (!value) { 10574 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10575 return 0; 10576 } 10577 10578 if (strchr(name, ' ')) { 10579 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10580 } 10581 10582 pbx_builtin_setvar_helper(chan, name, value); 10583 10584 return 0; 10585 }
int pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Add a variable to the channel variable stack, removing the most recently set value for the same name.
Definition at line 10500 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), gosub_run(), handle_gosub(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_call_full(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), ring_entry(), rollback_exec(), rotate_file(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
10501 { 10502 struct ast_var_t *newvariable; 10503 struct varshead *headp; 10504 const char *nametail = name; 10505 10506 if (name[strlen(name) - 1] == ')') { 10507 char *function = ast_strdupa(name); 10508 10509 return ast_func_write(chan, function, value); 10510 } 10511 10512 if (chan) { 10513 ast_channel_lock(chan); 10514 headp = &chan->varshead; 10515 } else { 10516 ast_rwlock_wrlock(&globalslock); 10517 headp = &globals; 10518 } 10519 10520 /* For comparison purposes, we have to strip leading underscores */ 10521 if (*nametail == '_') { 10522 nametail++; 10523 if (*nametail == '_') 10524 nametail++; 10525 } 10526 10527 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10528 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10529 /* there is already such a variable, delete it */ 10530 AST_LIST_REMOVE_CURRENT(entries); 10531 ast_var_delete(newvariable); 10532 break; 10533 } 10534 } 10535 AST_LIST_TRAVERSE_SAFE_END; 10536 10537 if (value && (newvariable = ast_var_assign(name, value))) { 10538 if (headp == &globals) 10539 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10540 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10541 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10542 "Channel: %s\r\n" 10543 "Variable: %s\r\n" 10544 "Value: %s\r\n" 10545 "Uniqueid: %s\r\n", 10546 chan ? chan->name : "none", name, value, 10547 chan ? chan->uniqueid : "none"); 10548 } 10549 10550 if (chan) 10551 ast_channel_unlock(chan); 10552 else 10553 ast_rwlock_unlock(&globalslock); 10554 return 0; 10555 }
int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
Definition at line 10587 of file pbx.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
10588 { 10589 char *data; 10590 int x; 10591 AST_DECLARE_APP_ARGS(args, 10592 AST_APP_ARG(pair)[24]; 10593 ); 10594 AST_DECLARE_APP_ARGS(pair, 10595 AST_APP_ARG(name); 10596 AST_APP_ARG(value); 10597 ); 10598 10599 if (ast_strlen_zero(vdata)) { 10600 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10601 return 0; 10602 } 10603 10604 data = ast_strdupa(vdata); 10605 AST_STANDARD_APP_ARGS(args, data); 10606 10607 for (x = 0; x < args.argc; x++) { 10608 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10609 if (pair.argc == 2) { 10610 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10611 if (strchr(pair.name, ' ')) 10612 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); 10613 } else if (!chan) { 10614 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10615 } else { 10616 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10617 } 10618 } 10619 10620 return 0; 10621 }
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 10673 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), pbx_builtin_gotoif(), and testtime_write().
10674 { 10675 int res; 10676 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10677 return 0; 10678 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10679 return res; 10680 } else { /* Strings are true */ 10681 return 1; 10682 } 10683 }
static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 1527 of file pbx.c.
References ast_free.
Referenced by __ast_pbx_run().
01528 { 01529 ast_free(p); 01530 }
int pbx_exec | ( | struct ast_channel * | c, | |
struct ast_app * | app, | |||
const char * | data | |||
) |
Execute an application.
c | channel to execute on | |
app | which app to execute | |
data | the data passed into the app |
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.
0 | success | |
-1 | failure |
c | Channel | |
app | Application | |
data | Data for execution |
Definition at line 1451 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_exec_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01454 { 01455 int res; 01456 struct ast_module_user *u = NULL; 01457 const char *saved_c_appl; 01458 const char *saved_c_data; 01459 01460 if (c->cdr && !ast_check_hangup(c)) 01461 ast_cdr_setapp(c->cdr, app->name, data); 01462 01463 /* save channel values */ 01464 saved_c_appl= c->appl; 01465 saved_c_data= c->data; 01466 01467 c->appl = app->name; 01468 c->data = data; 01469 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01470 01471 if (app->module) 01472 u = __ast_module_user_add(app->module, c); 01473 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01474 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01475 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01476 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01477 app->name, (char *) data); 01478 } 01479 res = app->execute(c, S_OR(data, "")); 01480 if (app->module && u) 01481 __ast_module_user_remove(app->module, u); 01482 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01483 /* restore channel values */ 01484 c->appl = saved_c_appl; 01485 c->data = saved_c_data; 01486 return res; 01487 }
static int pbx_extension_helper | ( | struct ast_channel * | c, | |
struct ast_context * | con, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
enum ext_match_t | action, | |||
int * | found, | |||
int | combined_find_spawn | |||
) | [static] |
The return value depends on the action:.
E_MATCH, E_CANMATCH, E_MATCHMORE require a real match, and return 0 on failure, -1 on match; E_FINDLABEL maps the label to a priority, and returns the priority on success, ... XXX E_SPAWN, spawn an application,
0 | on success. | |
-1 | on failure. |
Definition at line 4660 of file pbx.c.
References ast_exten::app, app, ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_strdupa, ast_strlen_zero(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, ast_exten::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_DIALPLAN, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, manager_event, ast_switch::name, ast_app::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables_helper(), ast_channel::priority, ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), and VERBOSITY_ATLEAST.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
04663 { 04664 struct ast_exten *e; 04665 struct ast_app *app; 04666 char *substitute = NULL; 04667 int res; 04668 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04669 char passdata[EXT_DATA_SIZE]; 04670 04671 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04672 04673 ast_rdlock_contexts(); 04674 if (found) 04675 *found = 0; 04676 04677 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04678 if (e) { 04679 if (found) 04680 *found = 1; 04681 if (matching_action) { 04682 ast_unlock_contexts(); 04683 return -1; /* success, we found it */ 04684 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04685 res = e->priority; 04686 ast_unlock_contexts(); 04687 return res; /* the priority we were looking for */ 04688 } else { /* spawn */ 04689 if (!e->cached_app) 04690 e->cached_app = pbx_findapp(e->app); 04691 app = e->cached_app; 04692 if (ast_strlen_zero(e->data)) { 04693 *passdata = '\0'; 04694 } else { 04695 const char *tmp; 04696 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 04697 /* no variables to substitute, copy on through */ 04698 ast_copy_string(passdata, e->data, sizeof(passdata)); 04699 } else { 04700 /* save e->data on stack for later processing after lock released */ 04701 substitute = ast_strdupa(e->data); 04702 } 04703 } 04704 ast_unlock_contexts(); 04705 if (!app) { 04706 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04707 return -1; 04708 } 04709 if (c->context != context) 04710 ast_copy_string(c->context, context, sizeof(c->context)); 04711 if (c->exten != exten) 04712 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04713 c->priority = priority; 04714 if (substitute) { 04715 pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1); 04716 } 04717 #ifdef CHANNEL_TRACE 04718 ast_channel_trace_update(c); 04719 #endif 04720 ast_debug(1, "Launching '%s'\n", app->name); 04721 if (VERBOSITY_ATLEAST(3)) { 04722 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04723 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04724 exten, context, priority, 04725 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04726 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04727 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04728 "in new stack"); 04729 } 04730 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04731 "Channel: %s\r\n" 04732 "Context: %s\r\n" 04733 "Extension: %s\r\n" 04734 "Priority: %d\r\n" 04735 "Application: %s\r\n" 04736 "AppData: %s\r\n" 04737 "Uniqueid: %s\r\n", 04738 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 04739 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04740 } 04741 } else if (q.swo) { /* not found here, but in another switch */ 04742 if (found) 04743 *found = 1; 04744 ast_unlock_contexts(); 04745 if (matching_action) { 04746 return -1; 04747 } else { 04748 if (!q.swo->exec) { 04749 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04750 res = -1; 04751 } 04752 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04753 } 04754 } else { /* not found anywhere, see what happened */ 04755 ast_unlock_contexts(); 04756 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04757 switch (q.status) { 04758 case STATUS_NO_CONTEXT: 04759 if (!matching_action && !combined_find_spawn) 04760 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04761 break; 04762 case STATUS_NO_EXTENSION: 04763 if (!matching_action && !combined_find_spawn) 04764 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04765 break; 04766 case STATUS_NO_PRIORITY: 04767 if (!matching_action && !combined_find_spawn) 04768 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04769 break; 04770 case STATUS_NO_LABEL: 04771 if (context && !combined_find_spawn) 04772 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04773 break; 04774 default: 04775 ast_debug(1, "Shouldn't happen!\n"); 04776 } 04777 04778 return (matching_action) ? 0 : -1; 04779 } 04780 }
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 2967 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().
02971 { 02972 int x, res; 02973 struct ast_context *tmp = NULL; 02974 struct ast_exten *e = NULL, *eroot = NULL; 02975 struct ast_include *i = NULL; 02976 struct ast_sw *sw = NULL; 02977 struct ast_exten pattern = {NULL, }; 02978 struct scoreboard score = {0, }; 02979 struct ast_str *tmpdata = NULL; 02980 02981 pattern.label = label; 02982 pattern.priority = priority; 02983 #ifdef NEED_DEBUG_HERE 02984 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02985 #endif 02986 02987 /* Initialize status if appropriate */ 02988 if (q->stacklen == 0) { 02989 q->status = STATUS_NO_CONTEXT; 02990 q->swo = NULL; 02991 q->data = NULL; 02992 q->foundcontext = NULL; 02993 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02994 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02995 return NULL; 02996 } 02997 02998 /* Check first to see if we've already been checked */ 02999 for (x = 0; x < q->stacklen; x++) { 03000 if (!strcasecmp(q->incstack[x], context)) 03001 return NULL; 03002 } 03003 03004 if (bypass) { /* bypass means we only look there */ 03005 tmp = bypass; 03006 } else { /* look in contexts */ 03007 tmp = find_context(context); 03008 if (!tmp) { 03009 return NULL; 03010 } 03011 } 03012 03013 if (q->status < STATUS_NO_EXTENSION) 03014 q->status = STATUS_NO_EXTENSION; 03015 03016 /* Do a search for matching extension */ 03017 03018 eroot = NULL; 03019 score.total_specificity = 0; 03020 score.exten = 0; 03021 score.total_length = 0; 03022 if (!tmp->pattern_tree && tmp->root_table) { 03023 create_match_char_tree(tmp); 03024 #ifdef NEED_DEBUG 03025 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 03026 log_match_char_tree(tmp->pattern_tree," "); 03027 #endif 03028 } 03029 #ifdef NEED_DEBUG 03030 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03031 log_match_char_tree(tmp->pattern_tree, ":: "); 03032 #endif 03033 03034 do { 03035 if (!ast_strlen_zero(overrideswitch)) { 03036 char *osw = ast_strdupa(overrideswitch), *name; 03037 struct ast_switch *asw; 03038 ast_switch_f *aswf = NULL; 03039 char *datap; 03040 int eval = 0; 03041 03042 name = strsep(&osw, "/"); 03043 asw = pbx_findswitch(name); 03044 03045 if (!asw) { 03046 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03047 break; 03048 } 03049 03050 if (osw && strchr(osw, '$')) { 03051 eval = 1; 03052 } 03053 03054 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03055 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03056 break; 03057 } else if (eval) { 03058 /* Substitute variables now */ 03059 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03060 datap = ast_str_buffer(tmpdata); 03061 } else { 03062 datap = osw; 03063 } 03064 03065 /* equivalent of extension_match_core() at the switch level */ 03066 if (action == E_CANMATCH) 03067 aswf = asw->canmatch; 03068 else if (action == E_MATCHMORE) 03069 aswf = asw->matchmore; 03070 else /* action == E_MATCH */ 03071 aswf = asw->exists; 03072 if (!aswf) { 03073 res = 0; 03074 } else { 03075 if (chan) { 03076 ast_autoservice_start(chan); 03077 } 03078 res = aswf(chan, context, exten, priority, callerid, datap); 03079 if (chan) { 03080 ast_autoservice_stop(chan); 03081 } 03082 } 03083 if (res) { /* Got a match */ 03084 q->swo = asw; 03085 q->data = datap; 03086 q->foundcontext = context; 03087 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03088 return NULL; 03089 } 03090 } 03091 } while (0); 03092 03093 if (extenpatternmatchnew) { 03094 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03095 eroot = score.exten; 03096 03097 if (score.last_char == '!' && action == E_MATCHMORE) { 03098 /* We match an extension ending in '!'. 03099 * The decision in this case is final and is NULL (no match). 03100 */ 03101 #ifdef NEED_DEBUG_HERE 03102 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03103 #endif 03104 return NULL; 03105 } 03106 03107 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03108 q->status = STATUS_SUCCESS; 03109 #ifdef NEED_DEBUG_HERE 03110 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03111 #endif 03112 return score.canmatch_exten; 03113 } 03114 03115 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03116 if (score.node) { 03117 struct ast_exten *z = trie_find_next_match(score.node); 03118 if (z) { 03119 #ifdef NEED_DEBUG_HERE 03120 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03121 #endif 03122 } else { 03123 if (score.canmatch_exten) { 03124 #ifdef NEED_DEBUG_HERE 03125 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03126 #endif 03127 return score.canmatch_exten; 03128 } else { 03129 #ifdef NEED_DEBUG_HERE 03130 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03131 #endif 03132 } 03133 } 03134 return z; 03135 } 03136 #ifdef NEED_DEBUG_HERE 03137 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03138 #endif 03139 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03140 } 03141 03142 if (eroot) { 03143 /* found entry, now look for the right priority */ 03144 if (q->status < STATUS_NO_PRIORITY) 03145 q->status = STATUS_NO_PRIORITY; 03146 e = NULL; 03147 if (action == E_FINDLABEL && label ) { 03148 if (q->status < STATUS_NO_LABEL) 03149 q->status = STATUS_NO_LABEL; 03150 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03151 } else { 03152 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03153 } 03154 if (e) { /* found a valid match */ 03155 q->status = STATUS_SUCCESS; 03156 q->foundcontext = context; 03157 #ifdef NEED_DEBUG_HERE 03158 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03159 #endif 03160 return e; 03161 } 03162 } 03163 } else { /* the old/current default exten pattern match algorithm */ 03164 03165 /* scan the list trying to match extension and CID */ 03166 eroot = NULL; 03167 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03168 int match = extension_match_core(eroot->exten, exten, action); 03169 /* 0 on fail, 1 on match, 2 on earlymatch */ 03170 03171 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03172 continue; /* keep trying */ 03173 if (match == 2 && action == E_MATCHMORE) { 03174 /* We match an extension ending in '!'. 03175 * The decision in this case is final and is NULL (no match). 03176 */ 03177 return NULL; 03178 } 03179 /* found entry, now look for the right priority */ 03180 if (q->status < STATUS_NO_PRIORITY) 03181 q->status = STATUS_NO_PRIORITY; 03182 e = NULL; 03183 if (action == E_FINDLABEL && label ) { 03184 if (q->status < STATUS_NO_LABEL) 03185 q->status = STATUS_NO_LABEL; 03186 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03187 } else { 03188 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03189 } 03190 if (e) { /* found a valid match */ 03191 q->status = STATUS_SUCCESS; 03192 q->foundcontext = context; 03193 return e; 03194 } 03195 } 03196 } 03197 03198 /* Check alternative switches */ 03199 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03200 struct ast_switch *asw = pbx_findswitch(sw->name); 03201 ast_switch_f *aswf = NULL; 03202 char *datap; 03203 03204 if (!asw) { 03205 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03206 continue; 03207 } 03208 03209 /* Substitute variables now */ 03210 if (sw->eval) { 03211 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03212 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03213 continue; 03214 } 03215 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03216 } 03217 03218 /* equivalent of extension_match_core() at the switch level */ 03219 if (action == E_CANMATCH) 03220 aswf = asw->canmatch; 03221 else if (action == E_MATCHMORE) 03222 aswf = asw->matchmore; 03223 else /* action == E_MATCH */ 03224 aswf = asw->exists; 03225 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03226 if (!aswf) 03227 res = 0; 03228 else { 03229 if (chan) 03230 ast_autoservice_start(chan); 03231 res = aswf(chan, context, exten, priority, callerid, datap); 03232 if (chan) 03233 ast_autoservice_stop(chan); 03234 } 03235 if (res) { /* Got a match */ 03236 q->swo = asw; 03237 q->data = datap; 03238 q->foundcontext = context; 03239 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03240 return NULL; 03241 } 03242 } 03243 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03244 /* Now try any includes we have in this context */ 03245 for (i = tmp->includes; i; i = i->next) { 03246 if (include_valid(i)) { 03247 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03248 #ifdef NEED_DEBUG_HERE 03249 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03250 #endif 03251 return e; 03252 } 03253 if (q->swo) 03254 return NULL; 03255 } 03256 } 03257 return NULL; 03258 }
struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 1491 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_exec_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01492 { 01493 struct ast_app *tmp; 01494 01495 AST_RWLIST_RDLOCK(&apps); 01496 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01497 if (!strcasecmp(tmp->name, app)) 01498 break; 01499 } 01500 AST_RWLIST_UNLOCK(&apps); 01501 01502 return tmp; 01503 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 1505 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
01506 { 01507 struct ast_switch *asw; 01508 01509 AST_RWLIST_RDLOCK(&switches); 01510 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01511 if (!strcasecmp(asw->name, sw)) 01512 break; 01513 } 01514 AST_RWLIST_UNLOCK(&switches); 01515 01516 return asw; 01517 }
void pbx_live_dangerously | ( | int | new_live_dangerously | ) |
Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).
These dialplan functions (such as SHELL
) provide an opportunity for privilege escalation. They are okay to invoke from the dialplan, but external protocols with permission controls should not normally invoke them.
This function can globally enable/disable the execution of dangerous functions from external protocols.
new_live_dangerously | If true, enable the execution of escalating functions from external protocols. |
Definition at line 4013 of file pbx.c.
References ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by ast_readconfig().
04014 { 04015 if (new_live_dangerously && !live_dangerously) { 04016 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n" 04017 "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n"); 04018 } 04019 04020 if (!new_live_dangerously && live_dangerously) { 04021 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n"); 04022 } 04023 live_dangerously = new_live_dangerously; 04024 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 11130 of file pbx.c.
References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_party_id::number, ast_channel::priority, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
11131 { 11132 char *exten, *pri, *context; 11133 char *stringp; 11134 int ipri; 11135 int mode = 0; 11136 11137 if (ast_strlen_zero(goto_string)) { 11138 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 11139 return -1; 11140 } 11141 stringp = ast_strdupa(goto_string); 11142 context = strsep(&stringp, ","); /* guaranteed non-null */ 11143 exten = strsep(&stringp, ","); 11144 pri = strsep(&stringp, ","); 11145 if (!exten) { /* Only a priority in this one */ 11146 pri = context; 11147 exten = NULL; 11148 context = NULL; 11149 } else if (!pri) { /* Only an extension and priority in this one */ 11150 pri = exten; 11151 exten = context; 11152 context = NULL; 11153 } 11154 if (*pri == '+') { 11155 mode = 1; 11156 pri++; 11157 } else if (*pri == '-') { 11158 mode = -1; 11159 pri++; 11160 } 11161 if (sscanf(pri, "%30d", &ipri) != 1) { 11162 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 11163 exten ? exten : chan->exten, pri, 11164 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 11165 if (ipri < 1) { 11166 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 11167 return -1; 11168 } else 11169 mode = 0; 11170 } 11171 /* At this point we have a priority and maybe an extension and a context */ 11172 11173 if (mode) 11174 ipri = chan->priority + (ipri * mode); 11175 11176 if (async) 11177 ast_async_goto(chan, context, exten, ipri); 11178 else 11179 ast_explicit_goto(chan, context, exten, ipri); 11180 11181 return 0; 11182 11183 }
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 3388 of file pbx.c.
References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_retrieve_variable(), and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03389 { 03390 struct ast_str *str = ast_str_create(16); 03391 const char *cret; 03392 03393 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03394 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03395 *ret = cret ? workspace : NULL; 03396 ast_free(str); 03397 }
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 5895 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05896 { 05897 int oldval = autofallthrough; 05898 autofallthrough = newval; 05899 return oldval; 05900 }
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 5902 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05903 { 05904 int oldval = extenpatternmatchnew; 05905 extenpatternmatchnew = newval; 05906 return oldval; 05907 }
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 5909 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05910 { 05911 if (overrideswitch) { 05912 ast_free(overrideswitch); 05913 } 05914 if (!ast_strlen_zero(newval)) { 05915 overrideswitch = ast_strdup(newval); 05916 } else { 05917 overrideswitch = NULL; 05918 } 05919 }
static void pbx_shutdown | ( | void | ) | [static] |
Definition at line 11250 of file pbx.c.
References ao2_ref, ast_hashtab_destroy(), contexts_table, hints, pbx_builtin_clear_globals(), and statecbs.
Referenced by ast_pbx_init().
11251 { 11252 if (hints) { 11253 ao2_ref(hints, -1); 11254 hints = NULL; 11255 } 11256 if (statecbs) { 11257 ao2_ref(statecbs, -1); 11258 statecbs = NULL; 11259 } 11260 if (contexts_table) { 11261 ast_hashtab_destroy(contexts_table, NULL); 11262 } 11263 pbx_builtin_clear_globals(); 11264 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4630 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_extension_helper(), pbx_find_extension(), pbx_load_config(), realtime_exec(), rotate_file(), substituted(), try_calling(), and write_cdr().
04631 { 04632 size_t used; 04633 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04634 }
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 4434 of file pbx.c.
References ast_alloca, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
04435 { 04436 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04437 char *cp4 = NULL; 04438 const char *tmp, *whereweare, *orig_cp2 = cp2; 04439 int length, offset, offset2, isfunction; 04440 char *workspace = NULL; 04441 char *ltmp = NULL, *var = NULL; 04442 char *nextvar, *nextexp, *nextthing; 04443 char *vars, *vare; 04444 int pos, brackets, needsub, len; 04445 04446 *cp2 = 0; /* just in case nothing ends up there */ 04447 whereweare=tmp=cp1; 04448 while (!ast_strlen_zero(whereweare) && count) { 04449 /* Assume we're copying the whole remaining string */ 04450 pos = strlen(whereweare); 04451 nextvar = NULL; 04452 nextexp = NULL; 04453 nextthing = strchr(whereweare, '$'); 04454 if (nextthing) { 04455 switch (nextthing[1]) { 04456 case '{': 04457 nextvar = nextthing; 04458 pos = nextvar - whereweare; 04459 break; 04460 case '[': 04461 nextexp = nextthing; 04462 pos = nextexp - whereweare; 04463 break; 04464 default: 04465 pos = 1; 04466 } 04467 } 04468 04469 if (pos) { 04470 /* Can't copy more than 'count' bytes */ 04471 if (pos > count) 04472 pos = count; 04473 04474 /* Copy that many bytes */ 04475 memcpy(cp2, whereweare, pos); 04476 04477 count -= pos; 04478 cp2 += pos; 04479 whereweare += pos; 04480 *cp2 = 0; 04481 } 04482 04483 if (nextvar) { 04484 /* We have a variable. Find the start and end, and determine 04485 if we are going to have to recursively call ourselves on the 04486 contents */ 04487 vars = vare = nextvar + 2; 04488 brackets = 1; 04489 needsub = 0; 04490 04491 /* Find the end of it */ 04492 while (brackets && *vare) { 04493 if ((vare[0] == '$') && (vare[1] == '{')) { 04494 needsub++; 04495 } else if (vare[0] == '{') { 04496 brackets++; 04497 } else if (vare[0] == '}') { 04498 brackets--; 04499 } else if ((vare[0] == '$') && (vare[1] == '[')) 04500 needsub++; 04501 vare++; 04502 } 04503 if (brackets) 04504 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04505 len = vare - vars - 1; 04506 04507 /* Skip totally over variable string */ 04508 whereweare += (len + 3); 04509 04510 if (!var) 04511 var = ast_alloca(VAR_BUF_SIZE); 04512 04513 /* Store variable name (and truncate) */ 04514 ast_copy_string(var, vars, len + 1); 04515 04516 /* Substitute if necessary */ 04517 if (needsub) { 04518 size_t used; 04519 if (!ltmp) 04520 ltmp = ast_alloca(VAR_BUF_SIZE); 04521 04522 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04523 vars = ltmp; 04524 } else { 04525 vars = var; 04526 } 04527 04528 if (!workspace) 04529 workspace = ast_alloca(VAR_BUF_SIZE); 04530 04531 workspace[0] = '\0'; 04532 04533 parse_variable_name(vars, &offset, &offset2, &isfunction); 04534 if (isfunction) { 04535 /* Evaluate function */ 04536 if (c || !headp) 04537 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04538 else { 04539 struct varshead old; 04540 struct ast_channel *c = ast_dummy_channel_alloc(); 04541 if (c) { 04542 memcpy(&old, &c->varshead, sizeof(old)); 04543 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04544 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04545 /* Don't deallocate the varshead that was passed in */ 04546 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04547 c = ast_channel_unref(c); 04548 } else { 04549 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04550 } 04551 } 04552 ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)"); 04553 } else { 04554 /* Retrieve variable value */ 04555 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04556 } 04557 if (cp4) { 04558 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04559 04560 length = strlen(cp4); 04561 if (length > count) 04562 length = count; 04563 memcpy(cp2, cp4, length); 04564 count -= length; 04565 cp2 += length; 04566 *cp2 = 0; 04567 } 04568 } else if (nextexp) { 04569 /* We have an expression. Find the start and end, and determine 04570 if we are going to have to recursively call ourselves on the 04571 contents */ 04572 vars = vare = nextexp + 2; 04573 brackets = 1; 04574 needsub = 0; 04575 04576 /* Find the end of it */ 04577 while (brackets && *vare) { 04578 if ((vare[0] == '$') && (vare[1] == '[')) { 04579 needsub++; 04580 brackets++; 04581 vare++; 04582 } else if (vare[0] == '[') { 04583 brackets++; 04584 } else if (vare[0] == ']') { 04585 brackets--; 04586 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04587 needsub++; 04588 vare++; 04589 } 04590 vare++; 04591 } 04592 if (brackets) 04593 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04594 len = vare - vars - 1; 04595 04596 /* Skip totally over expression */ 04597 whereweare += (len + 3); 04598 04599 if (!var) 04600 var = ast_alloca(VAR_BUF_SIZE); 04601 04602 /* Store variable name (and truncate) */ 04603 ast_copy_string(var, vars, len + 1); 04604 04605 /* Substitute if necessary */ 04606 if (needsub) { 04607 size_t used; 04608 if (!ltmp) 04609 ltmp = ast_alloca(VAR_BUF_SIZE); 04610 04611 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04612 vars = ltmp; 04613 } else { 04614 vars = var; 04615 } 04616 04617 length = ast_expr(vars, cp2, count, c); 04618 04619 if (length) { 04620 ast_debug(1, "Expression result is '%s'\n", cp2); 04621 count -= length; 04622 cp2 += length; 04623 *cp2 = 0; 04624 } 04625 } 04626 } 04627 *used = cp2 - orig_cp2; 04628 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4636 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04637 { 04638 size_t used; 04639 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04640 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5813 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05814 { 05815 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05816 answer this channel and get it going. 05817 */ 05818 /* NOTE: 05819 The launcher of this function _MUST_ increment 'countcalls' 05820 before invoking the function; it will be decremented when the 05821 PBX has finished running on the channel 05822 */ 05823 struct ast_channel *c = data; 05824 05825 __ast_pbx_run(c, NULL); 05826 decrease_call_count(); 05827 05828 pthread_exit(NULL); 05829 05830 return NULL; 05831 }
static void print_app_docs | ( | struct ast_app * | aa, | |
int | fd | |||
) | [static] |
Definition at line 6422 of file pbx.c.
References ast_app::arguments, ast_cli(), ast_free, ast_malloc, AST_MAX_APP, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), COLOR_CYAN, COLOR_MAGENTA, ast_app::description, ast_switch::description, ast_app::docsrc, ast_app::name, S_OR, ast_app::seealso, ast_app::synopsis, synopsis, ast_app::syntax, and term_color().
Referenced by handle_show_application().
06423 { 06424 /* Maximum number of characters added by terminal coloring is 22 */ 06425 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 06426 char seealsotitle[40]; 06427 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 06428 char *seealso = NULL; 06429 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 06430 06431 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 06432 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 06433 06434 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 06435 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 06436 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 06437 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 06438 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 06439 06440 #ifdef AST_XML_DOCS 06441 if (aa->docsrc == AST_XML_DOC) { 06442 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 06443 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 06444 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 06445 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 06446 06447 if (!synopsis || !description || !arguments || !seealso) { 06448 goto return_cleanup; 06449 } 06450 } else 06451 #endif 06452 { 06453 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06454 synopsis = ast_malloc(synopsis_size); 06455 06456 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06457 description = ast_malloc(description_size); 06458 06459 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06460 arguments = ast_malloc(arguments_size); 06461 06462 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06463 seealso = ast_malloc(seealso_size); 06464 06465 if (!synopsis || !description || !arguments || !seealso) { 06466 goto return_cleanup; 06467 } 06468 06469 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 06470 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 06471 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 06472 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 06473 } 06474 06475 /* Handle the syntax the same for both XML and raw docs */ 06476 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06477 if (!(syntax = ast_malloc(syntax_size))) { 06478 goto return_cleanup; 06479 } 06480 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 06481 06482 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 06483 infotitle, syntitle, synopsis, destitle, description, 06484 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 06485 06486 return_cleanup: 06487 ast_free(description); 06488 ast_free(arguments); 06489 ast_free(synopsis); 06490 ast_free(seealso); 06491 ast_free(syntax); 06492 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 6859 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().
06860 { 06861 int prio = ast_get_extension_priority(e); 06862 if (prio == PRIORITY_HINT) { 06863 snprintf(buf, buflen, "hint: %s", 06864 ast_get_extension_app(e)); 06865 } else { 06866 snprintf(buf, buflen, "%d. %s(%s)", 06867 prio, ast_get_extension_app(e), 06868 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06869 } 06870 }
static int raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason, | |||
int | priority | |||
) | [static] |
Definition at line 3548 of file pbx.c.
References ast_calloc_with_stringfields, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run(), pbx_builtin_raise_exception(), and pbx_builtin_waitexten().
03549 { 03550 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03551 struct pbx_exception *exception = NULL; 03552 03553 if (!ds) { 03554 ds = ast_datastore_alloc(&exception_store_info, NULL); 03555 if (!ds) 03556 return -1; 03557 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03558 ast_datastore_free(ds); 03559 return -1; 03560 } 03561 ds->data = exception; 03562 ast_channel_datastore_add(chan, ds); 03563 } else 03564 exception = ds->data; 03565 03566 ast_string_field_set(exception, reason, reason); 03567 ast_string_field_set(exception, context, chan->context); 03568 ast_string_field_set(exception, exten, chan->exten); 03569 exception->priority = chan->priority; 03570 set_ext_pri(chan, "e", priority); 03571 return 0; 03572 }
static int read_escalates | ( | const struct ast_custom_function * | acf | ) | [static] |
Returns true if given custom function escalates privileges on read.
acf | Custom function to query. |
Definition at line 3810 of file pbx.c.
References ast_custom_escalating_function::acf, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_escalating_function::read_escalates.
Referenced by is_read_allowed().
03810 { 03811 int res = 0; 03812 struct ast_custom_escalating_function *cur_escalation; 03813 03814 AST_RWLIST_RDLOCK(&escalation_root); 03815 AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) { 03816 if (cur_escalation->acf == acf) { 03817 res = cur_escalation->read_escalates; 03818 break; 03819 } 03820 } 03821 AST_RWLIST_UNLOCK(&escalation_root); 03822 return res; 03823 }
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 5385 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_channel::exten, and ast_channel::priority.
Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten(), pbx_builtin_waitexten(), and raise_exception().
05386 { 05387 ast_channel_lock(c); 05388 ast_copy_string(c->exten, exten, sizeof(c->exten)); 05389 c->priority = pri; 05390 ast_channel_unlock(c); 05391 }
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 7028 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().
07029 { 07030 struct ast_context *c = NULL; 07031 int res = 0, old_total_exten = dpc->total_exten; 07032 07033 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 07034 07035 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 07036 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 07037 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 07038 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 07039 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 07040 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 07041 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 07042 ast_rdlock_contexts(); 07043 07044 /* walk all contexts ... */ 07045 while ( (c = ast_walk_contexts(c)) ) { 07046 int context_info_printed = 0; 07047 07048 if (context && strcmp(ast_get_context_name(c), context)) 07049 continue; /* skip this one, name doesn't match */ 07050 07051 dpc->context_existence = 1; 07052 07053 if (!c->pattern_tree) { 07054 /* Ignore check_return warning from Coverity for ast_exists_extension below */ 07055 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 07056 } 07057 07058 ast_rdlock_context(c); 07059 07060 dpc->total_context++; 07061 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 07062 ast_get_context_name(c), ast_get_context_registrar(c)); 07063 context_info_printed = 1; 07064 07065 if (c->pattern_tree) 07066 { 07067 cli_match_char_tree(c->pattern_tree, " ", fd); 07068 } else { 07069 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 07070 } 07071 07072 ast_unlock_context(c); 07073 07074 /* if we print something in context, make an empty line */ 07075 if (context_info_printed) 07076 ast_cli(fd, "\n"); 07077 } 07078 ast_unlock_contexts(); 07079 07080 return (dpc->total_exten == old_total_exten) ? -1 : res; 07081 }
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 6873 of file pbx.c.
References ast_cli(), AST_EXT_MATCHCID_ON, ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
06874 { 06875 struct ast_context *c = NULL; 06876 int res = 0, old_total_exten = dpc->total_exten; 06877 06878 ast_rdlock_contexts(); 06879 06880 /* walk all contexts ... */ 06881 while ( (c = ast_walk_contexts(c)) ) { 06882 struct ast_exten *e; 06883 struct ast_include *i; 06884 struct ast_ignorepat *ip; 06885 #ifndef LOW_MEMORY 06886 char buf[1024], buf2[1024]; 06887 #else 06888 char buf[256], buf2[256]; 06889 #endif 06890 int context_info_printed = 0; 06891 06892 if (context && strcmp(ast_get_context_name(c), context)) 06893 continue; /* skip this one, name doesn't match */ 06894 06895 dpc->context_existence = 1; 06896 06897 ast_rdlock_context(c); 06898 06899 /* are we looking for exten too? if yes, we print context 06900 * only if we find our extension. 06901 * Otherwise print context even if empty ? 06902 * XXX i am not sure how the rinclude is handled. 06903 * I think it ought to go inside. 06904 */ 06905 if (!exten) { 06906 dpc->total_context++; 06907 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06908 ast_get_context_name(c), ast_get_context_registrar(c)); 06909 context_info_printed = 1; 06910 } 06911 06912 /* walk extensions ... */ 06913 e = NULL; 06914 while ( (e = ast_walk_context_extensions(c, e)) ) { 06915 struct ast_exten *p; 06916 06917 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06918 continue; /* skip, extension match failed */ 06919 06920 dpc->extension_existence = 1; 06921 06922 /* may we print context info? */ 06923 if (!context_info_printed) { 06924 dpc->total_context++; 06925 if (rinclude) { /* TODO Print more info about rinclude */ 06926 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06927 ast_get_context_name(c), ast_get_context_registrar(c)); 06928 } else { 06929 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06930 ast_get_context_name(c), ast_get_context_registrar(c)); 06931 } 06932 context_info_printed = 1; 06933 } 06934 dpc->total_prio++; 06935 06936 /* write extension name and first peer */ 06937 if (e->matchcid == AST_EXT_MATCHCID_ON) 06938 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06939 else 06940 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06941 06942 print_ext(e, buf2, sizeof(buf2)); 06943 06944 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06945 ast_get_extension_registrar(e)); 06946 06947 dpc->total_exten++; 06948 /* walk next extension peers */ 06949 p = e; /* skip the first one, we already got it */ 06950 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06951 const char *el = ast_get_extension_label(p); 06952 dpc->total_prio++; 06953 if (el) 06954 snprintf(buf, sizeof(buf), " [%s]", el); 06955 else 06956 buf[0] = '\0'; 06957 print_ext(p, buf2, sizeof(buf2)); 06958 06959 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 06960 ast_get_extension_registrar(p)); 06961 } 06962 } 06963 06964 /* walk included and write info ... */ 06965 i = NULL; 06966 while ( (i = ast_walk_context_includes(c, i)) ) { 06967 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 06968 if (exten) { 06969 /* Check all includes for the requested extension */ 06970 if (includecount >= AST_PBX_MAX_STACK) { 06971 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 06972 } else { 06973 int dupe = 0; 06974 int x; 06975 for (x = 0; x < includecount; x++) { 06976 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 06977 dupe++; 06978 break; 06979 } 06980 } 06981 if (!dupe) { 06982 includes[includecount] = ast_get_include_name(i); 06983 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 06984 } else { 06985 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 06986 } 06987 } 06988 } else { 06989 ast_cli(fd, " Include => %-45s [%s]\n", 06990 buf, ast_get_include_registrar(i)); 06991 } 06992 } 06993 06994 /* walk ignore patterns and write info ... */ 06995 ip = NULL; 06996 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06997 const char *ipname = ast_get_ignorepat_name(ip); 06998 char ignorepat[AST_MAX_EXTENSION]; 06999 snprintf(buf, sizeof(buf), "'%s'", ipname); 07000 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 07001 if (!exten || ast_extension_match(ignorepat, exten)) { 07002 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 07003 buf, ast_get_ignorepat_registrar(ip)); 07004 } 07005 } 07006 if (!rinclude) { 07007 struct ast_sw *sw = NULL; 07008 while ( (sw = ast_walk_context_switches(c, sw)) ) { 07009 snprintf(buf, sizeof(buf), "'%s/%s'", 07010 ast_get_switch_name(sw), 07011 ast_get_switch_data(sw)); 07012 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 07013 buf, ast_get_switch_registrar(sw)); 07014 } 07015 } 07016 07017 ast_unlock_context(c); 07018 07019 /* if we print something in context, make an empty line */ 07020 if (context_info_printed) 07021 ast_cli(fd, "\n"); 07022 } 07023 ast_unlock_contexts(); 07024 07025 return (dpc->total_exten == old_total_exten) ? -1 : res; 07026 }
static int statecbs_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11242 of file pbx.c.
References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
11243 { 11244 const struct ast_state_cb *state_cb = obj; 11245 ast_state_cb_type change_cb = arg; 11246 11247 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; 11248 }
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 3298 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
03299 { 03300 char *ret = workspace; 03301 int lr; /* length of the input string after the copy */ 03302 03303 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 03304 03305 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 03306 03307 /* Quick check if no need to do anything */ 03308 if (offset == 0 && length >= lr) /* take the whole string */ 03309 return ret; 03310 03311 if (offset < 0) { /* translate negative offset into positive ones */ 03312 offset = lr + offset; 03313 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03314 offset = 0; 03315 } 03316 03317 /* too large offset result in empty string so we know what to return */ 03318 if (offset >= lr) 03319 return ret + lr; /* the final '\0' */ 03320 03321 ret += offset; /* move to the start position */ 03322 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 03323 ret[length] = '\0'; 03324 else if (length < 0) { 03325 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 03326 ret[lr + length - offset] = '\0'; 03327 else 03328 ret[0] = '\0'; 03329 } 03330 03331 return ret; 03332 }
static int thread_inhibits_escalations | ( | void | ) | [static] |
Indicates whether the current thread inhibits the execution of dangerous functions.
Definition at line 4049 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by is_read_allowed(), and is_write_allowed().
04050 { 04051 int *thread_inhibit_escalations; 04052 04053 thread_inhibit_escalations = ast_threadstorage_get( 04054 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04055 04056 if (thread_inhibit_escalations == NULL) { 04057 ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n"); 04058 /* On error, assume that we are inhibiting */ 04059 return 1; 04060 } 04061 04062 return *thread_inhibit_escalations; 04063 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1702 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().
01703 { 01704 struct match_char *m3; 01705 struct match_char *m4; 01706 struct ast_exten *e3; 01707 01708 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01709 return node->exten; 01710 } 01711 01712 if (node && node->x[0] == '!' && !node->x[1]) { 01713 return node->exten; 01714 } 01715 01716 if (!node || !node->next_char) { 01717 return NULL; 01718 } 01719 01720 m3 = node->next_char; 01721 01722 if (m3->exten) { 01723 return m3->exten; 01724 } 01725 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01726 if (m4->exten) { 01727 return m4->exten; 01728 } 01729 } 01730 for (m4 = m3; m4; m4 = m4->alt_char) { 01731 e3 = trie_find_next_match(m3); 01732 if (e3) { 01733 return e3; 01734 } 01735 } 01736 01737 return NULL; 01738 }
static void unload_pbx | ( | void | ) | [static] |
Definition at line 10832 of file pbx.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_event_unsubscribe(), ast_manager_unregister(), ast_taskprocessor_unreference(), ast_unregister_application(), builtins, device_state_sub, exception_function, pbx_cli, and testtime_function.
Referenced by load_pbx().
10833 { 10834 int x; 10835 10836 if (device_state_sub) { 10837 device_state_sub = ast_event_unsubscribe(device_state_sub); 10838 } 10839 if (device_state_tps) { 10840 ast_taskprocessor_unreference(device_state_tps); 10841 device_state_tps = NULL; 10842 } 10843 10844 /* Unregister builtin applications */ 10845 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10846 ast_unregister_application(builtins[x].name); 10847 } 10848 ast_manager_unregister("ShowDialPlan"); 10849 ast_cli_unregister_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10850 ast_custom_function_unregister(&exception_function); 10851 ast_custom_function_unregister(&testtime_function); 10852 ast_data_unregister(NULL); 10853 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 7640 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().
07641 { 07642 struct ast_context *context = NULL; 07643 struct ast_exten *eroot = NULL, *e = NULL; 07644 07645 ast_rdlock_contexts(); 07646 while ((context = ast_walk_contexts(context))) { 07647 while ((eroot = ast_walk_context_extensions(context, eroot))) { 07648 while ((e = ast_walk_extension_priorities(eroot, e))) { 07649 if (e->cached_app == app) 07650 e->cached_app = NULL; 07651 } 07652 } 07653 } 07654 ast_unlock_contexts(); 07655 07656 return; 07657 }
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 1606 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().
01607 { 01608 /* if this extension is marked as deleted, then skip this -- if it never shows 01609 on the scoreboard, it will never be found, nor will halt the traversal. */ 01610 if (deleted) 01611 return; 01612 board->total_specificity = spec; 01613 board->total_length = length; 01614 board->exten = exten; 01615 board->last_char = last; 01616 board->node = node; 01617 #ifdef NEED_DEBUG_HERE 01618 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01619 #endif 01620 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
const void * | data | |||
) | [static] |
Definition at line 9836 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().
09837 { 09838 int res; 09839 struct ast_frame *f; 09840 double waitsec; 09841 int waittime; 09842 09843 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 09844 waitsec = -1; 09845 if (waitsec > -1) { 09846 waittime = waitsec * 1000.0; 09847 ast_safe_sleep(chan, waittime); 09848 } else do { 09849 res = ast_waitfor(chan, -1); 09850 if (res < 0) 09851 return; 09852 f = ast_read(chan); 09853 if (f) 09854 ast_frfree(f); 09855 } while(f); 09856 }
static int write_escalates | ( | const struct ast_custom_function * | acf | ) | [static] |
Returns true if given custom function escalates privileges on write.
acf | Custom function to query. |
Definition at line 3832 of file pbx.c.
References ast_custom_escalating_function::acf, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_escalating_function::write_escalates.
Referenced by is_write_allowed().
03832 { 03833 int res = 0; 03834 struct ast_custom_escalating_function *cur_escalation; 03835 03836 AST_RWLIST_RDLOCK(&escalation_root); 03837 AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) { 03838 if (cur_escalation->acf == acf) { 03839 res = cur_escalation->write_escalates; 03840 break; 03841 } 03842 } 03843 AST_RWLIST_UNLOCK(&escalation_root); 03844 return res; 03845 }
int autofallthrough = 1 [static] |
Definition at line 1176 of file pbx.c.
Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().
struct ast_app_option background_opts[128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} [static] |
Definition at line 807 of file pbx.c.
Referenced by pbx_builtin_background().
struct pbx_builtin builtins[] [static] |
Declaration of builtin applications.
Referenced by load_pbx(), and unload_pbx().
ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock for the ast_context list.
Definition at line 1248 of file pbx.c.
Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().
ast_mutex_t context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition at line 1253 of file pbx.c.
Referenced by ast_merge_contexts_and_delete(), and handle_statechange().
struct ast_context* contexts [static] |
Definition at line 1239 of file pbx.c.
Referenced by __ast_context_destroy(), ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and ast_walk_contexts().
struct ast_hashtab* contexts_table = NULL [static] |
Definition at line 1240 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), find_context(), find_context_locked(), and pbx_shutdown().
int countcalls [static] |
Definition at line 1184 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
const char* const days[] [static] |
Definition at line 8239 of file pbx.c.
Referenced by ast_build_timing().
struct ast_event_sub* device_state_sub [static] |
Subscription for device state change events.
Definition at line 1181 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
{ .name = "EXCEPTION", .read = acf_exception_read, }
Definition at line 3600 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_datastore_info exception_store_info [static] |
{ .type = "EXCEPTION", .destroy = exception_store_free, }
Definition at line 3532 of file pbx.c.
Referenced by acf_exception_read(), and raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1177 of file pbx.c.
Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } [static] |
Definition at line 823 of file pbx.c.
Referenced by ast_extension_state2().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
Definition at line 1174 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [static] |
Definition at line 1173 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
struct ao2_container* hints [static] |
Definition at line 1268 of file pbx.c.
Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add_destroy(), ast_extension_state_del(), ast_merge_contexts_and_delete(), ast_pbx_init(), ast_remove_hint(), complete_core_show_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), and pbx_shutdown().
struct ast_data_handler hints_data_provider [static] |
{ .version = AST_DATA_HANDLER_VERSION, .get = hints_data_provider_get }
int live_dangerously [static] |
Set to true (non-zero) to globally allow all dangerous dialplan functions to run.
Definition at line 828 of file pbx.c.
Referenced by ast_readconfig().
ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 1183 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
const char* const months[] [static] |
Definition at line 8251 of file pbx.c.
Referenced by ast_build_timing().
char* overrideswitch = NULL [static] |
Definition at line 1178 of file pbx.c.
Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().
struct ast_cli_entry pbx_cli[] [static] |
Definition at line 7619 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_data_entry pbx_data_providers[] [static] |
{ AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider), }
Definition at line 10826 of file pbx.c.
Referenced by load_pbx().
struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} [static] |
Definition at line 9977 of file pbx.c.
Referenced by pbx_builtin_resetcdr().
struct ao2_container* statecbs [static] |
Definition at line 1270 of file pbx.c.
Referenced by ast_extension_state_add_destroy(), ast_extension_state_del(), ast_pbx_init(), handle_statechange(), and pbx_shutdown().
int stateid = 1 [static] |
Definition at line 1259 of file pbx.c.
Referenced by ast_extension_state_add_destroy().
struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } [static] |
Definition at line 822 of file pbx.c.
Referenced by pbx_find_extension().
struct ast_custom_function testtime_function [static] |
{ .name = "TESTTIME", .write = testtime_write, }
Definition at line 10068 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_threadstorage thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , } [static] |
Definition at line 828 of file pbx.c.
Referenced by ast_thread_inhibit_escalations(), and thread_inhibits_escalations().
int totalcalls [static] |
Definition at line 1185 of file pbx.c.
Referenced by ast_processed_calls(), increase_call_count(), and timing_read().
struct ast_app_option waitexten_opts[128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} [static] |
Definition at line 815 of file pbx.c.
Referenced by pbx_builtin_waitexten().