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_saydate (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 *) |
static int | pbx_builtin_saytime (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 841 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_NOANSWER (1 << 1) |
Definition at line 840 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_PLAYBACK (1 << 3) |
Definition at line 842 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_SKIP (1 << 0) |
Definition at line 839 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 828 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
#define HASH_EXTENHINT_SIZE 563 |
Definition at line 1028 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 833 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 852 of file pbx.c.
Referenced by pbx_builtin_waitexten().
#define WAITEXTEN_MOH (1 << 0) |
Definition at line 851 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 9718 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().
09719 { 09720 struct ast_context *tmp, *tmpl=NULL; 09721 struct ast_exten *exten_item, *prio_item; 09722 09723 for (tmp = list; tmp; ) { 09724 struct ast_context *next = NULL; /* next starting point */ 09725 /* The following code used to skip forward to the next 09726 context with matching registrar, but this didn't 09727 make sense; individual priorities registrar'd to 09728 the matching registrar could occur in any context! */ 09729 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 09730 if (con) { 09731 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 09732 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 09733 if ( !strcasecmp(tmp->name, con->name) ) { 09734 break; /* found it */ 09735 } 09736 } 09737 } 09738 09739 if (!tmp) /* not found, we are done */ 09740 break; 09741 ast_wrlock_context(tmp); 09742 09743 if (registrar) { 09744 /* then search thru and remove any extens that match registrar. */ 09745 struct ast_hashtab_iter *exten_iter; 09746 struct ast_hashtab_iter *prio_iter; 09747 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 09748 struct ast_include *i, *pi = NULL, *ni = NULL; 09749 struct ast_sw *sw = NULL; 09750 09751 /* remove any ignorepats whose registrar matches */ 09752 for (ip = tmp->ignorepats; ip; ip = ipn) { 09753 ipn = ip->next; 09754 if (!strcmp(ip->registrar, registrar)) { 09755 if (ipl) { 09756 ipl->next = ip->next; 09757 ast_free(ip); 09758 continue; /* don't change ipl */ 09759 } else { 09760 tmp->ignorepats = ip->next; 09761 ast_free(ip); 09762 continue; /* don't change ipl */ 09763 } 09764 } 09765 ipl = ip; 09766 } 09767 /* remove any includes whose registrar matches */ 09768 for (i = tmp->includes; i; i = ni) { 09769 ni = i->next; 09770 if (strcmp(i->registrar, registrar) == 0) { 09771 /* remove from list */ 09772 if (pi) { 09773 pi->next = i->next; 09774 /* free include */ 09775 ast_free(i); 09776 continue; /* don't change pi */ 09777 } else { 09778 tmp->includes = i->next; 09779 /* free include */ 09780 ast_free(i); 09781 continue; /* don't change pi */ 09782 } 09783 } 09784 pi = i; 09785 } 09786 /* remove any switches whose registrar matches */ 09787 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 09788 if (strcmp(sw->registrar,registrar) == 0) { 09789 AST_LIST_REMOVE_CURRENT(list); 09790 ast_free(sw); 09791 } 09792 } 09793 AST_LIST_TRAVERSE_SAFE_END; 09794 09795 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 09796 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 09797 while ((exten_item=ast_hashtab_next(exten_iter))) { 09798 int end_traversal = 1; 09799 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 09800 while ((prio_item=ast_hashtab_next(prio_iter))) { 09801 char extension[AST_MAX_EXTENSION]; 09802 char cidmatch[AST_MAX_EXTENSION]; 09803 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 09804 continue; 09805 } 09806 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 09807 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 09808 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 09809 if (prio_item->cidmatch) { 09810 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 09811 } 09812 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1); 09813 } 09814 /* Explanation: 09815 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 09816 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 09817 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 09818 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 09819 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 09820 * free the iterator 09821 */ 09822 if (end_traversal) { 09823 ast_hashtab_end_traversal(prio_iter); 09824 } else { 09825 ast_free(prio_iter); 09826 } 09827 } 09828 ast_hashtab_end_traversal(exten_iter); 09829 } 09830 09831 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 09832 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 09833 another registrar. It's not empty if there are any extensions */ 09834 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 09835 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09836 ast_hashtab_remove_this_object(contexttab, tmp); 09837 09838 next = tmp->next; 09839 if (tmpl) 09840 tmpl->next = next; 09841 else 09842 contexts = next; 09843 /* Okay, now we're safe to let it go -- in a sense, we were 09844 ready to let it go as soon as we locked it. */ 09845 ast_unlock_context(tmp); 09846 __ast_internal_context_destroy(tmp); 09847 } else { 09848 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 09849 tmp->refcount, tmp->root); 09850 ast_unlock_context(tmp); 09851 next = tmp->next; 09852 tmpl = tmp; 09853 } 09854 } else if (con) { 09855 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 09856 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09857 ast_hashtab_remove_this_object(contexttab, tmp); 09858 09859 next = tmp->next; 09860 if (tmpl) 09861 tmpl->next = next; 09862 else 09863 contexts = next; 09864 /* Okay, now we're safe to let it go -- in a sense, we were 09865 ready to let it go as soon as we locked it. */ 09866 ast_unlock_context(tmp); 09867 __ast_internal_context_destroy(tmp); 09868 } 09869 09870 /* if we have a specific match, we are done, otherwise continue */ 09871 tmp = con ? NULL : next; 09872 } 09873 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3946 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().
03947 { 03948 struct ast_custom_function *cur; 03949 char tmps[80]; 03950 03951 if (!acf) { 03952 return -1; 03953 } 03954 03955 acf->mod = mod; 03956 #ifdef AST_XML_DOCS 03957 acf->docsrc = AST_STATIC_DOC; 03958 #endif 03959 03960 if (acf_retrieve_docs(acf)) { 03961 return -1; 03962 } 03963 03964 AST_RWLIST_WRLOCK(&acf_root); 03965 03966 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03967 if (!strcmp(acf->name, cur->name)) { 03968 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03969 AST_RWLIST_UNLOCK(&acf_root); 03970 return -1; 03971 } 03972 } 03973 03974 /* Store in alphabetical order */ 03975 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03976 if (strcasecmp(acf->name, cur->name) < 0) { 03977 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03978 break; 03979 } 03980 } 03981 AST_RWLIST_TRAVERSE_SAFE_END; 03982 03983 if (!cur) { 03984 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03985 } 03986 03987 AST_RWLIST_UNLOCK(&acf_root); 03988 03989 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03990 03991 return 0; 03992 }
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 3994 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.
03995 { 03996 struct ast_custom_escalating_function *acf_escalation = NULL; 03997 int res; 03998 03999 res = __ast_custom_function_register(acf, mod); 04000 if (res != 0) { 04001 return -1; 04002 } 04003 04004 if (escalation == AST_CFE_NONE) { 04005 /* No escalations; no need to do anything else */ 04006 return 0; 04007 } 04008 04009 acf_escalation = ast_calloc(1, sizeof(*acf_escalation)); 04010 if (!acf_escalation) { 04011 ast_custom_function_unregister(acf); 04012 return -1; 04013 } 04014 04015 acf_escalation->acf = acf; 04016 switch (escalation) { 04017 case AST_CFE_NONE: 04018 break; 04019 case AST_CFE_READ: 04020 acf_escalation->read_escalates = 1; 04021 break; 04022 case AST_CFE_WRITE: 04023 acf_escalation->write_escalates = 1; 04024 break; 04025 case AST_CFE_BOTH: 04026 acf_escalation->read_escalates = 1; 04027 acf_escalation->write_escalates = 1; 04028 break; 04029 } 04030 04031 AST_RWLIST_WRLOCK(&escalation_root); 04032 AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list); 04033 AST_RWLIST_UNLOCK(&escalation_root); 04034 04035 return 0; 04036 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 11240 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().
11241 { 11242 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 11243 11244 if (!chan) 11245 return -2; 11246 11247 if (context == NULL) 11248 context = chan->context; 11249 if (exten == NULL) 11250 exten = chan->exten; 11251 11252 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 11253 if (ast_exists_extension(chan, context, exten, priority, 11254 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 11255 return goto_func(chan, context, exten, priority); 11256 else { 11257 return AST_PBX_GOTO_FAILED; 11258 } 11259 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 9670 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().
09671 { 09672 struct ast_include *tmpi; 09673 struct ast_sw *sw; 09674 struct ast_exten *e, *el, *en; 09675 struct ast_ignorepat *ipi; 09676 struct ast_context *tmp = con; 09677 09678 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 09679 struct ast_include *tmpil = tmpi; 09680 tmpi = tmpi->next; 09681 ast_free(tmpil); 09682 } 09683 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 09684 struct ast_ignorepat *ipl = ipi; 09685 ipi = ipi->next; 09686 ast_free(ipl); 09687 } 09688 if (tmp->registrar) 09689 ast_free(tmp->registrar); 09690 09691 /* destroy the hash tabs */ 09692 if (tmp->root_table) { 09693 ast_hashtab_destroy(tmp->root_table, 0); 09694 } 09695 /* and destroy the pattern tree */ 09696 if (tmp->pattern_tree) 09697 destroy_pattern_tree(tmp->pattern_tree); 09698 09699 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 09700 ast_free(sw); 09701 for (e = tmp->root; e;) { 09702 for (en = e->peer; en;) { 09703 el = en; 09704 en = en->peer; 09705 destroy_exten(el); 09706 } 09707 el = e; 09708 e = e->next; 09709 destroy_exten(el); 09710 } 09711 tmp->root = NULL; 09712 ast_rwlock_destroy(&tmp->lock); 09713 ast_mutex_destroy(&tmp->macrolock); 09714 ast_free(tmp); 09715 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 5473 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().
05475 { 05476 int found = 0; /* set if we find at least one match */ 05477 int res = 0; 05478 int autoloopflag; 05479 int error = 0; /* set an error conditions */ 05480 05481 /* A little initial setup here */ 05482 if (c->pbx) { 05483 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 05484 /* XXX and now what ? */ 05485 ast_free(c->pbx); 05486 } 05487 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 05488 return -1; 05489 /* Set reasonable defaults */ 05490 c->pbx->rtimeoutms = 10000; 05491 c->pbx->dtimeoutms = 5000; 05492 05493 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 05494 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 05495 05496 /* Start by trying whatever the channel is set to */ 05497 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05498 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05499 /* If not successful fall back to 's' */ 05500 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); 05501 /* XXX the original code used the existing priority in the call to 05502 * ast_exists_extension(), and reset it to 1 afterwards. 05503 * I believe the correct thing is to set it to 1 immediately. 05504 */ 05505 set_ext_pri(c, "s", 1); 05506 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05507 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05508 /* JK02: And finally back to default if everything else failed */ 05509 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); 05510 ast_copy_string(c->context, "default", sizeof(c->context)); 05511 } 05512 } 05513 ast_channel_lock(c); 05514 if (c->cdr) { 05515 /* allow CDR variables that have been collected after channel was created to be visible during call */ 05516 ast_cdr_update(c); 05517 } 05518 ast_channel_unlock(c); 05519 for (;;) { 05520 char dst_exten[256]; /* buffer to accumulate digits */ 05521 int pos = 0; /* XXX should check bounds */ 05522 int digit = 0; 05523 int invalid = 0; 05524 int timeout = 0; 05525 05526 /* No digits pressed yet */ 05527 dst_exten[pos] = '\0'; 05528 05529 /* loop on priorities in this context/exten */ 05530 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05531 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05532 &found, 1))) { 05533 if (!ast_check_hangup(c)) { 05534 ++c->priority; 05535 continue; 05536 } 05537 05538 /* Check softhangup flags. */ 05539 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05540 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05541 continue; 05542 } 05543 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05544 if (ast_exists_extension(c, c->context, "T", 1, 05545 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05546 set_ext_pri(c, "T", 1); 05547 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05548 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05549 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05550 continue; 05551 } else if (ast_exists_extension(c, c->context, "e", 1, 05552 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05553 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05554 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05555 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05556 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05557 continue; 05558 } 05559 05560 /* Call timed out with no special extension to jump to. */ 05561 error = 1; 05562 break; 05563 } 05564 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 05565 c->exten, c->priority); 05566 error = 1; 05567 break; 05568 } /* end while - from here on we can use 'break' to go out */ 05569 if (found && res) { 05570 /* Something bad happened, or a hangup has been requested. */ 05571 if (strchr("0123456789ABCDEF*#", res)) { 05572 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 05573 pos = 0; 05574 dst_exten[pos++] = digit = res; 05575 dst_exten[pos] = '\0'; 05576 } else if (res == AST_PBX_INCOMPLETE) { 05577 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05578 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05579 05580 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 05581 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 05582 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05583 invalid = 1; 05584 } else { 05585 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 05586 digit = 1; 05587 pos = strlen(dst_exten); 05588 } 05589 } else { 05590 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05591 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05592 05593 if ((res == AST_PBX_ERROR) 05594 && ast_exists_extension(c, c->context, "e", 1, 05595 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05596 /* if we are already on the 'e' exten, don't jump to it again */ 05597 if (!strcmp(c->exten, "e")) { 05598 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); 05599 error = 1; 05600 } else { 05601 raise_exception(c, "ERROR", 1); 05602 continue; 05603 } 05604 } 05605 05606 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05607 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05608 continue; 05609 } 05610 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05611 if (ast_exists_extension(c, c->context, "T", 1, 05612 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05613 set_ext_pri(c, "T", 1); 05614 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05615 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05616 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05617 continue; 05618 } else if (ast_exists_extension(c, c->context, "e", 1, 05619 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05620 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05621 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05622 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05623 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05624 continue; 05625 } 05626 /* Call timed out with no special extension to jump to. */ 05627 } 05628 ast_channel_lock(c); 05629 if (c->cdr) { 05630 ast_cdr_update(c); 05631 } 05632 ast_channel_unlock(c); 05633 error = 1; 05634 break; 05635 } 05636 } 05637 if (error) 05638 break; 05639 05640 /*!\note 05641 * We get here on a failure of some kind: non-existing extension or 05642 * hangup. We have options, here. We can either catch the failure 05643 * and continue, or we can drop out entirely. */ 05644 05645 if (invalid 05646 || (ast_strlen_zero(dst_exten) && 05647 !ast_exists_extension(c, c->context, c->exten, 1, 05648 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) { 05649 /*!\note 05650 * If there is no match at priority 1, it is not a valid extension anymore. 05651 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 05652 * neither exist. 05653 */ 05654 if (ast_exists_extension(c, c->context, "i", 1, 05655 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05656 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 05657 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 05658 set_ext_pri(c, "i", 1); 05659 } else if (ast_exists_extension(c, c->context, "e", 1, 05660 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05661 raise_exception(c, "INVALID", 1); 05662 } else { 05663 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 05664 c->name, c->exten, c->context); 05665 error = 1; /* we know what to do with it */ 05666 break; 05667 } 05668 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05669 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 05670 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05671 } else { /* keypress received, get more digits for a full extension */ 05672 int waittime = 0; 05673 if (digit) 05674 waittime = c->pbx->dtimeoutms; 05675 else if (!autofallthrough) 05676 waittime = c->pbx->rtimeoutms; 05677 if (!waittime) { 05678 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 05679 if (!status) 05680 status = "UNKNOWN"; 05681 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 05682 if (!strcasecmp(status, "CONGESTION")) 05683 res = pbx_builtin_congestion(c, "10"); 05684 else if (!strcasecmp(status, "CHANUNAVAIL")) 05685 res = pbx_builtin_congestion(c, "10"); 05686 else if (!strcasecmp(status, "BUSY")) 05687 res = pbx_builtin_busy(c, "10"); 05688 error = 1; /* XXX disable message */ 05689 break; /* exit from the 'for' loop */ 05690 } 05691 05692 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 05693 break; 05694 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 05695 timeout = 1; 05696 if (!timeout 05697 && ast_exists_extension(c, c->context, dst_exten, 1, 05698 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 05699 set_ext_pri(c, dst_exten, 1); 05700 } else { 05701 /* No such extension */ 05702 if (!timeout && !ast_strlen_zero(dst_exten)) { 05703 /* An invalid extension */ 05704 if (ast_exists_extension(c, c->context, "i", 1, 05705 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05706 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 05707 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 05708 set_ext_pri(c, "i", 1); 05709 } else if (ast_exists_extension(c, c->context, "e", 1, 05710 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05711 raise_exception(c, "INVALID", 1); 05712 } else { 05713 ast_log(LOG_WARNING, 05714 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", 05715 dst_exten, c->context); 05716 found = 1; /* XXX disable message */ 05717 break; 05718 } 05719 } else { 05720 /* A simple timeout */ 05721 if (ast_exists_extension(c, c->context, "t", 1, 05722 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05723 ast_verb(3, "Timeout on %s\n", c->name); 05724 set_ext_pri(c, "t", 1); 05725 } else if (ast_exists_extension(c, c->context, "e", 1, 05726 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05727 raise_exception(c, "RESPONSETIMEOUT", 1); 05728 } else { 05729 ast_log(LOG_WARNING, 05730 "Timeout, but no rule 't' or 'e' in context '%s'\n", 05731 c->context); 05732 found = 1; /* XXX disable message */ 05733 break; 05734 } 05735 } 05736 } 05737 ast_channel_lock(c); 05738 if (c->cdr) { 05739 ast_verb(2, "CDR updated on %s\n",c->name); 05740 ast_cdr_update(c); 05741 } 05742 ast_channel_unlock(c); 05743 } 05744 } 05745 05746 if (!found && !error) { 05747 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 05748 } 05749 05750 if (!args || !args->no_hangup_chan) { 05751 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 05752 } 05753 05754 if ((!args || !args->no_hangup_chan) 05755 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 05756 && ast_exists_extension(c, c->context, "h", 1, 05757 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05758 set_ext_pri(c, "h", 1); 05759 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 05760 ast_cdr_end(c->cdr); 05761 } 05762 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05763 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05764 &found, 1)) == 0) { 05765 c->priority++; 05766 } 05767 if (found && res) { 05768 /* Something bad happened, or a hangup has been requested. */ 05769 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05770 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05771 } 05772 } 05773 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 05774 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 05775 pbx_destroy(c->pbx); 05776 c->pbx = NULL; 05777 05778 if (!args || !args->no_hangup_chan) { 05779 ast_hangup(c); 05780 } 05781 05782 return 0; 05783 }
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 2739 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().
02740 { 02741 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02742 02743 #ifdef NEED_DEBUG_HERE 02744 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02745 #endif 02746 02747 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02748 int lp = ext_cmp_exten_strlen(pattern); 02749 int ld = ext_cmp_exten_strlen(data); 02750 02751 if (lp < ld) { /* pattern too short, cannot match */ 02752 #ifdef NEED_DEBUG_HERE 02753 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02754 #endif 02755 return 0; 02756 } 02757 /* depending on the mode, accept full or partial match or both */ 02758 if (mode == E_MATCH) { 02759 #ifdef NEED_DEBUG_HERE 02760 ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data); 02761 #endif 02762 return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */ 02763 } 02764 if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */ 02765 #ifdef NEED_DEBUG_HERE 02766 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02767 #endif 02768 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02769 } else { 02770 #ifdef NEED_DEBUG_HERE 02771 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02772 #endif 02773 return 0; 02774 } 02775 } 02776 if (mode == E_MATCH && data[0] == '_') { 02777 /* 02778 * XXX It is bad design that we don't know if we should be 02779 * comparing data and pattern as patterns or comparing data if 02780 * it conforms to pattern when the function is called. First, 02781 * assume they are both patterns. If they don't match then try 02782 * to see if data conforms to the given pattern. 02783 * 02784 * note: if this test is left out, then _x. will not match _x. !!! 02785 */ 02786 #ifdef NEED_DEBUG_HERE 02787 ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data); 02788 #endif 02789 if (!ext_cmp_pattern(pattern + 1, data + 1)) { 02790 #ifdef NEED_DEBUG_HERE 02791 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02792 #endif 02793 return 1; 02794 } 02795 } 02796 02797 ++pattern; /* skip leading _ */ 02798 /* 02799 * XXX below we stop at '/' which is a separator for the CID info. However we should 02800 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02801 */ 02802 for (;;) { 02803 const char *end; 02804 02805 /* Ignore '-' chars as eye candy fluff. */ 02806 while (*data == '-') { 02807 ++data; 02808 } 02809 while (*pattern == '-') { 02810 ++pattern; 02811 } 02812 if (!*data || !*pattern || *pattern == '/') { 02813 break; 02814 } 02815 02816 switch (*pattern) { 02817 case '[': /* a range */ 02818 ++pattern; 02819 end = strchr(pattern, ']'); /* XXX should deal with escapes ? */ 02820 if (!end) { 02821 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02822 return 0; /* unconditional failure */ 02823 } 02824 if (pattern == end) { 02825 /* Ignore empty character sets. */ 02826 ++pattern; 02827 continue; 02828 } 02829 for (; pattern < end; ++pattern) { 02830 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02831 if (*data >= pattern[0] && *data <= pattern[2]) 02832 break; /* match found */ 02833 else { 02834 pattern += 2; /* skip a total of 3 chars */ 02835 continue; 02836 } 02837 } else if (*data == pattern[0]) 02838 break; /* match found */ 02839 } 02840 if (pattern >= end) { 02841 #ifdef NEED_DEBUG_HERE 02842 ast_log(LOG_NOTICE,"return (0) when pattern>=end\n"); 02843 #endif 02844 return 0; 02845 } 02846 pattern = end; /* skip and continue */ 02847 break; 02848 case 'n': 02849 case 'N': 02850 if (*data < '2' || *data > '9') { 02851 #ifdef NEED_DEBUG_HERE 02852 ast_log(LOG_NOTICE,"return (0) N is not matched\n"); 02853 #endif 02854 return 0; 02855 } 02856 break; 02857 case 'x': 02858 case 'X': 02859 if (*data < '0' || *data > '9') { 02860 #ifdef NEED_DEBUG_HERE 02861 ast_log(LOG_NOTICE,"return (0) X is not matched\n"); 02862 #endif 02863 return 0; 02864 } 02865 break; 02866 case 'z': 02867 case 'Z': 02868 if (*data < '1' || *data > '9') { 02869 #ifdef NEED_DEBUG_HERE 02870 ast_log(LOG_NOTICE,"return (0) Z is not matched\n"); 02871 #endif 02872 return 0; 02873 } 02874 break; 02875 case '.': /* Must match, even with more digits */ 02876 #ifdef NEED_DEBUG_HERE 02877 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02878 #endif 02879 return 1; 02880 case '!': /* Early match */ 02881 #ifdef NEED_DEBUG_HERE 02882 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02883 #endif 02884 return 2; 02885 default: 02886 if (*data != *pattern) { 02887 #ifdef NEED_DEBUG_HERE 02888 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02889 #endif 02890 return 0; 02891 } 02892 break; 02893 } 02894 ++data; 02895 ++pattern; 02896 } 02897 if (*data) /* data longer than pattern, no match */ { 02898 #ifdef NEED_DEBUG_HERE 02899 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02900 #endif 02901 return 0; 02902 } 02903 02904 /* 02905 * match so far, but ran off the end of data. 02906 * Depending on what is next, determine match or not. 02907 */ 02908 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02909 #ifdef NEED_DEBUG_HERE 02910 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02911 #endif 02912 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02913 } else if (*pattern == '!') { /* early match */ 02914 #ifdef NEED_DEBUG_HERE 02915 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02916 #endif 02917 return 2; 02918 } else { /* partial match */ 02919 #ifdef NEED_DEBUG_HERE 02920 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02921 #endif 02922 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02923 } 02924 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 3626 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.
03627 { 03628 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03629 struct pbx_exception *exception = NULL; 03630 if (!ds || !ds->data) 03631 return -1; 03632 exception = ds->data; 03633 if (!strcasecmp(data, "REASON")) 03634 ast_copy_string(buf, exception->reason, buflen); 03635 else if (!strcasecmp(data, "CONTEXT")) 03636 ast_copy_string(buf, exception->context, buflen); 03637 else if (!strncasecmp(data, "EXTEN", 5)) 03638 ast_copy_string(buf, exception->exten, buflen); 03639 else if (!strcasecmp(data, "PRIORITY")) 03640 snprintf(buf, buflen, "%d", exception->priority); 03641 else 03642 return -1; 03643 return 0; 03644 }
static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3901 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().
03902 { 03903 #ifdef AST_XML_DOCS 03904 char *tmpxml; 03905 03906 /* Let's try to find it in the Documentation XML */ 03907 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03908 return 0; 03909 } 03910 03911 if (ast_string_field_init(acf, 128)) { 03912 return -1; 03913 } 03914 03915 /* load synopsis */ 03916 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); 03917 ast_string_field_set(acf, synopsis, tmpxml); 03918 ast_free(tmpxml); 03919 03920 /* load description */ 03921 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); 03922 ast_string_field_set(acf, desc, tmpxml); 03923 ast_free(tmpxml); 03924 03925 /* load syntax */ 03926 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod)); 03927 ast_string_field_set(acf, syntax, tmpxml); 03928 ast_free(tmpxml); 03929 03930 /* load arguments */ 03931 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod)); 03932 ast_string_field_set(acf, arguments, tmpxml); 03933 ast_free(tmpxml); 03934 03935 /* load seealso */ 03936 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod)); 03937 ast_string_field_set(acf, seealso, tmpxml); 03938 ast_free(tmpxml); 03939 03940 acf->docsrc = AST_XML_DOC; 03941 #endif 03942 03943 return 0; 03944 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static, read] |
Definition at line 2222 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().
02223 { 02224 struct match_char *m1 = NULL; 02225 struct match_char *m2 = NULL; 02226 struct match_char **m0; 02227 const char *pos; 02228 int already; 02229 int pattern = 0; 02230 int idx_cur; 02231 int idx_next; 02232 char extenbuf[512]; 02233 struct pattern_node pat_node[2]; 02234 02235 if (e1->matchcid) { 02236 if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) { 02237 ast_log(LOG_ERROR, 02238 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", 02239 e1->exten, e1->cidmatch); 02240 return NULL; 02241 } 02242 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */ 02243 } else { 02244 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 02245 } 02246 02247 #ifdef NEED_DEBUG 02248 ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf); 02249 #endif 02250 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 02251 m0 = &con->pattern_tree; 02252 already = 1; 02253 02254 pos = extenbuf; 02255 if (*pos == '_') { 02256 pattern = 1; 02257 ++pos; 02258 } 02259 idx_cur = 0; 02260 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf); 02261 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) { 02262 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node); 02263 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf); 02264 02265 /* See about adding node to tree. */ 02266 m2 = NULL; 02267 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern)) 02268 && m2->next_char) { 02269 if (!pat_node[idx_next].buf[0]) { 02270 /* 02271 * This is the end of the pattern, but not the end of the tree. 02272 * Mark this node with the exten... a shorter pattern might win 02273 * if the longer one doesn't match. 02274 */ 02275 if (findonly) { 02276 return m2; 02277 } 02278 if (m2->exten) { 02279 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02280 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02281 } 02282 m2->exten = e1; 02283 m2->deleted = 0; 02284 } 02285 m1 = m2->next_char; /* m1 points to the node to compare against */ 02286 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02287 } else { /* not already OR not m2 OR nor m2->next_char */ 02288 if (m2) { 02289 if (findonly) { 02290 return m2; 02291 } 02292 m1 = m2; /* while m0 stays the same */ 02293 } else { 02294 if (findonly) { 02295 return m1; 02296 } 02297 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0); 02298 if (!m1) { /* m1 is the node just added */ 02299 return NULL; 02300 } 02301 m0 = &m1->next_char; 02302 } 02303 if (!pat_node[idx_next].buf[0]) { 02304 if (m2 && m2->exten) { 02305 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02306 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02307 } 02308 m1->deleted = 0; 02309 m1->exten = e1; 02310 } 02311 02312 /* The 'already' variable is a mini-optimization designed to make it so that we 02313 * don't have to call already_in_tree when we know it will return false. 02314 */ 02315 already = 0; 02316 } 02317 } 02318 return m1; 02319 }
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 2024 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().
02025 { 02026 struct match_char *m; 02027 02028 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) { 02029 return NULL; 02030 } 02031 02032 /* strcpy is safe here since we know its size and have allocated 02033 * just enough space for when we allocated m 02034 */ 02035 strcpy(m->x, pattern->buf); 02036 02037 /* the specificity scores are the same as used in the old 02038 pattern matcher. */ 02039 m->is_pattern = is_pattern; 02040 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') { 02041 m->specificity = 0x0832; 02042 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') { 02043 m->specificity = 0x0931; 02044 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') { 02045 m->specificity = 0x0a30; 02046 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') { 02047 m->specificity = 0x18000; 02048 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') { 02049 m->specificity = 0x28000; 02050 } else { 02051 m->specificity = pattern->specif; 02052 } 02053 02054 if (!con->pattern_tree) { 02055 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 02056 } else { 02057 if (already) { /* switch to the new regime (traversing vs appending)*/ 02058 insert_in_next_chars_alt_char_list(nextcharptr, m); 02059 } else { 02060 insert_in_next_chars_alt_char_list(¤t->next_char, m); 02061 } 02062 } 02063 02064 return m; 02065 }
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 8856 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().
08858 { 08859 struct ast_exten *ep; 08860 struct ast_exten *eh=e; 08861 int repeated_label = 0; /* Track if this label is a repeat, assume no. */ 08862 08863 for (ep = NULL; e ; ep = e, e = e->peer) { 08864 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) { 08865 if (strcmp(e->exten, tmp->exten)) { 08866 ast_log(LOG_WARNING, 08867 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n", 08868 tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority); 08869 } else { 08870 ast_log(LOG_WARNING, 08871 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n", 08872 tmp->exten, tmp->priority, con->name, tmp->label, e->priority); 08873 } 08874 repeated_label = 1; 08875 } 08876 if (e->priority >= tmp->priority) { 08877 break; 08878 } 08879 } 08880 08881 if (repeated_label) { /* Discard the label since it's a repeat. */ 08882 tmp->label = NULL; 08883 } 08884 08885 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 08886 ast_hashtab_insert_safe(eh->peer_table, tmp); 08887 08888 if (tmp->label) { 08889 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08890 } 08891 ep->peer = tmp; 08892 return 0; /* success */ 08893 } 08894 if (e->priority == tmp->priority) { 08895 /* Can't have something exactly the same. Is this a 08896 replacement? If so, replace, otherwise, bonk. */ 08897 if (!replace) { 08898 if (strcmp(e->exten, tmp->exten)) { 08899 ast_log(LOG_WARNING, 08900 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n", 08901 tmp->exten, tmp->priority, con->name, e->exten); 08902 } else { 08903 ast_log(LOG_WARNING, 08904 "Unable to register extension '%s' priority %d in '%s', already in use\n", 08905 tmp->exten, tmp->priority, con->name); 08906 } 08907 if (tmp->datad) { 08908 tmp->datad(tmp->data); 08909 /* if you free this, null it out */ 08910 tmp->data = NULL; 08911 } 08912 08913 ast_free(tmp); 08914 return -1; 08915 } 08916 /* we are replacing e, so copy the link fields and then update 08917 * whoever pointed to e to point to us 08918 */ 08919 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 08920 tmp->peer = e->peer; /* always meaningful */ 08921 if (ep) { /* We're in the peer list, just insert ourselves */ 08922 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 08923 08924 if (e->label) { 08925 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 08926 } 08927 08928 ast_hashtab_insert_safe(eh->peer_table,tmp); 08929 if (tmp->label) { 08930 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 08931 } 08932 08933 ep->peer = tmp; 08934 } else if (el) { /* We're the first extension. Take over e's functions */ 08935 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08936 tmp->peer_table = e->peer_table; 08937 tmp->peer_label_table = e->peer_label_table; 08938 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 08939 ast_hashtab_insert_safe(tmp->peer_table,tmp); 08940 if (e->label) { 08941 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08942 } 08943 if (tmp->label) { 08944 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08945 } 08946 08947 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08948 ast_hashtab_insert_safe(con->root_table, tmp); 08949 el->next = tmp; 08950 /* The pattern trie points to this exten; replace the pointer, 08951 and all will be well */ 08952 if (x) { /* if the trie isn't formed yet, don't sweat this */ 08953 if (x->exten) { /* this test for safety purposes */ 08954 x->exten = tmp; /* replace what would become a bad pointer */ 08955 } else { 08956 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08957 } 08958 } 08959 } else { /* We're the very first extension. */ 08960 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08961 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08962 ast_hashtab_insert_safe(con->root_table, tmp); 08963 tmp->peer_table = e->peer_table; 08964 tmp->peer_label_table = e->peer_label_table; 08965 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 08966 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08967 if (e->label) { 08968 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08969 } 08970 if (tmp->label) { 08971 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08972 } 08973 08974 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08975 ast_hashtab_insert_safe(con->root_table, tmp); 08976 con->root = tmp; 08977 /* The pattern trie points to this exten; replace the pointer, 08978 and all will be well */ 08979 if (x) { /* if the trie isn't formed yet; no problem */ 08980 if (x->exten) { /* this test for safety purposes */ 08981 x->exten = tmp; /* replace what would become a bad pointer */ 08982 } else { 08983 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08984 } 08985 } 08986 } 08987 if (tmp->priority == PRIORITY_HINT) 08988 ast_change_hint(e,tmp); 08989 /* Destroy the old one */ 08990 if (e->datad) 08991 e->datad(e->data); 08992 ast_free(e); 08993 } else { /* Slip ourselves in just before e */ 08994 tmp->peer = e; 08995 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 08996 if (ep) { /* Easy enough, we're just in the peer list */ 08997 if (tmp->label) { 08998 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08999 } 09000 ast_hashtab_insert_safe(eh->peer_table, tmp); 09001 ep->peer = tmp; 09002 } else { /* we are the first in some peer list, so link in the ext list */ 09003 tmp->peer_table = e->peer_table; 09004 tmp->peer_label_table = e->peer_label_table; 09005 e->peer_table = 0; 09006 e->peer_label_table = 0; 09007 ast_hashtab_insert_safe(tmp->peer_table, tmp); 09008 if (tmp->label) { 09009 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 09010 } 09011 ast_hashtab_remove_object_via_lookup(con->root_table, e); 09012 ast_hashtab_insert_safe(con->root_table, tmp); 09013 if (el) 09014 el->next = tmp; /* in the middle... */ 09015 else 09016 con->root = tmp; /* ... or at the head */ 09017 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 09018 } 09019 /* And immediately return success. */ 09020 if (tmp->priority == PRIORITY_HINT) { 09021 ast_add_hint(tmp); 09022 } 09023 } 09024 return 0; 09025 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat, | |||
int | is_pattern | |||
) | [static, read] |
Definition at line 1962 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01963 { 01964 struct match_char *t; 01965 01966 if (!current) { 01967 return 0; 01968 } 01969 01970 for (t = current; t; t = t->alt_char) { 01971 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01972 return t; 01973 } 01974 } 01975 01976 return 0; 01977 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5931 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05932 { 05933 return countcalls; 05934 }
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 8691 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().
08694 { 08695 int ret = -1; 08696 struct ast_context *c; 08697 08698 c = find_context_locked(context); 08699 if (c) { 08700 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08701 application, data, datad, registrar); 08702 ast_unlock_contexts(); 08703 } 08704 08705 return ret; 08706 }
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 9052 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().
09056 { 09057 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 09058 application, data, datad, registrar, 1); 09059 }
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 9068 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().
09072 { 09073 /* 09074 * Sort extensions (or patterns) according to the rules indicated above. 09075 * These are implemented by the function ext_cmp()). 09076 * All priorities for the same ext/pattern/cid are kept in a list, 09077 * using the 'peer' field as a link field.. 09078 */ 09079 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 09080 int res; 09081 int length; 09082 char *p; 09083 char expand_buf[VAR_BUF_SIZE]; 09084 struct ast_exten dummy_exten = {0}; 09085 char dummy_name[1024]; 09086 09087 if (ast_strlen_zero(extension)) { 09088 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", 09089 con->name); 09090 return -1; 09091 } 09092 09093 /* If we are adding a hint evalulate in variables and global variables */ 09094 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') { 09095 struct ast_channel *c = ast_dummy_channel_alloc(); 09096 09097 if (c) { 09098 ast_copy_string(c->exten, extension, sizeof(c->exten)); 09099 ast_copy_string(c->context, con->name, sizeof(c->context)); 09100 } 09101 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 09102 application = expand_buf; 09103 if (c) { 09104 ast_channel_unref(c); 09105 } 09106 } 09107 09108 length = sizeof(struct ast_exten); 09109 length += strlen(extension) + 1; 09110 length += strlen(application) + 1; 09111 if (label) 09112 length += strlen(label) + 1; 09113 if (callerid) 09114 length += strlen(callerid) + 1; 09115 else 09116 length ++; /* just the '\0' */ 09117 09118 /* Be optimistic: Build the extension structure first */ 09119 if (!(tmp = ast_calloc(1, length))) 09120 return -1; 09121 09122 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 09123 label = 0; 09124 09125 /* use p as dst in assignments, as the fields are const char * */ 09126 p = tmp->stuff; 09127 if (label) { 09128 tmp->label = p; 09129 strcpy(p, label); 09130 p += strlen(label) + 1; 09131 } 09132 tmp->exten = p; 09133 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 09134 tmp->priority = priority; 09135 tmp->cidmatch = p; /* but use p for assignments below */ 09136 09137 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 09138 if (callerid) { 09139 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 09140 tmp->matchcid = AST_EXT_MATCHCID_ON; 09141 } else { 09142 *p++ = '\0'; 09143 tmp->matchcid = AST_EXT_MATCHCID_OFF; 09144 } 09145 tmp->app = p; 09146 strcpy(p, application); 09147 tmp->parent = con; 09148 tmp->data = data; 09149 tmp->datad = datad; 09150 tmp->registrar = registrar; 09151 09152 if (lock_context) { 09153 ast_wrlock_context(con); 09154 } 09155 09156 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 09157 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 09158 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 09159 dummy_exten.exten = dummy_name; 09160 dummy_exten.matchcid = AST_EXT_MATCHCID_OFF; 09161 dummy_exten.cidmatch = 0; 09162 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 09163 if (!tmp2) { 09164 /* hmmm, not in the trie; */ 09165 add_exten_to_pattern_tree(con, tmp, 0); 09166 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 09167 } 09168 } 09169 res = 0; /* some compilers will think it is uninitialized otherwise */ 09170 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 09171 res = ext_cmp(e->exten, tmp->exten); 09172 if (res == 0) { /* extension match, now look at cidmatch */ 09173 if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF) 09174 res = 0; 09175 else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF) 09176 res = 1; 09177 else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF) 09178 res = -1; 09179 else 09180 res = ext_cmp(e->cidmatch, tmp->cidmatch); 09181 } 09182 if (res >= 0) 09183 break; 09184 } 09185 if (e && res == 0) { /* exact match, insert in the priority chain */ 09186 res = add_priority(con, tmp, el, e, replace); 09187 if (lock_context) { 09188 ast_unlock_context(con); 09189 } 09190 if (res < 0) { 09191 errno = EEXIST; /* XXX do we care ? */ 09192 return 0; /* XXX should we return -1 maybe ? */ 09193 } 09194 } else { 09195 /* 09196 * not an exact match, this is the first entry with this pattern, 09197 * so insert in the main list right before 'e' (if any) 09198 */ 09199 tmp->next = e; 09200 if (el) { /* there is another exten already in this context */ 09201 el->next = tmp; 09202 tmp->peer_table = ast_hashtab_create(13, 09203 hashtab_compare_exten_numbers, 09204 ast_hashtab_resize_java, 09205 ast_hashtab_newsize_java, 09206 hashtab_hash_priority, 09207 0); 09208 tmp->peer_label_table = ast_hashtab_create(7, 09209 hashtab_compare_exten_labels, 09210 ast_hashtab_resize_java, 09211 ast_hashtab_newsize_java, 09212 hashtab_hash_labels, 09213 0); 09214 if (label) { 09215 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 09216 } 09217 ast_hashtab_insert_safe(tmp->peer_table, tmp); 09218 } else { /* this is the first exten in this context */ 09219 if (!con->root_table) 09220 con->root_table = ast_hashtab_create(27, 09221 hashtab_compare_extens, 09222 ast_hashtab_resize_java, 09223 ast_hashtab_newsize_java, 09224 hashtab_hash_extens, 09225 0); 09226 con->root = tmp; 09227 con->root->peer_table = ast_hashtab_create(13, 09228 hashtab_compare_exten_numbers, 09229 ast_hashtab_resize_java, 09230 ast_hashtab_newsize_java, 09231 hashtab_hash_priority, 09232 0); 09233 con->root->peer_label_table = ast_hashtab_create(7, 09234 hashtab_compare_exten_labels, 09235 ast_hashtab_resize_java, 09236 ast_hashtab_newsize_java, 09237 hashtab_hash_labels, 09238 0); 09239 if (label) { 09240 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 09241 } 09242 ast_hashtab_insert_safe(con->root->peer_table, tmp); 09243 09244 } 09245 ast_hashtab_insert_safe(con->root_table, tmp); 09246 if (lock_context) { 09247 ast_unlock_context(con); 09248 } 09249 if (tmp->priority == PRIORITY_HINT) { 09250 ast_add_hint(tmp); 09251 } 09252 } 09253 if (option_debug) { 09254 if (tmp->matchcid == AST_EXT_MATCHCID_ON) { 09255 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 09256 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 09257 } else { 09258 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 09259 tmp->exten, tmp->priority, con->name, con); 09260 } 09261 } 09262 09263 if (tmp->matchcid == AST_EXT_MATCHCID_ON) { 09264 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 09265 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 09266 } else { 09267 ast_verb(3, "Added extension '%s' priority %d to %s\n", 09268 tmp->exten, tmp->priority, con->name); 09269 } 09270 09271 return 0; 09272 }
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 8671 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
08674 { 08675 int ret = -1; 08676 struct ast_context *c; 08677 08678 c = find_context(context); 08679 if (c) { 08680 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 08681 application, data, datad, registrar, 1); 08682 } 08683 08684 return ret; 08685 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 5270 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().
05271 { 05272 struct ast_hint *hint_new; 05273 struct ast_hint *hint_found; 05274 05275 if (!e) { 05276 return -1; 05277 } 05278 05279 /* 05280 * We must create the hint we wish to add before determining if 05281 * it is already in the hints container to avoid possible 05282 * deadlock when getting the current extension state. 05283 */ 05284 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint); 05285 if (!hint_new) { 05286 return -1; 05287 } 05288 05289 /* Initialize new hint. */ 05290 hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); 05291 if (!hint_new->callbacks) { 05292 ao2_ref(hint_new, -1); 05293 return -1; 05294 } 05295 hint_new->exten = e; 05296 if (strstr(e->app, "${") && e->exten[0] == '_') { 05297 hint_new->laststate = AST_DEVICE_INVALID; 05298 } else { 05299 hint_new->laststate = ast_extension_state2(e); 05300 } 05301 05302 /* Prevent multiple add hints from adding the same hint at the same time. */ 05303 ao2_lock(hints); 05304 05305 /* Search if hint exists, do nothing */ 05306 hint_found = ao2_find(hints, e, 0); 05307 if (hint_found) { 05308 ao2_ref(hint_found, -1); 05309 ao2_unlock(hints); 05310 ao2_ref(hint_new, -1); 05311 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", 05312 ast_get_extension_name(e), ast_get_extension_app(e)); 05313 return -1; 05314 } 05315 05316 /* Add new hint to the hints container */ 05317 ast_debug(2, "HINTS: Adding hint %s: %s\n", 05318 ast_get_extension_name(e), ast_get_extension_app(e)); 05319 ao2_link(hints, hint_new); 05320 05321 ao2_unlock(hints); 05322 ao2_ref(hint_new, -1); 05323 05324 return 0; 05325 }
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 8731 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().
08732 { 08733 int res = 0; 08734 struct ast_channel *tmpchan; 08735 struct { 08736 char *accountcode; 08737 char *exten; 08738 char *context; 08739 char *linkedid; 08740 char *name; 08741 struct ast_cdr *cdr; 08742 int amaflags; 08743 int state; 08744 format_t readformat; 08745 format_t writeformat; 08746 } tmpvars = { 0, }; 08747 08748 ast_channel_lock(chan); 08749 if (chan->pbx) { /* This channel is currently in the PBX */ 08750 ast_explicit_goto(chan, context, exten, priority + 1); 08751 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08752 ast_channel_unlock(chan); 08753 return res; 08754 } 08755 08756 /* In order to do it when the channel doesn't really exist within 08757 * the PBX, we have to make a new channel, masquerade, and start the PBX 08758 * at the new location */ 08759 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08760 tmpvars.exten = ast_strdupa(chan->exten); 08761 tmpvars.context = ast_strdupa(chan->context); 08762 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08763 tmpvars.name = ast_strdupa(chan->name); 08764 tmpvars.amaflags = chan->amaflags; 08765 tmpvars.state = chan->_state; 08766 tmpvars.writeformat = chan->writeformat; 08767 tmpvars.readformat = chan->readformat; 08768 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08769 08770 ast_channel_unlock(chan); 08771 08772 /* Do not hold any channel locks while calling channel_alloc() since the function 08773 * locks the channel container when linking the new channel in. */ 08774 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08775 ast_cdr_discard(tmpvars.cdr); 08776 return -1; 08777 } 08778 08779 /* copy the cdr info over */ 08780 if (tmpvars.cdr) { 08781 ast_cdr_discard(tmpchan->cdr); 08782 tmpchan->cdr = tmpvars.cdr; 08783 tmpvars.cdr = NULL; 08784 } 08785 08786 /* Make formats okay */ 08787 tmpchan->readformat = tmpvars.readformat; 08788 tmpchan->writeformat = tmpvars.writeformat; 08789 08790 /* Setup proper location. Never hold another channel lock while calling this function. */ 08791 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08792 08793 /* Masquerade into tmp channel */ 08794 if (ast_channel_masquerade(tmpchan, chan)) { 08795 /* Failed to set up the masquerade. It's probably chan_local 08796 * in the middle of optimizing itself out. Sad. :( */ 08797 ast_hangup(tmpchan); 08798 tmpchan = NULL; 08799 res = -1; 08800 } else { 08801 ast_do_masquerade(tmpchan); 08802 /* Start the PBX going on our stolen channel */ 08803 if (ast_pbx_start(tmpchan)) { 08804 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08805 ast_hangup(tmpchan); 08806 res = -1; 08807 } 08808 } 08809 08810 return res; 08811 }
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 8813 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08814 { 08815 struct ast_channel *chan; 08816 int res = -1; 08817 08818 if ((chan = ast_channel_get_by_name(channame))) { 08819 res = ast_async_goto(chan, context, exten, priority); 08820 chan = ast_channel_unref(chan); 08821 } 08822 08823 return res; 08824 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11266 of file pbx.c.
References __ast_goto_if_exists().
11267 { 11268 return __ast_goto_if_exists(chan, context, exten, priority, 1); 11269 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11331 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
11332 { 11333 return pbx_parseable_goto(chan, goto_string, 1); 11334 }
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 8314 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().
08315 { 08316 char *info; 08317 int j, num_fields, last_sep = -1; 08318 08319 i->timezone = NULL; 08320 08321 /* Check for empty just in case */ 08322 if (ast_strlen_zero(info_in)) { 08323 return 0; 08324 } 08325 08326 /* make a copy just in case we were passed a static string */ 08327 info = ast_strdupa(info_in); 08328 08329 /* count the number of fields in the timespec */ 08330 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08331 if (info[j] == ',') { 08332 last_sep = j; 08333 num_fields++; 08334 } 08335 } 08336 08337 /* save the timezone, if it is specified */ 08338 if (num_fields == 5) { 08339 i->timezone = ast_strdup(info + last_sep + 1); 08340 } 08341 08342 /* Assume everything except time */ 08343 i->monthmask = 0xfff; /* 12 bits */ 08344 i->daymask = 0x7fffffffU; /* 31 bits */ 08345 i->dowmask = 0x7f; /* 7 bits */ 08346 /* on each call, use strsep() to move info to the next argument */ 08347 get_timerange(i, strsep(&info, "|,")); 08348 if (info) 08349 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08350 if (info) 08351 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08352 if (info) 08353 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08354 return 1; 08355 }
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 5415 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().
05416 { 05417 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05418 }
Change hint for an extension.
Definition at line 5328 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().
05329 { 05330 struct ast_hint *hint; 05331 05332 if (!oe || !ne) { 05333 return -1; 05334 } 05335 05336 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */ 05337 05338 /* 05339 * Unlink the hint from the hints container as the extension 05340 * name (which is the hash value) could change. 05341 */ 05342 hint = ao2_find(hints, oe, OBJ_UNLINK); 05343 if (!hint) { 05344 ao2_unlock(hints); 05345 return -1; 05346 } 05347 05348 /* Update the hint and put it back in the hints container. */ 05349 ao2_lock(hint); 05350 hint->exten = ne; 05351 ao2_unlock(hint); 05352 ao2_link(hints, hint); 05353 05354 ao2_unlock(hints); 05355 ao2_ref(hint, -1); 05356 05357 return 0; 05358 }
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 8357 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08358 { 08359 return ast_check_timing2(i, ast_tvnow()); 08360 }
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 8362 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().
08363 { 08364 struct ast_tm tm; 08365 08366 ast_localtime(&tv, &tm, i->timezone); 08367 08368 /* If it's not the right month, return */ 08369 if (!(i->monthmask & (1 << tm.tm_mon))) 08370 return 0; 08371 08372 /* If it's not that time of the month.... */ 08373 /* Warning, tm_mday has range 1..31! */ 08374 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08375 return 0; 08376 08377 /* If it's not the right day of the week */ 08378 if (!(i->dowmask & (1 << tm.tm_wday))) 08379 return 0; 08380 08381 /* Sanity check the hour just to be safe */ 08382 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08383 ast_log(LOG_WARNING, "Insane time...\n"); 08384 return 0; 08385 } 08386 08387 /* Now the tough part, we calculate if it fits 08388 in the right time based on min/hour */ 08389 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)))) 08390 return 0; 08391 08392 /* If we got this far, then we're good */ 08393 return 1; 08394 }
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 11336 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().
11337 { 11338 struct ast_app *app = NULL; 11339 int which = 0; 11340 char *ret = NULL; 11341 size_t wordlen = strlen(word); 11342 11343 AST_RWLIST_RDLOCK(&apps); 11344 AST_RWLIST_TRAVERSE(&apps, app, list) { 11345 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 11346 ret = ast_strdup(app->name); 11347 break; 11348 } 11349 } 11350 AST_RWLIST_UNLOCK(&apps); 11351 11352 return ret; 11353 }
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 8598 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08599 { 08600 int ret = -1; 08601 struct ast_context *c; 08602 08603 c = find_context_locked(context); 08604 if (c) { 08605 ret = ast_context_add_ignorepat2(c, value, registrar); 08606 ast_unlock_contexts(); 08607 } 08608 return ret; 08609 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 8611 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().
08612 { 08613 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08614 int length; 08615 char *pattern; 08616 length = sizeof(struct ast_ignorepat); 08617 length += strlen(value) + 1; 08618 if (!(ignorepat = ast_calloc(1, length))) 08619 return -1; 08620 /* The cast to char * is because we need to write the initial value. 08621 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08622 * sees the cast as dereferencing a type-punned pointer and warns about 08623 * it. This is the workaround (we're telling gcc, yes, that's really 08624 * what we wanted to do). 08625 */ 08626 pattern = (char *) ignorepat->pattern; 08627 strcpy(pattern, value); 08628 ignorepat->next = NULL; 08629 ignorepat->registrar = registrar; 08630 ast_wrlock_context(con); 08631 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08632 ignorepatl = ignorepatc; 08633 if (!strcasecmp(ignorepatc->pattern, value)) { 08634 /* Already there */ 08635 ast_unlock_context(con); 08636 ast_free(ignorepat); 08637 errno = EEXIST; 08638 return -1; 08639 } 08640 } 08641 if (ignorepatl) 08642 ignorepatl->next = ignorepat; 08643 else 08644 con->ignorepats = ignorepat; 08645 ast_unlock_context(con); 08646 return 0; 08647 08648 }
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 8142 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
08143 { 08144 int ret = -1; 08145 struct ast_context *c; 08146 08147 c = find_context_locked(context); 08148 if (c) { 08149 ret = ast_context_add_include2(c, include, registrar); 08150 ast_unlock_contexts(); 08151 } 08152 return ret; 08153 }
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 8411 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().
08413 { 08414 struct ast_include *new_include; 08415 char *c; 08416 struct ast_include *i, *il = NULL; /* include, include_last */ 08417 int length; 08418 char *p; 08419 08420 length = sizeof(struct ast_include); 08421 length += 2 * (strlen(value) + 1); 08422 08423 /* allocate new include structure ... */ 08424 if (!(new_include = ast_calloc(1, length))) 08425 return -1; 08426 /* Fill in this structure. Use 'p' for assignments, as the fields 08427 * in the structure are 'const char *' 08428 */ 08429 p = new_include->stuff; 08430 new_include->name = p; 08431 strcpy(p, value); 08432 p += strlen(value) + 1; 08433 new_include->rname = p; 08434 strcpy(p, value); 08435 /* Strip off timing info, and process if it is there */ 08436 if ( (c = strchr(p, ',')) ) { 08437 *c++ = '\0'; 08438 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08439 } 08440 new_include->next = NULL; 08441 new_include->registrar = registrar; 08442 08443 ast_wrlock_context(con); 08444 08445 /* ... go to last include and check if context is already included too... */ 08446 for (i = con->includes; i; i = i->next) { 08447 if (!strcasecmp(i->name, new_include->name)) { 08448 ast_destroy_timing(&(new_include->timing)); 08449 ast_free(new_include); 08450 ast_unlock_context(con); 08451 errno = EEXIST; 08452 return -1; 08453 } 08454 il = i; 08455 } 08456 08457 /* ... include new context into context list, unlock, return */ 08458 if (il) 08459 il->next = new_include; 08460 else 08461 con->includes = new_include; 08462 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08463 08464 ast_unlock_context(con); 08465 08466 return 0; 08467 }
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 8474 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08475 { 08476 int ret = -1; 08477 struct ast_context *c; 08478 08479 c = find_context_locked(context); 08480 if (c) { /* found, add switch to this context */ 08481 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08482 ast_unlock_contexts(); 08483 } 08484 return ret; 08485 }
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 8494 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().
08496 { 08497 struct ast_sw *new_sw; 08498 struct ast_sw *i; 08499 int length; 08500 char *p; 08501 08502 length = sizeof(struct ast_sw); 08503 length += strlen(value) + 1; 08504 if (data) 08505 length += strlen(data); 08506 length++; 08507 08508 /* allocate new sw structure ... */ 08509 if (!(new_sw = ast_calloc(1, length))) 08510 return -1; 08511 /* ... fill in this structure ... */ 08512 p = new_sw->stuff; 08513 new_sw->name = p; 08514 strcpy(new_sw->name, value); 08515 p += strlen(value) + 1; 08516 new_sw->data = p; 08517 if (data) { 08518 strcpy(new_sw->data, data); 08519 p += strlen(data) + 1; 08520 } else { 08521 strcpy(new_sw->data, ""); 08522 p++; 08523 } 08524 new_sw->eval = eval; 08525 new_sw->registrar = registrar; 08526 08527 /* ... try to lock this context ... */ 08528 ast_wrlock_context(con); 08529 08530 /* ... go to last sw and check if context is already swd too... */ 08531 AST_LIST_TRAVERSE(&con->alts, i, list) { 08532 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08533 ast_free(new_sw); 08534 ast_unlock_context(con); 08535 errno = EEXIST; 08536 return -1; 08537 } 08538 } 08539 08540 /* ... sw new context into context list, unlock, return */ 08541 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08542 08543 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08544 08545 ast_unlock_context(con); 08546 08547 return 0; 08548 }
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 9875 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().
09876 { 09877 ast_wrlock_contexts(); 09878 __ast_context_destroy(contexts, contexts_table, con,registrar); 09879 ast_unlock_contexts(); 09880 }
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 2971 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().
02972 { 02973 struct ast_context *tmp; 02974 struct fake_context item; 02975 02976 if (!name) { 02977 return NULL; 02978 } 02979 ast_rdlock_contexts(); 02980 if (contexts_table) { 02981 ast_copy_string(item.name, name, sizeof(item.name)); 02982 tmp = ast_hashtab_lookup(contexts_table, &item); 02983 } else { 02984 tmp = NULL; 02985 while ((tmp = ast_walk_contexts(tmp))) { 02986 if (!strcasecmp(name, tmp->name)) { 02987 break; 02988 } 02989 } 02990 } 02991 ast_unlock_contexts(); 02992 return tmp; 02993 }
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 7726 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().
07727 { 07728 struct ast_context *tmp, **local_contexts; 07729 struct fake_context search; 07730 int length = sizeof(struct ast_context) + strlen(name) + 1; 07731 07732 if (!contexts_table) { 07733 /* Protect creation of contexts_table from reentrancy. */ 07734 ast_wrlock_contexts(); 07735 if (!contexts_table) { 07736 contexts_table = ast_hashtab_create(17, 07737 ast_hashtab_compare_contexts, 07738 ast_hashtab_resize_java, 07739 ast_hashtab_newsize_java, 07740 ast_hashtab_hash_contexts, 07741 0); 07742 } 07743 ast_unlock_contexts(); 07744 } 07745 07746 ast_copy_string(search.name, name, sizeof(search.name)); 07747 if (!extcontexts) { 07748 ast_rdlock_contexts(); 07749 local_contexts = &contexts; 07750 tmp = ast_hashtab_lookup(contexts_table, &search); 07751 ast_unlock_contexts(); 07752 if (tmp) { 07753 tmp->refcount++; 07754 return tmp; 07755 } 07756 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07757 local_contexts = extcontexts; 07758 tmp = ast_hashtab_lookup(exttable, &search); 07759 if (tmp) { 07760 tmp->refcount++; 07761 return tmp; 07762 } 07763 } 07764 07765 if ((tmp = ast_calloc(1, length))) { 07766 ast_rwlock_init(&tmp->lock); 07767 ast_mutex_init(&tmp->macrolock); 07768 strcpy(tmp->name, name); 07769 tmp->root = NULL; 07770 tmp->root_table = NULL; 07771 tmp->registrar = ast_strdup(registrar); 07772 tmp->includes = NULL; 07773 tmp->ignorepats = NULL; 07774 tmp->refcount = 1; 07775 } else { 07776 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07777 return NULL; 07778 } 07779 07780 if (!extcontexts) { 07781 ast_wrlock_contexts(); 07782 tmp->next = *local_contexts; 07783 *local_contexts = tmp; 07784 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07785 ast_unlock_contexts(); 07786 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07787 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07788 } else { 07789 tmp->next = *local_contexts; 07790 if (exttable) 07791 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07792 07793 *local_contexts = tmp; 07794 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07795 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07796 } 07797 return tmp; 07798 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 6306 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06307 { 06308 struct ast_context *c; 06309 int ret = -1; 06310 06311 c = find_context_locked(context); 06312 if (c) { 06313 ast_unlock_contexts(); 06314 06315 /* if we found context, lock macrolock */ 06316 ret = ast_mutex_lock(&c->macrolock); 06317 } 06318 06319 return ret; 06320 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
Definition at line 6114 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().
06115 { 06116 return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar); 06117 }
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 6144 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().
06145 { 06146 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked); 06147 }
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 6119 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().
06120 { 06121 int ret = -1; /* default error return */ 06122 struct ast_context *c; 06123 06124 c = find_context_locked(context); 06125 if (c) { /* ... remove extension ... */ 06126 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 06127 matchcallerid, registrar, 0); 06128 ast_unlock_contexts(); 06129 } 06130 06131 return ret; 06132 }
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 6149 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().
06150 { 06151 struct ast_exten *exten, *prev_exten = NULL; 06152 struct ast_exten *peer; 06153 struct ast_exten ex, *exten2, *exten3; 06154 char dummy_name[1024]; 06155 struct ast_exten *previous_peer = NULL; 06156 struct ast_exten *next_peer = NULL; 06157 int found = 0; 06158 06159 if (!already_locked) 06160 ast_wrlock_context(con); 06161 06162 #ifdef NEED_DEBUG 06163 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 06164 #endif 06165 #ifdef CONTEXT_DEBUG 06166 check_contexts(__FILE__, __LINE__); 06167 #endif 06168 /* find this particular extension */ 06169 ex.exten = dummy_name; 06170 ex.matchcid = matchcallerid; 06171 ex.cidmatch = callerid; 06172 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 06173 exten = ast_hashtab_lookup(con->root_table, &ex); 06174 if (exten) { 06175 if (priority == 0) { 06176 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06177 if (!exten2) 06178 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); 06179 if (con->pattern_tree) { 06180 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06181 06182 if (x->exten) { /* this test for safety purposes */ 06183 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06184 x->exten = 0; /* get rid of what will become a bad pointer */ 06185 } else { 06186 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 06187 } 06188 } 06189 } else { 06190 ex.priority = priority; 06191 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 06192 if (exten2) { 06193 if (exten2->label) { /* if this exten has a label, remove that, too */ 06194 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 06195 if (!exten3) 06196 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); 06197 } 06198 06199 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 06200 if (!exten3) 06201 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); 06202 if (exten2 == exten && exten2->peer) { 06203 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06204 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 06205 } 06206 if (ast_hashtab_size(exten->peer_table) == 0) { 06207 /* well, if the last priority of an exten is to be removed, 06208 then, the extension is removed, too! */ 06209 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 06210 if (!exten3) 06211 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 06212 if (con->pattern_tree) { 06213 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06214 if (x->exten) { /* this test for safety purposes */ 06215 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06216 x->exten = 0; /* get rid of what will become a bad pointer */ 06217 } 06218 } 06219 } 06220 } else { 06221 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 06222 priority, exten->exten, con->name); 06223 } 06224 } 06225 } else { 06226 /* hmmm? this exten is not in this pattern tree? */ 06227 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 06228 extension, con->name); 06229 } 06230 #ifdef NEED_DEBUG 06231 if (con->pattern_tree) { 06232 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 06233 log_match_char_tree(con->pattern_tree, " "); 06234 } 06235 #endif 06236 06237 /* scan the extension list to find first matching extension-registrar */ 06238 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 06239 if (!strcmp(exten->exten, extension) && 06240 (!registrar || !strcmp(exten->registrar, registrar)) && 06241 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 06242 break; 06243 } 06244 if (!exten) { 06245 /* we can't find right extension */ 06246 if (!already_locked) 06247 ast_unlock_context(con); 06248 return -1; 06249 } 06250 06251 /* scan the priority list to remove extension with exten->priority == priority */ 06252 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 06253 peer && !strcmp(peer->exten, extension) && 06254 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ; 06255 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 06256 06257 if ((priority == 0 || peer->priority == priority) && 06258 (!registrar || !strcmp(peer->registrar, registrar) )) { 06259 found = 1; 06260 06261 /* we are first priority extension? */ 06262 if (!previous_peer) { 06263 /* 06264 * We are first in the priority chain, so must update the extension chain. 06265 * The next node is either the next priority or the next extension 06266 */ 06267 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 06268 if (peer->peer) { 06269 /* move the peer_table and peer_label_table down to the next peer, if 06270 it is there */ 06271 peer->peer->peer_table = peer->peer_table; 06272 peer->peer->peer_label_table = peer->peer_label_table; 06273 peer->peer_table = NULL; 06274 peer->peer_label_table = NULL; 06275 } 06276 if (!prev_exten) { /* change the root... */ 06277 con->root = next_node; 06278 } else { 06279 prev_exten->next = next_node; /* unlink */ 06280 } 06281 if (peer->peer) { /* update the new head of the pri list */ 06282 peer->peer->next = peer->next; 06283 } 06284 } else { /* easy, we are not first priority in extension */ 06285 previous_peer->peer = peer->peer; 06286 } 06287 06288 06289 /* now, free whole priority extension */ 06290 destroy_exten(peer); 06291 } else { 06292 previous_peer = peer; 06293 } 06294 } 06295 if (!already_locked) 06296 ast_unlock_context(con); 06297 return found ? 0 : -1; 06298 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8554 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08555 { 08556 int ret = -1; 08557 struct ast_context *c; 08558 08559 c = find_context_locked(context); 08560 if (c) { 08561 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08562 ast_unlock_contexts(); 08563 } 08564 return ret; 08565 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8567 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().
08568 { 08569 struct ast_ignorepat *ip, *ipl = NULL; 08570 08571 ast_wrlock_context(con); 08572 08573 for (ip = con->ignorepats; ip; ip = ip->next) { 08574 if (!strcmp(ip->pattern, ignorepat) && 08575 (!registrar || (registrar == ip->registrar))) { 08576 if (ipl) { 08577 ipl->next = ip->next; 08578 ast_free(ip); 08579 } else { 08580 con->ignorepats = ip->next; 08581 ast_free(ip); 08582 } 08583 ast_unlock_context(con); 08584 return 0; 08585 } 08586 ipl = ip; 08587 } 08588 08589 ast_unlock_context(con); 08590 errno = EINVAL; 08591 return -1; 08592 }
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 6007 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
06008 { 06009 int ret = -1; 06010 struct ast_context *c; 06011 06012 c = find_context_locked(context); 06013 if (c) { 06014 /* found, remove include from this context ... */ 06015 ret = ast_context_remove_include2(c, include, registrar); 06016 ast_unlock_contexts(); 06017 } 06018 return ret; 06019 }
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 6030 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().
06031 { 06032 struct ast_include *i, *pi = NULL; 06033 int ret = -1; 06034 06035 ast_wrlock_context(con); 06036 06037 /* find our include */ 06038 for (i = con->includes; i; pi = i, i = i->next) { 06039 if (!strcmp(i->name, include) && 06040 (!registrar || !strcmp(i->registrar, registrar))) { 06041 /* remove from list */ 06042 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 06043 if (pi) 06044 pi->next = i->next; 06045 else 06046 con->includes = i->next; 06047 /* free include and return */ 06048 ast_destroy_timing(&(i->timing)); 06049 ast_free(i); 06050 ret = 0; 06051 break; 06052 } 06053 } 06054 06055 ast_unlock_context(con); 06056 06057 return ret; 06058 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 6065 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
06066 { 06067 int ret = -1; /* default error return */ 06068 struct ast_context *c; 06069 06070 c = find_context_locked(context); 06071 if (c) { 06072 /* remove switch from this context ... */ 06073 ret = ast_context_remove_switch2(c, sw, data, registrar); 06074 ast_unlock_contexts(); 06075 } 06076 return ret; 06077 }
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 6087 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().
06088 { 06089 struct ast_sw *i; 06090 int ret = -1; 06091 06092 ast_wrlock_context(con); 06093 06094 /* walk switches */ 06095 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 06096 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 06097 (!registrar || !strcmp(i->registrar, registrar))) { 06098 /* found, remove from list */ 06099 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 06100 AST_LIST_REMOVE_CURRENT(list); 06101 ast_free(i); /* free switch and return */ 06102 ret = 0; 06103 break; 06104 } 06105 } 06106 AST_LIST_TRAVERSE_SAFE_END; 06107 06108 ast_unlock_context(con); 06109 06110 return ret; 06111 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 6327 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06328 { 06329 struct ast_context *c; 06330 int ret = -1; 06331 06332 c = find_context_locked(context); 06333 if (c) { 06334 ast_unlock_contexts(); 06335 06336 /* if we found context, unlock macrolock */ 06337 ret = ast_mutex_unlock(&c->macrolock); 06338 } 06339 06340 return ret; 06341 }
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 11221 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().
11222 { 11223 struct ast_include *inc = NULL; 11224 int res = 0; 11225 11226 while ( (inc = ast_walk_context_includes(con, inc)) ) { 11227 if (ast_context_find(inc->rname)) 11228 continue; 11229 11230 res = -1; 11231 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 11232 ast_get_context_name(con), inc->rname); 11233 break; 11234 } 11235 11236 return res; 11237 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3800 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().
03801 { 03802 struct ast_custom_function *acf = NULL; 03803 03804 AST_RWLIST_RDLOCK(&acf_root); 03805 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03806 if (!strcmp(name, acf->name)) 03807 break; 03808 } 03809 AST_RWLIST_UNLOCK(&acf_root); 03810 03811 return acf; 03812 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3814 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().
03815 { 03816 struct ast_custom_function *cur; 03817 struct ast_custom_escalating_function *cur_escalation; 03818 03819 if (!acf) { 03820 return -1; 03821 } 03822 03823 AST_RWLIST_WRLOCK(&acf_root); 03824 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03825 #ifdef AST_XML_DOCS 03826 if (cur->docsrc == AST_XML_DOC) { 03827 ast_string_field_free_memory(acf); 03828 } 03829 #endif 03830 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03831 } 03832 AST_RWLIST_UNLOCK(&acf_root); 03833 03834 /* Remove from the escalation list */ 03835 AST_RWLIST_WRLOCK(&escalation_root); 03836 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) { 03837 if (cur_escalation->acf == acf) { 03838 AST_RWLIST_REMOVE_CURRENT(list); 03839 ast_free(cur_escalation); 03840 break; 03841 } 03842 } 03843 AST_RWLIST_TRAVERSE_SAFE_END; 03844 AST_RWLIST_UNLOCK(&escalation_root); 03845 03846 return cur ? 0 : -1; 03847 }
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 8396 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 4844 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().
04845 { 04846 switch (devstate) { 04847 case AST_DEVICE_ONHOLD: 04848 return AST_EXTENSION_ONHOLD; 04849 case AST_DEVICE_BUSY: 04850 return AST_EXTENSION_BUSY; 04851 case AST_DEVICE_UNKNOWN: 04852 return AST_EXTENSION_NOT_INUSE; 04853 case AST_DEVICE_UNAVAILABLE: 04854 case AST_DEVICE_INVALID: 04855 return AST_EXTENSION_UNAVAILABLE; 04856 case AST_DEVICE_RINGINUSE: 04857 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04858 case AST_DEVICE_RINGING: 04859 return AST_EXTENSION_RINGING; 04860 case AST_DEVICE_INUSE: 04861 return AST_EXTENSION_INUSE; 04862 case AST_DEVICE_NOT_INUSE: 04863 return AST_EXTENSION_NOT_INUSE; 04864 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04865 break; 04866 } 04867 04868 return AST_EXTENSION_NOT_INUSE; 04869 }
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 5400 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().
05401 { 05402 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05403 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8708 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().
08709 { 08710 if (!chan) 08711 return -1; 08712 08713 ast_channel_lock(chan); 08714 08715 if (!ast_strlen_zero(context)) 08716 ast_copy_string(chan->context, context, sizeof(chan->context)); 08717 if (!ast_strlen_zero(exten)) 08718 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08719 if (priority > -1) { 08720 chan->priority = priority; 08721 /* see flag description in channel.h for explanation */ 08722 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08723 chan->priority--; 08724 } 08725 08726 ast_channel_unlock(chan); 08727 08728 return 0; 08729 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2948 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().
02949 { 02950 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02951 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02952 return extension_match_core(pattern, data, needmore); 02953 }
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 2713 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02714 { 02715 int cmp; 02716 02717 cmp = ext_cmp(a, b); 02718 if (cmp < 0) { 02719 return -1; 02720 } 02721 if (cmp > 0) { 02722 return 1; 02723 } 02724 return 0; 02725 }
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 2943 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().
02944 { 02945 return extension_match_core(pattern, data, E_MATCH); 02946 }
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 4914 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().
04915 { 04916 struct ast_exten *e; 04917 04918 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04919 return -1; /* No hint, return -1 */ 04920 } 04921 04922 if (e->exten[0] == '_') { 04923 /* Create this hint on-the-fly */ 04924 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04925 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04926 e->registrar); 04927 if (!(e = ast_hint_extension(c, context, exten))) { 04928 /* Improbable, but not impossible */ 04929 return -1; 04930 } 04931 } 04932 04933 return ast_extension_state2(e); /* Check all devices in the hint */ 04934 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4889 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().
04890 { 04891 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32); 04892 04893 if (!e || !hint_app) { 04894 return -1; 04895 } 04896 04897 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e)); 04898 return ast_extension_state3(hint_app); 04899 }
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 4902 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().
04903 { 04904 int i; 04905 04906 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04907 if (extension_states[i].extension_state == extension_state) 04908 return extension_states[i].text; 04909 } 04910 return "Unknown"; 04911 }
static int ast_extension_state3 | ( | struct ast_str * | hint_app | ) | [static] |
Definition at line 4871 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().
04872 { 04873 char *cur; 04874 char *rest; 04875 struct ast_devstate_aggregate agg; 04876 04877 /* One or more devices separated with a & character */ 04878 rest = ast_str_buffer(hint_app); 04879 04880 ast_devstate_aggregate_init(&agg); 04881 while ((cur = strsep(&rest, "&"))) { 04882 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04883 } 04884 04885 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04886 }
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 5135 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
05137 { 05138 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 05139 }
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 5048 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().
05050 { 05051 struct ast_hint *hint; 05052 struct ast_state_cb *state_cb; 05053 struct ast_exten *e; 05054 int id; 05055 05056 /* If there's no context and extension: add callback to statecbs list */ 05057 if (!context && !exten) { 05058 /* Prevent multiple adds from adding the same change_cb at the same time. */ 05059 ao2_lock(statecbs); 05060 05061 /* Remove any existing change_cb. */ 05062 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 05063 05064 /* Now insert the change_cb */ 05065 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05066 ao2_unlock(statecbs); 05067 return -1; 05068 } 05069 state_cb->id = 0; 05070 state_cb->change_cb = change_cb; 05071 state_cb->destroy_cb = destroy_cb; 05072 state_cb->data = data; 05073 ao2_link(statecbs, state_cb); 05074 05075 ao2_ref(state_cb, -1); 05076 ao2_unlock(statecbs); 05077 return 0; 05078 } 05079 05080 if (!context || !exten) 05081 return -1; 05082 05083 /* This callback type is for only one hint, so get the hint */ 05084 e = ast_hint_extension(NULL, context, exten); 05085 if (!e) { 05086 return -1; 05087 } 05088 05089 /* If this is a pattern, dynamically create a new extension for this 05090 * particular match. Note that this will only happen once for each 05091 * individual extension, because the pattern will no longer match first. 05092 */ 05093 if (e->exten[0] == '_') { 05094 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 05095 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 05096 e->registrar); 05097 e = ast_hint_extension(NULL, context, exten); 05098 if (!e || e->exten[0] == '_') { 05099 return -1; 05100 } 05101 } 05102 05103 /* Find the hint in the hints container */ 05104 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05105 hint = ao2_find(hints, e, 0); 05106 if (!hint) { 05107 ao2_unlock(hints); 05108 return -1; 05109 } 05110 05111 /* Now insert the callback in the callback list */ 05112 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05113 ao2_ref(hint, -1); 05114 ao2_unlock(hints); 05115 return -1; 05116 } 05117 do { 05118 id = stateid++; /* Unique ID for this callback */ 05119 /* Do not allow id to ever be -1 or 0. */ 05120 } while (id == -1 || id == 0); 05121 state_cb->id = id; 05122 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 05123 state_cb->destroy_cb = destroy_cb; 05124 state_cb->data = data; /* Data for the callback */ 05125 ao2_link(hint->callbacks, state_cb); 05126 05127 ao2_ref(state_cb, -1); 05128 ao2_ref(hint, -1); 05129 ao2_unlock(hints); 05130 05131 return id; 05132 }
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 5157 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().
05158 { 05159 struct ast_state_cb *p_cur; 05160 int ret = -1; 05161 05162 if (!id) { /* id == 0 is a callback without extension */ 05163 if (!change_cb) { 05164 return ret; 05165 } 05166 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 05167 if (p_cur) { 05168 ret = 0; 05169 ao2_ref(p_cur, -1); 05170 } 05171 } else { /* callback with extension, find the callback based on ID */ 05172 struct ast_hint *hint; 05173 05174 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05175 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 05176 if (hint) { 05177 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 05178 if (p_cur) { 05179 ret = 0; 05180 ao2_ref(p_cur, -1); 05181 } 05182 ao2_ref(hint, -1); 05183 } 05184 ao2_unlock(hints); 05185 } 05186 05187 return ret; 05188 }
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 5405 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().
05406 { 05407 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05408 }
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 5410 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05411 { 05412 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05413 }
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 4177 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().
04178 { 04179 char *copy = ast_strdupa(function); 04180 char *args = func_args(copy); 04181 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04182 int res; 04183 struct ast_module_user *u = NULL; 04184 04185 if (acfptr == NULL) { 04186 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04187 } else if (!acfptr->read && !acfptr->read2) { 04188 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04189 } else if (!is_read_allowed(acfptr)) { 04190 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04191 } else if (acfptr->read) { 04192 if (acfptr->mod) { 04193 u = __ast_module_user_add(acfptr->mod, chan); 04194 } 04195 res = acfptr->read(chan, copy, args, workspace, len); 04196 if (acfptr->mod && u) { 04197 __ast_module_user_remove(acfptr->mod, u); 04198 } 04199 return res; 04200 } else { 04201 struct ast_str *str = ast_str_create(16); 04202 if (acfptr->mod) { 04203 u = __ast_module_user_add(acfptr->mod, chan); 04204 } 04205 res = acfptr->read2(chan, copy, args, &str, 0); 04206 if (acfptr->mod && u) { 04207 __ast_module_user_remove(acfptr->mod, u); 04208 } 04209 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 04210 ast_free(str); 04211 return res; 04212 } 04213 return -1; 04214 }
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 4216 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().
04217 { 04218 char *copy = ast_strdupa(function); 04219 char *args = func_args(copy); 04220 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04221 int res; 04222 struct ast_module_user *u = NULL; 04223 04224 if (acfptr == NULL) { 04225 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04226 } else if (!acfptr->read && !acfptr->read2) { 04227 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04228 } else if (!is_read_allowed(acfptr)) { 04229 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04230 } else { 04231 if (acfptr->mod) { 04232 u = __ast_module_user_add(acfptr->mod, chan); 04233 } 04234 ast_str_reset(*str); 04235 if (acfptr->read2) { 04236 /* ast_str enabled */ 04237 res = acfptr->read2(chan, copy, args, str, maxlen); 04238 } else { 04239 /* Legacy function pointer, allocate buffer for result */ 04240 int maxsize = ast_str_size(*str); 04241 if (maxlen > -1) { 04242 if (maxlen == 0) { 04243 if (acfptr->read_max) { 04244 maxsize = acfptr->read_max; 04245 } else { 04246 maxsize = VAR_BUF_SIZE; 04247 } 04248 } else { 04249 maxsize = maxlen; 04250 } 04251 ast_str_make_space(str, maxsize); 04252 } 04253 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 04254 } 04255 if (acfptr->mod && u) { 04256 __ast_module_user_remove(acfptr->mod, u); 04257 } 04258 return res; 04259 } 04260 return -1; 04261 }
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 4263 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().
04264 { 04265 char *copy = ast_strdupa(function); 04266 char *args = func_args(copy); 04267 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04268 04269 if (acfptr == NULL) { 04270 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04271 } else if (!acfptr->write) { 04272 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 04273 } else if (!is_write_allowed(acfptr)) { 04274 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy); 04275 } else { 04276 int res; 04277 struct ast_module_user *u = NULL; 04278 if (acfptr->mod) 04279 u = __ast_module_user_add(acfptr->mod, chan); 04280 res = acfptr->write(chan, copy, args, value); 04281 if (acfptr->mod && u) 04282 __ast_module_user_remove(acfptr->mod, u); 04283 return res; 04284 } 04285 04286 return -1; 04287 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 11073 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().
11074 { 11075 return con ? con->name : NULL; 11076 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 11111 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
11112 { 11113 return c ? c->registrar : NULL; 11114 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 11141 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().
11142 { 11143 return e ? e->app : NULL; 11144 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 11146 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().
11147 { 11148 return e ? e->data : NULL; 11149 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 11136 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
11137 { 11138 return e ? e->cidmatch : NULL; 11139 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 11078 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().
11079 { 11080 return exten ? exten->parent : NULL; 11081 }
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 11088 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11089 { 11090 return exten ? exten->label : NULL; 11091 }
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 11131 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
11132 { 11133 return e ? e->matchcid : 0; 11134 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 11083 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().
11084 { 11085 return exten ? exten->exten : NULL; 11086 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 11103 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().
11104 { 11105 return exten ? exten->priority : -1; 11106 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 11116 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11117 { 11118 return e ? e->registrar : NULL; 11119 }
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 5362 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().
05363 { 05364 struct ast_exten *e = ast_hint_extension(c, context, exten); 05365 05366 if (e) { 05367 if (hint) 05368 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05369 if (name) { 05370 const char *tmp = ast_get_extension_app_data(e); 05371 if (tmp) 05372 ast_copy_string(name, tmp, namesize); 05373 } 05374 return -1; 05375 } 05376 return 0; 05377 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 11098 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().
11099 { 11100 return ip ? ip->pattern : NULL; 11101 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 11126 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().
11127 { 11128 return ip ? ip->registrar : NULL; 11129 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 11093 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().
11094 { 11095 return inc ? inc->name : NULL; 11096 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 11121 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().
11122 { 11123 return i ? i->registrar : NULL; 11124 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 11156 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().
11157 { 11158 return sw ? sw->data : NULL; 11159 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 11161 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
11162 { 11163 return sw->eval; 11164 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 11151 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().
11152 { 11153 return sw ? sw->name : NULL; 11154 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 11166 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().
11167 { 11168 return sw ? sw->registrar : NULL; 11169 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11261 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().
11262 { 11263 return __ast_goto_if_exists(chan, context, exten, priority, 0); 11264 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1136 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01137 { 01138 const struct ast_context *ac = ah_a; 01139 const struct ast_context *bc = ah_b; 01140 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01141 return 1; 01142 /* assume context names are registered in a string table! */ 01143 return strcmp(ac->name, bc->name); 01144 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1188 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().
01189 { 01190 const struct ast_context *ac = obj; 01191 return ast_hashtab_hash_string(ac->name); 01192 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static, read] |
Definition at line 4835 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().
04836 { 04837 struct ast_exten *e; 04838 ast_rdlock_contexts(); 04839 e = ast_hint_extension_nolock(c, context, exten); 04840 ast_unlock_contexts(); 04841 return e; 04842 }
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 4829 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().
04830 { 04831 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04832 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04833 }
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 8650 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().
08651 { 08652 struct ast_context *con = ast_context_find(context); 08653 08654 if (con) { 08655 struct ast_ignorepat *pat; 08656 08657 for (pat = con->ignorepats; pat; pat = pat->next) { 08658 if (ast_extension_match(pat->pattern, pattern)) 08659 return 1; 08660 } 08661 } 08662 08663 return 0; 08664 }
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 5420 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().
05421 { 05422 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05423 }
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 7937 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().
07938 { 07939 double ft; 07940 struct ast_context *tmp; 07941 struct ast_context *oldcontextslist; 07942 struct ast_hashtab *oldtable; 07943 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07944 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07945 struct store_hint *saved_hint; 07946 struct ast_hint *hint; 07947 struct ast_exten *exten; 07948 int length; 07949 struct ast_state_cb *thiscb; 07950 struct ast_hashtab_iter *iter; 07951 struct ao2_iterator i; 07952 struct timeval begintime; 07953 struct timeval writelocktime; 07954 struct timeval endlocktime; 07955 struct timeval enddeltime; 07956 07957 /* 07958 * It is very important that this function hold the hints 07959 * container lock _and_ the conlock during its operation; not 07960 * only do we need to ensure that the list of contexts and 07961 * extensions does not change, but also that no hint callbacks 07962 * (watchers) are added or removed during the merge/delete 07963 * process 07964 * 07965 * In addition, the locks _must_ be taken in this order, because 07966 * there are already other code paths that use this order 07967 */ 07968 07969 begintime = ast_tvnow(); 07970 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07971 ast_wrlock_contexts(); 07972 07973 if (!contexts_table) { 07974 /* Well, that's odd. There are no contexts. */ 07975 contexts_table = exttable; 07976 contexts = *extcontexts; 07977 ast_unlock_contexts(); 07978 ast_mutex_unlock(&context_merge_lock); 07979 return; 07980 } 07981 07982 iter = ast_hashtab_start_traversal(contexts_table); 07983 while ((tmp = ast_hashtab_next(iter))) { 07984 context_merge(extcontexts, exttable, tmp, registrar); 07985 } 07986 ast_hashtab_end_traversal(iter); 07987 07988 ao2_lock(hints); 07989 writelocktime = ast_tvnow(); 07990 07991 /* preserve all watchers for hints */ 07992 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07993 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07994 if (ao2_container_count(hint->callbacks)) { 07995 ao2_lock(hint); 07996 if (!hint->exten) { 07997 /* The extension has already been destroyed. (Should never happen here) */ 07998 ao2_unlock(hint); 07999 continue; 08000 } 08001 08002 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 08003 + sizeof(*saved_hint); 08004 if (!(saved_hint = ast_calloc(1, length))) { 08005 ao2_unlock(hint); 08006 continue; 08007 } 08008 08009 /* This removes all the callbacks from the hint into saved_hint. */ 08010 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 08011 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 08012 /* 08013 * We intentionally do not unref thiscb to account for the 08014 * non-ao2 reference in saved_hint->callbacks 08015 */ 08016 } 08017 08018 saved_hint->laststate = hint->laststate; 08019 saved_hint->context = saved_hint->data; 08020 strcpy(saved_hint->data, hint->exten->parent->name); 08021 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 08022 strcpy(saved_hint->exten, hint->exten->exten); 08023 ao2_unlock(hint); 08024 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 08025 } 08026 } 08027 ao2_iterator_destroy(&i); 08028 08029 /* save the old table and list */ 08030 oldtable = contexts_table; 08031 oldcontextslist = contexts; 08032 08033 /* move in the new table and list */ 08034 contexts_table = exttable; 08035 contexts = *extcontexts; 08036 08037 /* 08038 * Restore the watchers for hints that can be found; notify 08039 * those that cannot be restored. 08040 */ 08041 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 08042 struct pbx_find_info q = { .stacklen = 0 }; 08043 08044 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 08045 PRIORITY_HINT, NULL, "", E_MATCH); 08046 /* 08047 * If this is a pattern, dynamically create a new extension for this 08048 * particular match. Note that this will only happen once for each 08049 * individual extension, because the pattern will no longer match first. 08050 */ 08051 if (exten && exten->exten[0] == '_') { 08052 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 08053 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 08054 exten->registrar); 08055 /* rwlocks are not recursive locks */ 08056 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 08057 saved_hint->exten); 08058 } 08059 08060 /* Find the hint in the hints container */ 08061 hint = exten ? ao2_find(hints, exten, 0) : NULL; 08062 if (!hint) { 08063 /* 08064 * Notify watchers of this removed hint later when we aren't 08065 * encumberd by so many locks. 08066 */ 08067 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 08068 } else { 08069 ao2_lock(hint); 08070 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08071 ao2_link(hint->callbacks, thiscb); 08072 /* Ref that we added when putting into saved_hint->callbacks */ 08073 ao2_ref(thiscb, -1); 08074 } 08075 hint->laststate = saved_hint->laststate; 08076 ao2_unlock(hint); 08077 ao2_ref(hint, -1); 08078 ast_free(saved_hint); 08079 } 08080 } 08081 08082 ao2_unlock(hints); 08083 ast_unlock_contexts(); 08084 08085 /* 08086 * Notify watchers of all removed hints with the same lock 08087 * environment as handle_statechange(). 08088 */ 08089 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 08090 /* this hint has been removed, notify the watchers */ 08091 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08092 thiscb->change_cb(saved_hint->context, saved_hint->exten, 08093 AST_EXTENSION_REMOVED, thiscb->data); 08094 /* Ref that we added when putting into saved_hint->callbacks */ 08095 ao2_ref(thiscb, -1); 08096 } 08097 ast_free(saved_hint); 08098 } 08099 08100 ast_mutex_unlock(&context_merge_lock); 08101 endlocktime = ast_tvnow(); 08102 08103 /* 08104 * The old list and hashtab no longer are relevant, delete them 08105 * while the rest of asterisk is now freely using the new stuff 08106 * instead. 08107 */ 08108 08109 ast_hashtab_destroy(oldtable, NULL); 08110 08111 for (tmp = oldcontextslist; tmp; ) { 08112 struct ast_context *next; /* next starting point */ 08113 08114 next = tmp->next; 08115 __ast_internal_context_destroy(tmp); 08116 tmp = next; 08117 } 08118 enddeltime = ast_tvnow(); 08119 08120 ft = ast_tvdiff_us(writelocktime, begintime); 08121 ft /= 1000000.0; 08122 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 08123 08124 ft = ast_tvdiff_us(endlocktime, writelocktime); 08125 ft /= 1000000.0; 08126 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 08127 08128 ft = ast_tvdiff_us(enddeltime, endlocktime); 08129 ft /= 1000000.0; 08130 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 08131 08132 ft = ast_tvdiff_us(enddeltime, begintime); 08133 ft /= 1000000.0; 08134 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 08135 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11326 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().
11327 { 11328 return pbx_parseable_goto(chan, goto_string, 0); 11329 }
int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 11407 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().
11408 { 11409 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 11410 statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); 11411 11412 ast_register_atexit(pbx_shutdown); 11413 11414 return (hints && statecbs) ? 0 : -1; 11415 }
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 9544 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().
09545 { 09546 struct ast_channel *chan; 09547 struct app_tmp *tmp; 09548 int res = -1, cdr_res = -1; 09549 struct outgoing_helper oh; 09550 09551 memset(&oh, 0, sizeof(oh)); 09552 oh.vars = vars; 09553 oh.account = account; 09554 09555 if (locked_channel) 09556 *locked_channel = NULL; 09557 if (ast_strlen_zero(app)) { 09558 res = -1; 09559 goto outgoing_app_cleanup; 09560 } 09561 if (synchronous) { 09562 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09563 if (chan) { 09564 ast_set_variables(chan, vars); 09565 if (account) 09566 ast_cdr_setaccount(chan, account); 09567 if (chan->_state == AST_STATE_UP) { 09568 res = 0; 09569 ast_verb(4, "Channel %s was answered.\n", chan->name); 09570 tmp = ast_calloc(1, sizeof(*tmp)); 09571 if (!tmp || ast_string_field_init(tmp, 252)) { 09572 if (tmp) { 09573 ast_free(tmp); 09574 } 09575 res = -1; 09576 } else { 09577 ast_string_field_set(tmp, app, app); 09578 ast_string_field_set(tmp, data, appdata); 09579 tmp->chan = chan; 09580 if (synchronous > 1) { 09581 if (locked_channel) 09582 ast_channel_unlock(chan); 09583 ast_pbx_run_app(tmp); 09584 } else { 09585 if (locked_channel) 09586 ast_channel_lock(chan); 09587 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09588 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09589 ast_string_field_free_memory(tmp); 09590 ast_free(tmp); 09591 if (locked_channel) 09592 ast_channel_unlock(chan); 09593 ast_hangup(chan); 09594 res = -1; 09595 } else { 09596 if (locked_channel) 09597 *locked_channel = chan; 09598 } 09599 } 09600 } 09601 } else { 09602 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09603 if (chan->cdr) { /* update the cdr */ 09604 /* here we update the status of the call, which sould be busy. 09605 * if that fails then we set the status to failed */ 09606 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09607 ast_cdr_failed(chan->cdr); 09608 } 09609 ast_hangup(chan); 09610 } 09611 } 09612 09613 if (res < 0) { /* the call failed for some reason */ 09614 if (*reason == 0) { /* if the call failed (not busy or no answer) 09615 * update the cdr with the failed message */ 09616 cdr_res = ast_pbx_outgoing_cdr_failed(); 09617 if (cdr_res != 0) { 09618 res = cdr_res; 09619 goto outgoing_app_cleanup; 09620 } 09621 } 09622 } 09623 09624 } else { 09625 struct async_stat *as; 09626 if (!(as = ast_calloc(1, sizeof(*as)))) { 09627 res = -1; 09628 goto outgoing_app_cleanup; 09629 } 09630 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09631 if (!chan) { 09632 ast_free(as); 09633 res = -1; 09634 goto outgoing_app_cleanup; 09635 } 09636 as->chan = chan; 09637 ast_copy_string(as->app, app, sizeof(as->app)); 09638 if (appdata) 09639 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09640 as->timeout = timeout; 09641 ast_set_variables(chan, vars); 09642 if (account) 09643 ast_cdr_setaccount(chan, account); 09644 /* Start a new thread, and get something handling this channel. */ 09645 if (locked_channel) 09646 ast_channel_lock(chan); 09647 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09648 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09649 ast_free(as); 09650 if (locked_channel) 09651 ast_channel_unlock(chan); 09652 ast_hangup(chan); 09653 res = -1; 09654 goto outgoing_app_cleanup; 09655 } else { 09656 if (locked_channel) 09657 *locked_channel = chan; 09658 } 09659 res = 0; 09660 } 09661 outgoing_app_cleanup: 09662 ast_variables_destroy(vars); 09663 return res; 09664 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 9348 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().
09349 { 09350 /* allocate a channel */ 09351 struct ast_channel *chan = ast_dummy_channel_alloc(); 09352 09353 if (!chan) 09354 return -1; /* failure */ 09355 09356 chan->cdr = ast_cdr_alloc(); 09357 if (!chan->cdr) { 09358 /* allocation of the cdr failed */ 09359 chan = ast_channel_unref(chan); /* free the channel */ 09360 return -1; /* return failure */ 09361 } 09362 09363 /* allocation of the cdr was successful */ 09364 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 09365 ast_cdr_start(chan->cdr); /* record the start and stop time */ 09366 ast_cdr_end(chan->cdr); 09367 ast_cdr_failed(chan->cdr); /* set the status to failed */ 09368 ast_cdr_detach(chan->cdr); /* post and free the record */ 09369 chan->cdr = NULL; 09370 chan = ast_channel_unref(chan); /* free the channel */ 09371 09372 return 0; /* success */ 09373 }
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 9375 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().
09376 { 09377 struct ast_channel *chan; 09378 struct async_stat *as; 09379 int res = -1, cdr_res = -1; 09380 struct outgoing_helper oh; 09381 09382 if (synchronous) { 09383 oh.context = context; 09384 oh.exten = exten; 09385 oh.priority = priority; 09386 oh.cid_num = cid_num; 09387 oh.cid_name = cid_name; 09388 oh.account = account; 09389 oh.vars = vars; 09390 oh.parent_channel = NULL; 09391 09392 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09393 if (channel) { 09394 *channel = chan; 09395 if (chan) 09396 ast_channel_lock(chan); 09397 } 09398 if (chan) { 09399 if (chan->_state == AST_STATE_UP) { 09400 res = 0; 09401 ast_verb(4, "Channel %s was answered.\n", chan->name); 09402 09403 if (synchronous > 1) { 09404 if (channel) 09405 ast_channel_unlock(chan); 09406 if (ast_pbx_run(chan)) { 09407 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09408 if (channel) 09409 *channel = NULL; 09410 ast_hangup(chan); 09411 chan = NULL; 09412 res = -1; 09413 } 09414 } else { 09415 if (ast_pbx_start(chan)) { 09416 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09417 if (channel) { 09418 *channel = NULL; 09419 ast_channel_unlock(chan); 09420 } 09421 ast_hangup(chan); 09422 res = -1; 09423 } 09424 chan = NULL; 09425 } 09426 } else { 09427 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09428 09429 if (chan->cdr) { /* update the cdr */ 09430 /* here we update the status of the call, which sould be busy. 09431 * if that fails then we set the status to failed */ 09432 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09433 ast_cdr_failed(chan->cdr); 09434 } 09435 09436 if (channel) { 09437 *channel = NULL; 09438 ast_channel_unlock(chan); 09439 } 09440 ast_hangup(chan); 09441 chan = NULL; 09442 } 09443 } 09444 09445 if (res < 0) { /* the call failed for some reason */ 09446 if (*reason == 0) { /* if the call failed (not busy or no answer) 09447 * update the cdr with the failed message */ 09448 cdr_res = ast_pbx_outgoing_cdr_failed(); 09449 if (cdr_res != 0) { 09450 res = cdr_res; 09451 goto outgoing_exten_cleanup; 09452 } 09453 } 09454 09455 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09456 /* check if "failed" exists */ 09457 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09458 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09459 if (chan) { 09460 char failed_reason[4] = ""; 09461 if (!ast_strlen_zero(context)) 09462 ast_copy_string(chan->context, context, sizeof(chan->context)); 09463 set_ext_pri(chan, "failed", 1); 09464 ast_set_variables(chan, vars); 09465 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09466 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09467 if (account) 09468 ast_cdr_setaccount(chan, account); 09469 if (ast_pbx_run(chan)) { 09470 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09471 ast_hangup(chan); 09472 } 09473 chan = NULL; 09474 } 09475 } 09476 } 09477 } else { 09478 if (!(as = ast_calloc(1, sizeof(*as)))) { 09479 res = -1; 09480 goto outgoing_exten_cleanup; 09481 } 09482 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09483 if (channel) { 09484 *channel = chan; 09485 if (chan) 09486 ast_channel_lock(chan); 09487 } 09488 if (!chan) { 09489 ast_free(as); 09490 res = -1; 09491 goto outgoing_exten_cleanup; 09492 } 09493 as->chan = chan; 09494 ast_copy_string(as->context, context, sizeof(as->context)); 09495 set_ext_pri(as->chan, exten, priority); 09496 as->timeout = timeout; 09497 ast_set_variables(chan, vars); 09498 if (account) 09499 ast_cdr_setaccount(chan, account); 09500 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09501 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09502 ast_free(as); 09503 if (channel) { 09504 *channel = NULL; 09505 ast_channel_unlock(chan); 09506 } 09507 ast_hangup(chan); 09508 res = -1; 09509 goto outgoing_exten_cleanup; 09510 } 09511 res = 0; 09512 } 09513 outgoing_exten_cleanup: 09514 ast_variables_destroy(vars); 09515 return res; 09516 }
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 5926 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().
05927 { 05928 return ast_pbx_run_args(c, NULL); 05929 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 9528 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().
09529 { 09530 struct app_tmp *tmp = data; 09531 struct ast_app *app; 09532 app = pbx_findapp(tmp->app); 09533 if (app) { 09534 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 09535 pbx_exec(tmp->chan, app, tmp->data); 09536 } else 09537 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 09538 ast_hangup(tmp->chan); 09539 ast_string_field_free_memory(tmp); 09540 ast_free(tmp); 09541 return NULL; 09542 }
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 5906 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().
05907 { 05908 enum ast_pbx_result res = AST_PBX_SUCCESS; 05909 05910 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05911 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05912 return AST_PBX_FAILED; 05913 } 05914 05915 if (increase_call_count(c)) { 05916 return AST_PBX_CALL_LIMIT; 05917 } 05918 05919 res = __ast_pbx_run(c, args); 05920 05921 decrease_call_count(); 05922 05923 return res; 05924 }
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 5879 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().
05880 { 05881 pthread_t t; 05882 05883 if (!c) { 05884 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05885 return AST_PBX_FAILED; 05886 } 05887 05888 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05889 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05890 return AST_PBX_FAILED; 05891 } 05892 05893 if (increase_call_count(c)) 05894 return AST_PBX_CALL_LIMIT; 05895 05896 /* Start a new thread, and get something handling this channel. */ 05897 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05898 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05899 decrease_call_count(); 05900 return AST_PBX_FAILED; 05901 } 05902 05903 return AST_PBX_SUCCESS; 05904 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5936 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05937 { 05938 return totalcalls; 05939 }
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 11060 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().
11061 { 11062 return ast_rwlock_rdlock(&con->lock); 11063 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 11042 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().
11043 { 11044 return ast_mutex_lock(&conlock); 11045 }
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 6344 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().
06345 { 06346 struct ast_app *tmp, *cur = NULL; 06347 char tmps[80]; 06348 int length, res; 06349 #ifdef AST_XML_DOCS 06350 char *tmpxml; 06351 #endif 06352 06353 AST_RWLIST_WRLOCK(&apps); 06354 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 06355 if (!(res = strcasecmp(app, tmp->name))) { 06356 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 06357 AST_RWLIST_UNLOCK(&apps); 06358 return -1; 06359 } else if (res < 0) 06360 break; 06361 } 06362 06363 length = sizeof(*tmp) + strlen(app) + 1; 06364 06365 if (!(tmp = ast_calloc(1, length))) { 06366 AST_RWLIST_UNLOCK(&apps); 06367 return -1; 06368 } 06369 06370 if (ast_string_field_init(tmp, 128)) { 06371 AST_RWLIST_UNLOCK(&apps); 06372 ast_free(tmp); 06373 return -1; 06374 } 06375 06376 strcpy(tmp->name, app); 06377 tmp->execute = execute; 06378 tmp->module = mod; 06379 06380 #ifdef AST_XML_DOCS 06381 /* Try to lookup the docs in our XML documentation database */ 06382 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 06383 /* load synopsis */ 06384 tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module)); 06385 ast_string_field_set(tmp, synopsis, tmpxml); 06386 ast_free(tmpxml); 06387 06388 /* load description */ 06389 tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); 06390 ast_string_field_set(tmp, description, tmpxml); 06391 ast_free(tmpxml); 06392 06393 /* load syntax */ 06394 tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module)); 06395 ast_string_field_set(tmp, syntax, tmpxml); 06396 ast_free(tmpxml); 06397 06398 /* load arguments */ 06399 tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module)); 06400 ast_string_field_set(tmp, arguments, tmpxml); 06401 ast_free(tmpxml); 06402 06403 /* load seealso */ 06404 tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module)); 06405 ast_string_field_set(tmp, seealso, tmpxml); 06406 ast_free(tmpxml); 06407 tmp->docsrc = AST_XML_DOC; 06408 } else { 06409 #endif 06410 ast_string_field_set(tmp, synopsis, synopsis); 06411 ast_string_field_set(tmp, description, description); 06412 #ifdef AST_XML_DOCS 06413 tmp->docsrc = AST_STATIC_DOC; 06414 } 06415 #endif 06416 06417 /* Store in alphabetical order */ 06418 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 06419 if (strcasecmp(tmp->name, cur->name) < 0) { 06420 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 06421 break; 06422 } 06423 } 06424 AST_RWLIST_TRAVERSE_SAFE_END; 06425 if (!cur) 06426 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 06427 06428 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 06429 06430 AST_RWLIST_UNLOCK(&apps); 06431 06432 return 0; 06433 }
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 6439 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().
06440 { 06441 struct ast_switch *tmp; 06442 06443 AST_RWLIST_WRLOCK(&switches); 06444 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06445 if (!strcasecmp(tmp->name, sw->name)) { 06446 AST_RWLIST_UNLOCK(&switches); 06447 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06448 return -1; 06449 } 06450 } 06451 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06452 AST_RWLIST_UNLOCK(&switches); 06453 06454 return 0; 06455 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 5237 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().
05238 { 05239 /* Cleanup the Notifys if hint is removed */ 05240 struct ast_hint *hint; 05241 05242 if (!e) { 05243 return -1; 05244 } 05245 05246 hint = ao2_find(hints, e, OBJ_UNLINK); 05247 if (!hint) { 05248 return -1; 05249 } 05250 05251 /* 05252 * The extension is being destroyed so we must save some 05253 * information to notify that the extension is deactivated. 05254 */ 05255 ao2_lock(hint); 05256 ast_copy_string(hint->context_name, 05257 ast_get_context_name(ast_get_extension_context(hint->exten)), 05258 sizeof(hint->context_name)); 05259 ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten), 05260 sizeof(hint->exten_name)); 05261 hint->exten = NULL; 05262 ao2_unlock(hint); 05263 05264 ao2_ref(hint, -1); 05265 05266 return 0; 05267 }
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 5425 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().
05426 { 05427 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05428 }
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 5380 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().
05381 { 05382 struct ast_exten *e = ast_hint_extension(c, context, exten); 05383 05384 if (!e) { 05385 return 0; 05386 } 05387 05388 if (hint) { 05389 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05390 } 05391 if (name) { 05392 const char *tmp = ast_get_extension_app_data(e); 05393 if (tmp) { 05394 ast_str_set(name, namesize, "%s", tmp); 05395 } 05396 } 05397 return -1; 05398 }
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 3445 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().
03446 { 03447 const char not_found = '\0'; 03448 char *tmpvar; 03449 const char *ret; 03450 const char *s; /* the result */ 03451 int offset, length; 03452 int i, need_substring; 03453 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03454 char workspace[20]; 03455 03456 if (c) { 03457 ast_channel_lock(c); 03458 places[0] = &c->varshead; 03459 } 03460 /* 03461 * Make a copy of var because parse_variable_name() modifies the string. 03462 * Then if called directly, we might need to run substring() on the result; 03463 * remember this for later in 'need_substring', 'offset' and 'length' 03464 */ 03465 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03466 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03467 03468 /* 03469 * Look first into predefined variables, then into variable lists. 03470 * Variable 's' points to the result, according to the following rules: 03471 * s == ¬_found (set at the beginning) means that we did not find a 03472 * matching variable and need to look into more places. 03473 * If s != ¬_found, s is a valid result string as follows: 03474 * s = NULL if the variable does not have a value; 03475 * you typically do this when looking for an unset predefined variable. 03476 * s = workspace if the result has been assembled there; 03477 * typically done when the result is built e.g. with an snprintf(), 03478 * so we don't need to do an additional copy. 03479 * s != workspace in case we have a string, that needs to be copied 03480 * (the ast_copy_string is done once for all at the end). 03481 * Typically done when the result is already available in some string. 03482 */ 03483 s = ¬_found; /* default value */ 03484 if (c) { /* This group requires a valid channel */ 03485 /* Names with common parts are looked up a piece at a time using strncmp. */ 03486 if (!strncmp(var, "CALL", 4)) { 03487 if (!strncmp(var + 4, "ING", 3)) { 03488 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03489 ast_str_set(str, maxlen, "%d", 03490 ast_party_id_presentation(&c->caller.id)); 03491 s = ast_str_buffer(*str); 03492 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03493 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03494 s = ast_str_buffer(*str); 03495 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03496 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03497 s = ast_str_buffer(*str); 03498 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03499 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03500 s = ast_str_buffer(*str); 03501 } 03502 } 03503 } else if (!strcmp(var, "HINT")) { 03504 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03505 } else if (!strcmp(var, "HINTNAME")) { 03506 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03507 } else if (!strcmp(var, "EXTEN")) { 03508 s = c->exten; 03509 } else if (!strcmp(var, "CONTEXT")) { 03510 s = c->context; 03511 } else if (!strcmp(var, "PRIORITY")) { 03512 ast_str_set(str, maxlen, "%d", c->priority); 03513 s = ast_str_buffer(*str); 03514 } else if (!strcmp(var, "CHANNEL")) { 03515 s = c->name; 03516 } else if (!strcmp(var, "UNIQUEID")) { 03517 s = c->uniqueid; 03518 } else if (!strcmp(var, "HANGUPCAUSE")) { 03519 ast_str_set(str, maxlen, "%d", c->hangupcause); 03520 s = ast_str_buffer(*str); 03521 } 03522 } 03523 if (s == ¬_found) { /* look for more */ 03524 if (!strcmp(var, "EPOCH")) { 03525 ast_str_set(str, maxlen, "%d", (int) time(NULL)); 03526 s = ast_str_buffer(*str); 03527 } else if (!strcmp(var, "SYSTEMNAME")) { 03528 s = ast_config_AST_SYSTEM_NAME; 03529 } else if (!strcmp(var, "ENTITYID")) { 03530 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03531 s = workspace; 03532 } 03533 } 03534 /* if not found, look into chanvars or global vars */ 03535 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03536 struct ast_var_t *variables; 03537 if (!places[i]) 03538 continue; 03539 if (places[i] == &globals) 03540 ast_rwlock_rdlock(&globalslock); 03541 AST_LIST_TRAVERSE(places[i], variables, entries) { 03542 if (!strcasecmp(ast_var_name(variables), var)) { 03543 s = ast_var_value(variables); 03544 break; 03545 } 03546 } 03547 if (places[i] == &globals) 03548 ast_rwlock_unlock(&globalslock); 03549 } 03550 if (s == ¬_found || s == NULL) { 03551 ast_debug(5, "Result of '%s' is NULL\n", var); 03552 ret = NULL; 03553 } else { 03554 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03555 if (s != ast_str_buffer(*str)) { 03556 ast_str_set(str, maxlen, "%s", s); 03557 } 03558 ret = ast_str_buffer(*str); 03559 if (need_substring) { 03560 ret = ast_str_substring(*str, offset, length); 03561 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03562 } 03563 } 03564 03565 if (c) { 03566 ast_channel_unlock(c); 03567 } 03568 return ret; 03569 }
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 4468 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().
04469 { 04470 size_t used; 04471 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04472 }
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 4289 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().
04290 { 04291 /* Substitutes variables into buf, based on string templ */ 04292 char *cp4 = NULL; 04293 const char *tmp, *whereweare; 04294 int orig_size = 0; 04295 int offset, offset2, isfunction; 04296 const char *nextvar, *nextexp, *nextthing; 04297 const char *vars, *vare; 04298 char *finalvars; 04299 int pos, brackets, needsub, len; 04300 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04301 04302 ast_str_reset(*buf); 04303 whereweare = tmp = templ; 04304 while (!ast_strlen_zero(whereweare)) { 04305 /* reset our buffer */ 04306 ast_str_reset(substr3); 04307 04308 /* Assume we're copying the whole remaining string */ 04309 pos = strlen(whereweare); 04310 nextvar = NULL; 04311 nextexp = NULL; 04312 nextthing = strchr(whereweare, '$'); 04313 if (nextthing) { 04314 switch (nextthing[1]) { 04315 case '{': 04316 nextvar = nextthing; 04317 pos = nextvar - whereweare; 04318 break; 04319 case '[': 04320 nextexp = nextthing; 04321 pos = nextexp - whereweare; 04322 break; 04323 default: 04324 pos = 1; 04325 } 04326 } 04327 04328 if (pos) { 04329 /* Copy that many bytes */ 04330 ast_str_append_substr(buf, maxlen, whereweare, pos); 04331 04332 templ += pos; 04333 whereweare += pos; 04334 } 04335 04336 if (nextvar) { 04337 /* We have a variable. Find the start and end, and determine 04338 if we are going to have to recursively call ourselves on the 04339 contents */ 04340 vars = vare = nextvar + 2; 04341 brackets = 1; 04342 needsub = 0; 04343 04344 /* Find the end of it */ 04345 while (brackets && *vare) { 04346 if ((vare[0] == '$') && (vare[1] == '{')) { 04347 needsub++; 04348 } else if (vare[0] == '{') { 04349 brackets++; 04350 } else if (vare[0] == '}') { 04351 brackets--; 04352 } else if ((vare[0] == '$') && (vare[1] == '[')) 04353 needsub++; 04354 vare++; 04355 } 04356 if (brackets) 04357 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04358 len = vare - vars - 1; 04359 04360 /* Skip totally over variable string */ 04361 whereweare += (len + 3); 04362 04363 /* Store variable name (and truncate) */ 04364 ast_str_set_substr(&substr1, 0, vars, len); 04365 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04366 04367 /* Substitute if necessary */ 04368 if (needsub) { 04369 size_t used; 04370 if (!substr2) { 04371 substr2 = ast_str_create(16); 04372 } 04373 04374 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04375 finalvars = ast_str_buffer(substr2); 04376 } else { 04377 finalvars = ast_str_buffer(substr1); 04378 } 04379 04380 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04381 if (isfunction) { 04382 /* Evaluate function */ 04383 if (c || !headp) { 04384 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04385 } else { 04386 struct varshead old; 04387 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04388 if (bogus) { 04389 memcpy(&old, &bogus->varshead, sizeof(old)); 04390 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04391 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04392 /* Don't deallocate the varshead that was passed in */ 04393 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04394 ast_channel_unref(bogus); 04395 } else { 04396 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04397 } 04398 } 04399 ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)"); 04400 } else { 04401 /* Retrieve variable value */ 04402 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04403 cp4 = ast_str_buffer(substr3); 04404 } 04405 if (cp4) { 04406 ast_str_substring(substr3, offset, offset2); 04407 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04408 } 04409 } else if (nextexp) { 04410 /* We have an expression. Find the start and end, and determine 04411 if we are going to have to recursively call ourselves on the 04412 contents */ 04413 vars = vare = nextexp + 2; 04414 brackets = 1; 04415 needsub = 0; 04416 04417 /* Find the end of it */ 04418 while (brackets && *vare) { 04419 if ((vare[0] == '$') && (vare[1] == '[')) { 04420 needsub++; 04421 brackets++; 04422 vare++; 04423 } else if (vare[0] == '[') { 04424 brackets++; 04425 } else if (vare[0] == ']') { 04426 brackets--; 04427 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04428 needsub++; 04429 vare++; 04430 } 04431 vare++; 04432 } 04433 if (brackets) 04434 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04435 len = vare - vars - 1; 04436 04437 /* Skip totally over expression */ 04438 whereweare += (len + 3); 04439 04440 /* Store variable name (and truncate) */ 04441 ast_str_set_substr(&substr1, 0, vars, len); 04442 04443 /* Substitute if necessary */ 04444 if (needsub) { 04445 size_t used; 04446 if (!substr2) { 04447 substr2 = ast_str_create(16); 04448 } 04449 04450 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04451 finalvars = ast_str_buffer(substr2); 04452 } else { 04453 finalvars = ast_str_buffer(substr1); 04454 } 04455 04456 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04457 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04458 } 04459 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04460 } 04461 } 04462 *used = ast_str_strlen(*buf) - orig_size; 04463 ast_free(substr1); 04464 ast_free(substr2); 04465 ast_free(substr3); 04466 }
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 4474 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().
04475 { 04476 size_t used; 04477 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04478 }
static const char* ast_str_substring | ( | struct ast_str * | value, | |
int | offset, | |||
int | length | |||
) | [static] |
Definition at line 3380 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().
03381 { 03382 int lr; /* length of the input string after the copy */ 03383 03384 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 03385 03386 /* Quick check if no need to do anything */ 03387 if (offset == 0 && length >= lr) /* take the whole string */ 03388 return ast_str_buffer(value); 03389 03390 if (offset < 0) { /* translate negative offset into positive ones */ 03391 offset = lr + offset; 03392 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03393 offset = 0; 03394 } 03395 03396 /* too large offset result in empty string so we know what to return */ 03397 if (offset >= lr) { 03398 ast_str_reset(value); 03399 return ast_str_buffer(value); 03400 } 03401 03402 if (offset > 0) { 03403 /* Go ahead and chop off the beginning */ 03404 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 03405 lr -= offset; 03406 } 03407 03408 if (length >= 0 && length < lr) { /* truncate if necessary */ 03409 char *tmp = ast_str_buffer(value); 03410 tmp[length] = '\0'; 03411 ast_str_update(value); 03412 } else if (length < 0) { 03413 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 03414 char *tmp = ast_str_buffer(value); 03415 tmp[lr + length] = '\0'; 03416 ast_str_update(value); 03417 } else { 03418 ast_str_reset(value); 03419 } 03420 } else { 03421 /* Nothing to do, but update the buffer length */ 03422 ast_str_update(value); 03423 } 03424 03425 return ast_str_buffer(value); 03426 }
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 4072 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by handle_tcptls_connection().
04073 { 04074 int *thread_inhibit_escalations; 04075 04076 thread_inhibit_escalations = ast_threadstorage_get( 04077 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04078 04079 if (thread_inhibit_escalations == NULL) { 04080 ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n"); 04081 return -1; 04082 } 04083 04084 *thread_inhibit_escalations = 1; 04085 return 0; 04086 }
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 11065 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().
11066 { 11067 return ast_rwlock_unlock(&con->lock); 11068 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 11047 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().
11048 { 11049 return ast_mutex_unlock(&conlock); 11050 }
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 7705 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().
07706 { 07707 struct ast_app *tmp; 07708 07709 AST_RWLIST_WRLOCK(&apps); 07710 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 07711 if (!strcasecmp(app, tmp->name)) { 07712 unreference_cached_app(tmp); 07713 AST_RWLIST_REMOVE_CURRENT(list); 07714 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 07715 ast_string_field_free_memory(tmp); 07716 ast_free(tmp); 07717 break; 07718 } 07719 } 07720 AST_RWLIST_TRAVERSE_SAFE_END; 07721 AST_RWLIST_UNLOCK(&apps); 07722 07723 return tmp ? 0 : -1; 07724 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6457 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06458 { 06459 AST_RWLIST_WRLOCK(&switches); 06460 AST_RWLIST_REMOVE(&switches, sw, list); 06461 AST_RWLIST_UNLOCK(&switches); 06462 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) | [read] |
Definition at line 11179 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 11212 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().
11214 { 11215 if (!ip) 11216 return con ? con->ignorepats : NULL; 11217 else 11218 return ip->next; 11219 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 11203 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 11188 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().
11190 { 11191 if (!sw) 11192 return con ? AST_LIST_FIRST(&con->alts) : NULL; 11193 else 11194 return AST_LIST_NEXT(sw, list); 11195 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 11174 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 11197 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().
11199 { 11200 return priority ? priority->peer : exten; 11201 }
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 11055 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().
11056 { 11057 return ast_rwlock_wrlock(&con->lock); 11058 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 11037 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().
11038 { 11039 return ast_mutex_lock(&conlock); 11040 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 9285 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().
09286 { 09287 struct async_stat *as = data; 09288 struct ast_channel *chan = as->chan; 09289 int timeout = as->timeout; 09290 int res; 09291 struct ast_frame *f; 09292 struct ast_app *app; 09293 struct timeval start = ast_tvnow(); 09294 int ms; 09295 09296 while ((ms = ast_remaining_ms(start, timeout)) && 09297 chan->_state != AST_STATE_UP) { 09298 res = ast_waitfor(chan, ms); 09299 if (res < 1) 09300 break; 09301 09302 f = ast_read(chan); 09303 if (!f) 09304 break; 09305 if (f->frametype == AST_FRAME_CONTROL) { 09306 if ((f->subclass.integer == AST_CONTROL_BUSY) || 09307 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 09308 ast_frfree(f); 09309 break; 09310 } 09311 } 09312 ast_frfree(f); 09313 } 09314 if (chan->_state == AST_STATE_UP) { 09315 if (!ast_strlen_zero(as->app)) { 09316 app = pbx_findapp(as->app); 09317 if (app) { 09318 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 09319 pbx_exec(chan, app, as->appdata); 09320 } else 09321 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 09322 } else { 09323 if (!ast_strlen_zero(as->context)) 09324 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 09325 if (!ast_strlen_zero(as->exten)) 09326 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 09327 if (as->priority > 0) 09328 chan->priority = as->priority; 09329 /* Run the PBX */ 09330 if (ast_pbx_run(chan)) { 09331 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 09332 } else { 09333 /* PBX will have taken care of this */ 09334 chan = NULL; 09335 } 09336 } 09337 } 09338 ast_free(as); 09339 if (chan) 09340 ast_hangup(chan); 09341 return NULL; 09342 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1699 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().
01700 { 01701 char extenstr[40]; 01702 struct ast_str *my_prefix = ast_str_alloca(1024); 01703 01704 extenstr[0] = '\0'; 01705 01706 if (node->exten) { 01707 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01708 } 01709 01710 if (strlen(node->x) > 1) { 01711 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01712 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01713 node->exten ? node->exten->exten : "", extenstr); 01714 } else { 01715 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01716 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01717 node->exten ? node->exten->exten : "", extenstr); 01718 } 01719 01720 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01721 01722 if (node->next_char) 01723 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01724 01725 if (node->alt_char) 01726 cli_match_char_tree(node->alt_char, prefix, fd); 01727 }
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 5446 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().
05447 { 05448 int digit; 05449 05450 buf[pos] = '\0'; /* make sure it is properly terminated */ 05451 while (ast_matchmore_extension(c, c->context, buf, 1, 05452 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05453 /* As long as we're willing to wait, and as long as it's not defined, 05454 keep reading digits until we can't possibly get a right answer anymore. */ 05455 digit = ast_waitfordigit(c, waittime); 05456 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05457 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05458 } else { 05459 if (!digit) /* No entry */ 05460 break; 05461 if (digit < 0) /* Error, maybe a hangup */ 05462 return -1; 05463 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 05464 buf[pos++] = digit; 05465 buf[pos] = '\0'; 05466 } 05467 waittime = c->pbx->dtimeoutms; 05468 } 05469 } 05470 return 0; 05471 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 1127 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 6649 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().
06650 { 06651 struct ast_hint *hint; 06652 char *ret = NULL; 06653 int which = 0; 06654 int wordlen; 06655 struct ao2_iterator i; 06656 06657 if (pos != 3) 06658 return NULL; 06659 06660 wordlen = strlen(word); 06661 06662 /* walk through all hints */ 06663 i = ao2_iterator_init(hints, 0); 06664 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06665 ao2_lock(hint); 06666 if (!hint->exten) { 06667 /* The extension has already been destroyed */ 06668 ao2_unlock(hint); 06669 continue; 06670 } 06671 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 06672 ret = ast_strdup(ast_get_extension_name(hint->exten)); 06673 ao2_unlock(hint); 06674 ao2_ref(hint, -1); 06675 break; 06676 } 06677 ao2_unlock(hint); 06678 } 06679 ao2_iterator_destroy(&i); 06680 06681 return ret; 06682 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 6865 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().
06867 { 06868 struct ast_context *c = NULL; 06869 char *ret = NULL; 06870 int which = 0; 06871 int wordlen; 06872 06873 /* we are do completion of [exten@]context on second position only */ 06874 if (pos != 2) 06875 return NULL; 06876 06877 ast_rdlock_contexts(); 06878 06879 wordlen = strlen(word); 06880 06881 /* walk through all contexts and return the n-th match */ 06882 while ( (c = ast_walk_contexts(c)) ) { 06883 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06884 ret = ast_strdup(ast_get_context_name(c)); 06885 break; 06886 } 06887 } 06888 06889 ast_unlock_contexts(); 06890 06891 return ret; 06892 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7846 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().
07847 { 07848 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 07849 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 07850 struct ast_hashtab_iter *exten_iter; 07851 struct ast_hashtab_iter *prio_iter; 07852 int insert_count = 0; 07853 int first = 1; 07854 07855 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 07856 the current registrar, and copy them to the new context. If the new context does not 07857 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 07858 only create the empty matching context if the old one meets the criteria */ 07859 07860 if (context->root_table) { 07861 exten_iter = ast_hashtab_start_traversal(context->root_table); 07862 while ((exten_item=ast_hashtab_next(exten_iter))) { 07863 if (new) { 07864 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 07865 } else { 07866 new_exten_item = NULL; 07867 } 07868 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07869 while ((prio_item=ast_hashtab_next(prio_iter))) { 07870 int res1; 07871 char *dupdstr; 07872 07873 if (new_exten_item) { 07874 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 07875 } else { 07876 new_prio_item = NULL; 07877 } 07878 if (strcmp(prio_item->registrar,registrar) == 0) { 07879 continue; 07880 } 07881 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 07882 if (!new) { 07883 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 */ 07884 } 07885 07886 /* copy in the includes, switches, and ignorepats */ 07887 if (first) { /* but, only need to do this once */ 07888 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07889 first = 0; 07890 } 07891 07892 if (!new) { 07893 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07894 ast_hashtab_end_traversal(prio_iter); 07895 ast_hashtab_end_traversal(exten_iter); 07896 return; /* no sense continuing. */ 07897 } 07898 /* we will not replace existing entries in the new context with stuff from the old context. 07899 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07900 07901 dupdstr = ast_strdup(prio_item->data); 07902 07903 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07904 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07905 if (!res1 && new_exten_item && new_prio_item){ 07906 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07907 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07908 } else { 07909 /* 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, 07910 and no double frees take place, either! */ 07911 insert_count++; 07912 } 07913 } 07914 ast_hashtab_end_traversal(prio_iter); 07915 } 07916 ast_hashtab_end_traversal(exten_iter); 07917 } else if (new) { 07918 /* If the context existed but had no extensions, we still want to merge 07919 * the includes, switches and ignore patterns. 07920 */ 07921 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07922 } 07923 07924 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07925 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07926 /* we could have given it the registrar of the other module who incremented the refcount, 07927 but that's not available, so we give it the registrar we know about */ 07928 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07929 07930 /* copy in the includes, switches, and ignorepats */ 07931 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07932 } 07933 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7813 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().
07814 { 07815 struct ast_include *i; 07816 struct ast_ignorepat *ip; 07817 struct ast_sw *sw; 07818 07819 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); 07820 /* copy in the includes, switches, and ignorepats */ 07821 /* walk through includes */ 07822 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 07823 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 07824 continue; /* not mine */ 07825 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 07826 } 07827 07828 /* walk through switches */ 07829 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 07830 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 07831 continue; /* not mine */ 07832 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)); 07833 } 07834 07835 /* walk thru ignorepats ... */ 07836 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 07837 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 07838 continue; /* not mine */ 07839 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 07840 } 07841 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2321 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().
02322 { 02323 struct ast_hashtab_iter *t1; 02324 struct ast_exten *e1; 02325 #ifdef NEED_DEBUG 02326 int biggest_bucket, resizes, numobjs, numbucks; 02327 02328 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02329 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02330 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02331 numobjs, numbucks, biggest_bucket, resizes); 02332 #endif 02333 t1 = ast_hashtab_start_traversal(con->root_table); 02334 while ((e1 = ast_hashtab_next(t1))) { 02335 if (e1->exten) { 02336 add_exten_to_pattern_tree(con, e1, 0); 02337 } else { 02338 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02339 } 02340 } 02341 ast_hashtab_end_traversal(t1); 02342 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 5837 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().
05838 { 05839 ast_mutex_lock(&maxcalllock); 05840 if (countcalls > 0) 05841 countcalls--; 05842 ast_mutex_unlock(&maxcalllock); 05843 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 5845 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().
05846 { 05847 if (e->priority == PRIORITY_HINT) 05848 ast_remove_hint(e); 05849 05850 if (e->peer_table) 05851 ast_hashtab_destroy(e->peer_table,0); 05852 if (e->peer_label_table) 05853 ast_hashtab_destroy(e->peer_label_table, 0); 05854 if (e->datad) 05855 e->datad(e->data); 05856 ast_free(e); 05857 }
static void destroy_hint | ( | void * | obj | ) | [static] |
Definition at line 5207 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().
05208 { 05209 struct ast_hint *hint = obj; 05210 05211 if (hint->callbacks) { 05212 struct ast_state_cb *state_cb; 05213 const char *context_name; 05214 const char *exten_name; 05215 05216 if (hint->exten) { 05217 context_name = ast_get_context_name(ast_get_extension_context(hint->exten)); 05218 exten_name = ast_get_extension_name(hint->exten); 05219 hint->exten = NULL; 05220 } else { 05221 /* The extension has already been destroyed */ 05222 context_name = hint->context_name; 05223 exten_name = hint->exten_name; 05224 } 05225 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 05226 /* Notify with -1 and remove all callbacks */ 05227 /* NOTE: The casts will not be needed for v1.10 and later */ 05228 state_cb->change_cb((char *) context_name, (char *) exten_name, 05229 AST_EXTENSION_DEACTIVATED, state_cb->data); 05230 ao2_ref(state_cb, -1); 05231 } 05232 ao2_ref(hint->callbacks, -1); 05233 } 05234 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2344 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().
02345 { 02346 /* destroy all the alternates */ 02347 if (pattern_tree->alt_char) { 02348 destroy_pattern_tree(pattern_tree->alt_char); 02349 pattern_tree->alt_char = 0; 02350 } 02351 /* destroy all the nexts */ 02352 if (pattern_tree->next_char) { 02353 destroy_pattern_tree(pattern_tree->next_char); 02354 pattern_tree->next_char = 0; 02355 } 02356 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02357 ast_free(pattern_tree); 02358 }
static void destroy_state_cb | ( | void * | doomed | ) | [static] |
Definition at line 5038 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().
05039 { 05040 struct ast_state_cb *state_cb = doomed; 05041 05042 if (state_cb->destroy_cb) { 05043 state_cb->destroy_cb(state_cb->id, state_cb->data); 05044 } 05045 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 10905 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().
10906 { 10907 const char *device; 10908 struct statechange *sc; 10909 10910 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 10911 if (ast_strlen_zero(device)) { 10912 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 10913 return; 10914 } 10915 10916 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 10917 return; 10918 strcpy(sc->dev, device); 10919 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 10920 ast_free(sc); 10921 } 10922 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3571 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03572 { 03573 struct pbx_exception *exception = data; 03574 ast_string_field_free_memory(exception); 03575 ast_free(exception); 03576 }
static int ext_cmp | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2691 of file pbx.c.
References ext_cmp_exten(), and ext_cmp_pattern().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02692 { 02693 /* Make sure non-pattern extens come first. */ 02694 if (left[0] != '_') { 02695 if (right[0] == '_') { 02696 return -1; 02697 } 02698 /* Compare two non-pattern extens. */ 02699 return ext_cmp_exten(left, right); 02700 } 02701 if (right[0] != '_') { 02702 return 1; 02703 } 02704 02705 /* 02706 * OK, we need full pattern sorting routine. 02707 * 02708 * Skip past the underscores 02709 */ 02710 return ext_cmp_pattern(left + 1, right + 1); 02711 }
static int ext_cmp_exten | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2441 of file pbx.c.
Referenced by _extension_match_core(), and ext_cmp().
02442 { 02443 int cmp; 02444 02445 for (;;) { 02446 /* Ignore '-' chars as eye candy fluff. */ 02447 while (*left == '-') { 02448 ++left; 02449 } 02450 while (*right == '-') { 02451 ++right; 02452 } 02453 02454 cmp = *left - *right; 02455 if (cmp) { 02456 break; 02457 } 02458 if (!*left) { 02459 /* 02460 * Get here only if both strings ended at the same time. cmp 02461 * would be non-zero if only one string ended. 02462 */ 02463 break; 02464 } 02465 ++left; 02466 ++right; 02467 } 02468 return cmp; 02469 }
static int ext_cmp_exten_partial | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2398 of file pbx.c.
Referenced by _extension_match_core().
02399 { 02400 int cmp; 02401 02402 for (;;) { 02403 /* Ignore '-' chars as eye candy fluff. */ 02404 while (*left == '-') { 02405 ++left; 02406 } 02407 while (*right == '-') { 02408 ++right; 02409 } 02410 02411 if (!*right) { 02412 /* 02413 * Right ended first for partial match or both ended at the same 02414 * time for a match. 02415 */ 02416 cmp = 0; 02417 break; 02418 } 02419 02420 cmp = *left - *right; 02421 if (cmp) { 02422 break; 02423 } 02424 ++left; 02425 ++right; 02426 } 02427 return cmp; 02428 }
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 2643 of file pbx.c.
References ARRAY_LEN, and ext_cmp_pattern_pos().
Referenced by _extension_match_core(), and ext_cmp().
02644 { 02645 int cmp; 02646 int left_pos; 02647 int right_pos; 02648 02649 for (;;) { 02650 unsigned char left_bitwise[32] = { 0, }; 02651 unsigned char right_bitwise[32] = { 0, }; 02652 02653 left_pos = ext_cmp_pattern_pos(&left, left_bitwise); 02654 right_pos = ext_cmp_pattern_pos(&right, right_bitwise); 02655 cmp = left_pos - right_pos; 02656 if (!cmp) { 02657 /* 02658 * Are the character sets different, even though they score the same? 02659 * 02660 * Note: Must swap left and right to get the sense of the 02661 * comparison correct. Otherwise, we would need to multiply by 02662 * -1 instead. 02663 */ 02664 cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise)); 02665 } 02666 if (cmp) { 02667 break; 02668 } 02669 if (!left) { 02670 /* 02671 * Get here only if both patterns ended at the same time. cmp 02672 * would be non-zero if only one pattern ended. 02673 */ 02674 break; 02675 } 02676 } 02677 return cmp; 02678 }
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 2528 of file pbx.c.
References ast_log(), BITS_PER, and LOG_WARNING.
Referenced by ext_cmp_pattern().
02529 { 02530 #define BITS_PER 8 /* Number of bits per unit (byte). */ 02531 unsigned char c; 02532 unsigned char cmin; 02533 int count; 02534 const char *end; 02535 02536 do { 02537 /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */ 02538 do { 02539 c = *(*p)++; 02540 } while (c == '-'); 02541 02542 /* always return unless we have a set of chars */ 02543 switch (c) { 02544 default: 02545 /* ordinary character */ 02546 bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER)); 02547 return 0x0100 | c; 02548 02549 case 'n': 02550 case 'N': 02551 /* 2..9 */ 02552 bitwise[6] = 0x3f; 02553 bitwise[7] = 0xc0; 02554 return 0x0800 | '2'; 02555 02556 case 'x': 02557 case 'X': 02558 /* 0..9 */ 02559 bitwise[6] = 0xff; 02560 bitwise[7] = 0xc0; 02561 return 0x0A00 | '0'; 02562 02563 case 'z': 02564 case 'Z': 02565 /* 1..9 */ 02566 bitwise[6] = 0x7f; 02567 bitwise[7] = 0xc0; 02568 return 0x0900 | '1'; 02569 02570 case '.': 02571 /* wildcard */ 02572 return 0x18000; 02573 02574 case '!': 02575 /* earlymatch */ 02576 return 0x28000; /* less specific than '.' */ 02577 02578 case '\0': 02579 /* empty string */ 02580 *p = NULL; 02581 return 0x30000; 02582 02583 case '[': 02584 /* char set */ 02585 break; 02586 } 02587 /* locate end of set */ 02588 end = strchr(*p, ']'); 02589 02590 if (!end) { 02591 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02592 return 0x40000; /* XXX make this entry go last... */ 02593 } 02594 02595 count = 0; 02596 cmin = 0xFF; 02597 for (; *p < end; ++*p) { 02598 unsigned char c1; /* first char in range */ 02599 unsigned char c2; /* last char in range */ 02600 02601 c1 = (*p)[0]; 02602 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02603 c2 = (*p)[2]; 02604 *p += 2; /* skip a total of 3 chars */ 02605 } else { /* individual character */ 02606 c2 = c1; 02607 } 02608 if (c1 < cmin) { 02609 cmin = c1; 02610 } 02611 for (; c1 <= c2; ++c1) { 02612 unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER)); 02613 02614 /* 02615 * Note: If two character sets score the same, the one with the 02616 * lowest ASCII values will compare as coming first. Must fill 02617 * in most significant bits for lower ASCII values to accomplish 02618 * the desired sort order. 02619 */ 02620 if (!(bitwise[c1 / BITS_PER] & mask)) { 02621 /* Add the character to the set. */ 02622 bitwise[c1 / BITS_PER] |= mask; 02623 count += 0x100; 02624 } 02625 } 02626 } 02627 ++*p; 02628 } while (!count);/* While the char set was empty. */ 02629 return count | cmin; 02630 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 8827 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
08828 { 08829 int count = 0; 08830 int insquares = 0; 08831 08832 while (*src && (count < len - 1)) { 08833 if (*src == '[') { 08834 insquares = 1; 08835 } else if (*src == ']') { 08836 insquares = 0; 08837 } else if (*src == ' ' && !insquares) { 08838 src++; 08839 continue; 08840 } 08841 *dst = *src; 08842 dst++; 08843 src++; 08844 count++; 08845 } 08846 *dst = '\0'; 08847 08848 return count; 08849 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2930 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().
02931 { 02932 int i; 02933 static int prof_id = -2; /* marker for 'unallocated' id */ 02934 if (prof_id == -2) { 02935 prof_id = ast_add_profile("ext_match", 0); 02936 } 02937 ast_mark(prof_id, 1); 02938 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode); 02939 ast_mark(prof_id, 0); 02940 return i; 02941 }
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 5971 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05972 { 05973 struct fake_context item; 05974 05975 ast_copy_string(item.name, context, sizeof(item.name)); 05976 05977 return ast_hashtab_lookup(contexts_table, &item); 05978 }
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 5985 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().
05986 { 05987 struct ast_context *c; 05988 struct fake_context item; 05989 05990 ast_copy_string(item.name, context, sizeof(item.name)); 05991 05992 ast_rdlock_contexts(); 05993 c = ast_hashtab_lookup(contexts_table, &item); 05994 if (!c) { 05995 ast_unlock_contexts(); 05996 } 05997 05998 return c; 05999 }
static int find_hint_by_cb_id | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Remove a watcher from the callback list.
Definition at line 5142 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 4041 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
04042 { 04043 char *args = strchr(function, '('); 04044 04045 if (!args) { 04046 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 04047 } else { 04048 char *p; 04049 *args++ = '\0'; 04050 if ((p = strrchr(args, ')'))) { 04051 *p = '\0'; 04052 } else { 04053 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 04054 } 04055 } 04056 return args; 04057 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1729 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.
01730 { 01731 /* find the exten at the end of the rope */ 01732 struct match_char *node2 = node; 01733 01734 for (node2 = node; node2; node2 = node2->next_char) { 01735 if (node2->exten) { 01736 #ifdef NEED_DEBUG_HERE 01737 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01738 #endif 01739 return node2->exten; 01740 } 01741 } 01742 #ifdef NEED_DEBUG_HERE 01743 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01744 #endif 01745 return 0; 01746 }
static const char* get_pattern_node | ( | struct pattern_node * | node, | |
const char * | src, | |||
int | pattern, | |||
const char * | extenbuf | |||
) | [static] |
Definition at line 2078 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().
02079 { 02080 #define INC_DST_OVERFLOW_CHECK \ 02081 do { \ 02082 if (dst - node->buf < sizeof(node->buf) - 1) { \ 02083 ++dst; \ 02084 } else { \ 02085 overflow = 1; \ 02086 } \ 02087 } while (0) 02088 02089 node->specif = 0; 02090 node->buf[0] = '\0'; 02091 while (*src) { 02092 if (*src == '[' && pattern) { 02093 char *dst = node->buf; 02094 const char *src_next; 02095 int length; 02096 int overflow = 0; 02097 02098 /* get past the '[' */ 02099 ++src; 02100 for (;;) { 02101 if (*src == '\\') { 02102 /* Escaped character. */ 02103 ++src; 02104 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') { 02105 *dst = *src++; 02106 INC_DST_OVERFLOW_CHECK; 02107 } 02108 } else if (*src == '-') { 02109 unsigned char first; 02110 unsigned char last; 02111 02112 src_next = src; 02113 first = *(src_next - 1); 02114 last = *++src_next; 02115 02116 if (last == '\\') { 02117 /* Escaped character. */ 02118 last = *++src_next; 02119 } 02120 02121 /* Possible char range. */ 02122 if (node->buf[0] && last) { 02123 /* Expand the char range. */ 02124 while (++first <= last) { 02125 *dst = first; 02126 INC_DST_OVERFLOW_CHECK; 02127 } 02128 src = src_next + 1; 02129 } else { 02130 /* 02131 * There was no left or right char for the range. 02132 * It is just a '-'. 02133 */ 02134 *dst = *src++; 02135 INC_DST_OVERFLOW_CHECK; 02136 } 02137 } else if (*src == '\0') { 02138 ast_log(LOG_WARNING, 02139 "A matching ']' was not found for '[' in exten pattern '%s'\n", 02140 extenbuf); 02141 break; 02142 } else if (*src == ']') { 02143 ++src; 02144 break; 02145 } else { 02146 *dst = *src++; 02147 INC_DST_OVERFLOW_CHECK; 02148 } 02149 } 02150 /* null terminate the exploded range */ 02151 *dst = '\0'; 02152 02153 if (overflow) { 02154 ast_log(LOG_ERROR, 02155 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n", 02156 extenbuf); 02157 node->buf[0] = '\0'; 02158 continue; 02159 } 02160 02161 /* Sort the characters in character set. */ 02162 length = strlen(node->buf); 02163 if (!length) { 02164 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n", 02165 extenbuf); 02166 node->buf[0] = '\0'; 02167 continue; 02168 } 02169 qsort(node->buf, length, 1, compare_char); 02170 02171 /* Remove duplicate characters from character set. */ 02172 dst = node->buf; 02173 src_next = node->buf; 02174 while (*src_next++) { 02175 if (*dst != *src_next) { 02176 *++dst = *src_next; 02177 } 02178 } 02179 02180 length = strlen(node->buf); 02181 length <<= 8; 02182 node->specif = length | (unsigned char) node->buf[0]; 02183 break; 02184 } else if (*src == '-') { 02185 /* Skip dashes in all extensions. */ 02186 ++src; 02187 } else { 02188 if (*src == '\\') { 02189 /* 02190 * XXX The escape character here does not remove any special 02191 * meaning to characters except the '[', '\\', and '-' 02192 * characters since they are special only in this function. 02193 */ 02194 node->buf[0] = *++src; 02195 if (!node->buf[0]) { 02196 break; 02197 } 02198 } else { 02199 node->buf[0] = *src; 02200 if (pattern) { 02201 /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02202 if (node->buf[0] == 'n') { 02203 node->buf[0] = 'N'; 02204 } else if (node->buf[0] == 'x') { 02205 node->buf[0] = 'X'; 02206 } else if (node->buf[0] == 'z') { 02207 node->buf[0] = 'Z'; 02208 } 02209 } 02210 } 02211 node->buf[1] = '\0'; 02212 node->specif = 1; 02213 ++src; 02214 break; 02215 } 02216 } 02217 return src; 02218 02219 #undef INC_DST_OVERFLOW_CHECK 02220 }
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 8182 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and lookup_name().
Referenced by ast_build_timing().
08183 { 08184 int start, end; /* start and ending position */ 08185 unsigned int mask = 0; 08186 char *part; 08187 08188 /* Check for whole range */ 08189 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 08190 return (1 << max) - 1; 08191 } 08192 08193 while ((part = strsep(&src, "&"))) { 08194 /* Get start and ending position */ 08195 char *endpart = strchr(part, '-'); 08196 if (endpart) { 08197 *endpart++ = '\0'; 08198 } 08199 /* Find the start */ 08200 if ((start = lookup_name(part, names, max)) < 0) { 08201 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 08202 continue; 08203 } 08204 if (endpart) { /* find end of range */ 08205 if ((end = lookup_name(endpart, names, max)) < 0) { 08206 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 08207 continue; 08208 } 08209 } else { 08210 end = start; 08211 } 08212 /* Fill the mask. Remember that ranges are cyclic */ 08213 mask |= (1 << end); /* initialize with last element */ 08214 while (start != end) { 08215 mask |= (1 << start); 08216 if (++start >= max) { 08217 start = 0; 08218 } 08219 } 08220 } 08221 return mask; 08222 }
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 8225 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
08226 { 08227 char *endpart, *part; 08228 int x; 08229 int st_h, st_m; 08230 int endh, endm; 08231 int minute_start, minute_end; 08232 08233 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 08234 memset(i->minmask, 0, sizeof(i->minmask)); 08235 08236 /* 1-minute per bit */ 08237 /* Star is all times */ 08238 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 08239 /* 48, because each hour takes 2 integers; 30 bits each */ 08240 for (x = 0; x < 48; x++) { 08241 i->minmask[x] = 0x3fffffff; /* 30 bits */ 08242 } 08243 return; 08244 } 08245 /* Otherwise expect a range */ 08246 while ((part = strsep(×, "&"))) { 08247 if (!(endpart = strchr(part, '-'))) { 08248 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 08249 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 08250 continue; 08251 } 08252 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 08253 continue; 08254 } 08255 *endpart++ = '\0'; 08256 /* why skip non digits? Mostly to skip spaces */ 08257 while (*endpart && !isdigit(*endpart)) { 08258 endpart++; 08259 } 08260 if (!*endpart) { 08261 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 08262 continue; 08263 } 08264 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 08265 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 08266 continue; 08267 } 08268 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 08269 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 08270 continue; 08271 } 08272 minute_start = st_h * 60 + st_m; 08273 minute_end = endh * 60 + endm; 08274 /* Go through the time and enable each appropriate bit */ 08275 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 08276 i->minmask[x / 30] |= (1 << (x % 30)); 08277 } 08278 /* Do the last one */ 08279 i->minmask[x / 30] |= (1 << (x % 30)); 08280 } 08281 /* All done */ 08282 return; 08283 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 7196 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.
07197 { 07198 char *exten = NULL, *context = NULL; 07199 /* Variables used for different counters */ 07200 struct dialplan_counters counters; 07201 const char *incstack[AST_PBX_MAX_STACK]; 07202 07203 switch (cmd) { 07204 case CLI_INIT: 07205 e->command = "dialplan debug"; 07206 e->usage = 07207 "Usage: dialplan debug [context]\n" 07208 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 07209 return NULL; 07210 case CLI_GENERATE: 07211 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 07212 } 07213 07214 memset(&counters, 0, sizeof(counters)); 07215 07216 if (a->argc != 2 && a->argc != 3) 07217 return CLI_SHOWUSAGE; 07218 07219 /* we obtain [exten@]context? if yes, split them ... */ 07220 /* note: we ignore the exten totally here .... */ 07221 if (a->argc == 3) { 07222 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 07223 context = ast_strdupa(a->argv[2]); 07224 exten = strsep(&context, "@"); 07225 /* change empty strings to NULL */ 07226 if (ast_strlen_zero(exten)) 07227 exten = NULL; 07228 } else { /* no '@' char, only context given */ 07229 context = ast_strdupa(a->argv[2]); 07230 } 07231 if (ast_strlen_zero(context)) 07232 context = NULL; 07233 } 07234 /* else Show complete dial plan, context and exten are NULL */ 07235 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 07236 07237 /* check for input failure and throw some error messages */ 07238 if (context && !counters.context_existence) { 07239 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 07240 return CLI_FAILURE; 07241 } 07242 07243 07244 ast_cli(a->fd,"-= %d %s. =-\n", 07245 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 07246 07247 /* everything ok */ 07248 return CLI_SUCCESS; 07249 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7569 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.
07570 { 07571 struct ast_channel *chan; 07572 const char *chan_name, *var_name, *var_value; 07573 07574 switch (cmd) { 07575 case CLI_INIT: 07576 e->command = "dialplan set chanvar"; 07577 e->usage = 07578 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 07579 " Set channel variable <varname> to <value>\n"; 07580 return NULL; 07581 case CLI_GENERATE: 07582 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07583 } 07584 07585 if (a->argc != e->args + 3) 07586 return CLI_SHOWUSAGE; 07587 07588 chan_name = a->argv[e->args]; 07589 var_name = a->argv[e->args + 1]; 07590 var_value = a->argv[e->args + 2]; 07591 07592 if (!(chan = ast_channel_get_by_name(chan_name))) { 07593 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 07594 return CLI_FAILURE; 07595 } 07596 07597 pbx_builtin_setvar_helper(chan, var_name, var_value); 07598 07599 chan = ast_channel_unref(chan); 07600 07601 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 07602 07603 return CLI_SUCCESS; 07604 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7606 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.
07607 { 07608 int oldval = 0; 07609 07610 switch (cmd) { 07611 case CLI_INIT: 07612 e->command = "dialplan set extenpatternmatchnew true"; 07613 e->usage = 07614 "Usage: dialplan set extenpatternmatchnew true|false\n" 07615 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07616 return NULL; 07617 case CLI_GENERATE: 07618 return NULL; 07619 } 07620 07621 if (a->argc != 4) 07622 return CLI_SHOWUSAGE; 07623 07624 oldval = pbx_set_extenpatternmatchnew(1); 07625 07626 if (oldval) 07627 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07628 else 07629 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07630 07631 return CLI_SUCCESS; 07632 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7547 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.
07548 { 07549 switch (cmd) { 07550 case CLI_INIT: 07551 e->command = "dialplan set global"; 07552 e->usage = 07553 "Usage: dialplan set global <name> <value>\n" 07554 " Set global dialplan variable <name> to <value>\n"; 07555 return NULL; 07556 case CLI_GENERATE: 07557 return NULL; 07558 } 07559 07560 if (a->argc != e->args + 2) 07561 return CLI_SHOWUSAGE; 07562 07563 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 07564 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 07565 07566 return CLI_SUCCESS; 07567 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6543 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.
06544 { 06545 struct ast_app *aa; 06546 int app, no_registered_app = 1; 06547 06548 switch (cmd) { 06549 case CLI_INIT: 06550 e->command = "core show application"; 06551 e->usage = 06552 "Usage: core show application <application> [<application> [<application> [...]]]\n" 06553 " Describes a particular application.\n"; 06554 return NULL; 06555 case CLI_GENERATE: 06556 /* 06557 * There is a possibility to show informations about more than one 06558 * application at one time. You can type 'show application Dial Echo' and 06559 * you will see informations about these two applications ... 06560 */ 06561 return ast_complete_applications(a->line, a->word, a->n); 06562 } 06563 06564 if (a->argc < 4) { 06565 return CLI_SHOWUSAGE; 06566 } 06567 06568 AST_RWLIST_RDLOCK(&apps); 06569 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06570 /* Check for each app that was supplied as an argument */ 06571 for (app = 3; app < a->argc; app++) { 06572 if (strcasecmp(aa->name, a->argv[app])) { 06573 continue; 06574 } 06575 06576 /* We found it! */ 06577 no_registered_app = 0; 06578 06579 print_app_docs(aa, a->fd); 06580 } 06581 } 06582 AST_RWLIST_UNLOCK(&apps); 06583 06584 /* we found at least one app? no? */ 06585 if (no_registered_app) { 06586 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 06587 return CLI_FAILURE; 06588 } 06589 06590 return CLI_SUCCESS; 06591 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6779 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.
06780 { 06781 struct ast_app *aa; 06782 int like = 0, describing = 0; 06783 int total_match = 0; /* Number of matches in like clause */ 06784 int total_apps = 0; /* Number of apps registered */ 06785 static const char * const choices[] = { "like", "describing", NULL }; 06786 06787 switch (cmd) { 06788 case CLI_INIT: 06789 e->command = "core show applications [like|describing]"; 06790 e->usage = 06791 "Usage: core show applications [{like|describing} <text>]\n" 06792 " List applications which are currently available.\n" 06793 " If 'like', <text> will be a substring of the app name\n" 06794 " If 'describing', <text> will be a substring of the description\n"; 06795 return NULL; 06796 case CLI_GENERATE: 06797 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 06798 } 06799 06800 AST_RWLIST_RDLOCK(&apps); 06801 06802 if (AST_RWLIST_EMPTY(&apps)) { 06803 ast_cli(a->fd, "There are no registered applications\n"); 06804 AST_RWLIST_UNLOCK(&apps); 06805 return CLI_SUCCESS; 06806 } 06807 06808 /* core list applications like <keyword> */ 06809 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 06810 like = 1; 06811 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 06812 describing = 1; 06813 } 06814 06815 /* core list applications describing <keyword1> [<keyword2>] [...] */ 06816 if ((!like) && (!describing)) { 06817 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 06818 } else { 06819 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 06820 } 06821 06822 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06823 int printapp = 0; 06824 total_apps++; 06825 if (like) { 06826 if (strcasestr(aa->name, a->argv[4])) { 06827 printapp = 1; 06828 total_match++; 06829 } 06830 } else if (describing) { 06831 if (aa->description) { 06832 /* Match all words on command line */ 06833 int i; 06834 printapp = 1; 06835 for (i = 4; i < a->argc; i++) { 06836 if (!strcasestr(aa->description, a->argv[i])) { 06837 printapp = 0; 06838 } else { 06839 total_match++; 06840 } 06841 } 06842 } 06843 } else { 06844 printapp = 1; 06845 } 06846 06847 if (printapp) { 06848 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 06849 } 06850 } 06851 if ((!like) && (!describing)) { 06852 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 06853 } else { 06854 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 06855 } 06856 06857 AST_RWLIST_UNLOCK(&apps); 06858 06859 return CLI_SUCCESS; 06860 }
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 7512 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.
07513 { 07514 struct ast_channel *chan = NULL; 07515 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 07516 07517 switch (cmd) { 07518 case CLI_INIT: 07519 e->command = "dialplan show chanvar"; 07520 e->usage = 07521 "Usage: dialplan show chanvar <channel>\n" 07522 " List current channel variables and their values\n"; 07523 return NULL; 07524 case CLI_GENERATE: 07525 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07526 } 07527 07528 if (a->argc != e->args + 1) 07529 return CLI_SHOWUSAGE; 07530 07531 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 07532 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 07533 return CLI_FAILURE; 07534 } 07535 07536 pbx_builtin_serialize_variables(chan, &vars); 07537 07538 if (ast_str_strlen(vars)) { 07539 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 07540 } 07541 07542 chan = ast_channel_unref(chan); 07543 07544 return CLI_SUCCESS; 07545 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7129 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.
07130 { 07131 char *exten = NULL, *context = NULL; 07132 /* Variables used for different counters */ 07133 struct dialplan_counters counters; 07134 const char *incstack[AST_PBX_MAX_STACK]; 07135 07136 switch (cmd) { 07137 case CLI_INIT: 07138 e->command = "dialplan show"; 07139 e->usage = 07140 "Usage: dialplan show [[exten@]context]\n" 07141 " Show dialplan\n"; 07142 return NULL; 07143 case CLI_GENERATE: 07144 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 07145 } 07146 07147 memset(&counters, 0, sizeof(counters)); 07148 07149 if (a->argc != 2 && a->argc != 3) 07150 return CLI_SHOWUSAGE; 07151 07152 /* we obtain [exten@]context? if yes, split them ... */ 07153 if (a->argc == 3) { 07154 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 07155 context = ast_strdupa(a->argv[2]); 07156 exten = strsep(&context, "@"); 07157 /* change empty strings to NULL */ 07158 if (ast_strlen_zero(exten)) 07159 exten = NULL; 07160 } else { /* no '@' char, only context given */ 07161 context = ast_strdupa(a->argv[2]); 07162 } 07163 if (ast_strlen_zero(context)) 07164 context = NULL; 07165 } 07166 /* else Show complete dial plan, context and exten are NULL */ 07167 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 07168 07169 /* check for input failure and throw some error messages */ 07170 if (context && !counters.context_existence) { 07171 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 07172 return CLI_FAILURE; 07173 } 07174 07175 if (exten && !counters.extension_existence) { 07176 if (context) 07177 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 07178 exten, context); 07179 else 07180 ast_cli(a->fd, 07181 "There is no existence of '%s' extension in all contexts\n", 07182 exten); 07183 return CLI_FAILURE; 07184 } 07185 07186 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 07187 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 07188 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 07189 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 07190 07191 /* everything ok */ 07192 return CLI_SUCCESS; 07193 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3693 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.
03694 { 03695 struct ast_custom_function *acf; 03696 /* Maximum number of characters added by terminal coloring is 22 */ 03697 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03698 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03699 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03700 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03701 char *ret = NULL; 03702 int which = 0; 03703 int wordlen; 03704 03705 switch (cmd) { 03706 case CLI_INIT: 03707 e->command = "core show function"; 03708 e->usage = 03709 "Usage: core show function <function>\n" 03710 " Describe a particular dialplan function.\n"; 03711 return NULL; 03712 case CLI_GENERATE: 03713 wordlen = strlen(a->word); 03714 /* case-insensitive for convenience in this 'complete' function */ 03715 AST_RWLIST_RDLOCK(&acf_root); 03716 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03717 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03718 ret = ast_strdup(acf->name); 03719 break; 03720 } 03721 } 03722 AST_RWLIST_UNLOCK(&acf_root); 03723 03724 return ret; 03725 } 03726 03727 if (a->argc < 4) { 03728 return CLI_SHOWUSAGE; 03729 } 03730 03731 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03732 ast_cli(a->fd, "No function by that name registered.\n"); 03733 return CLI_FAILURE; 03734 } 03735 03736 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03737 if (!(syntax = ast_malloc(syntax_size))) { 03738 ast_cli(a->fd, "Memory allocation failure!\n"); 03739 return CLI_FAILURE; 03740 } 03741 03742 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03743 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03744 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03745 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03746 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03747 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03748 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03749 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03750 #ifdef AST_XML_DOCS 03751 if (acf->docsrc == AST_XML_DOC) { 03752 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03753 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03754 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03755 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03756 } else 03757 #endif 03758 { 03759 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03760 synopsis = ast_malloc(synopsis_size); 03761 03762 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03763 description = ast_malloc(description_size); 03764 03765 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03766 arguments = ast_malloc(arguments_size); 03767 03768 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03769 seealso = ast_malloc(seealso_size); 03770 03771 /* check allocated memory. */ 03772 if (!synopsis || !description || !arguments || !seealso) { 03773 ast_free(synopsis); 03774 ast_free(description); 03775 ast_free(arguments); 03776 ast_free(seealso); 03777 ast_free(syntax); 03778 return CLI_FAILURE; 03779 } 03780 03781 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03782 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03783 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03784 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03785 } 03786 03787 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03788 infotitle, syntitle, synopsis, destitle, description, 03789 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03790 03791 ast_free(arguments); 03792 ast_free(synopsis); 03793 ast_free(description); 03794 ast_free(seealso); 03795 ast_free(syntax); 03796 03797 return CLI_SUCCESS; 03798 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3651 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_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.
03652 { 03653 struct ast_custom_function *acf; 03654 int count_acf = 0; 03655 int like = 0; 03656 03657 switch (cmd) { 03658 case CLI_INIT: 03659 e->command = "core show functions [like]"; 03660 e->usage = 03661 "Usage: core show functions [like <text>]\n" 03662 " List builtin functions, optionally only those matching a given string\n"; 03663 return NULL; 03664 case CLI_GENERATE: 03665 return NULL; 03666 } 03667 03668 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03669 like = 1; 03670 } else if (a->argc != 3) { 03671 return CLI_SHOWUSAGE; 03672 } 03673 03674 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03675 03676 AST_RWLIST_RDLOCK(&acf_root); 03677 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03678 if (!like || strstr(acf->name, a->argv[4])) { 03679 count_acf++; 03680 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03681 S_OR(acf->name, ""), 03682 S_OR(acf->syntax, ""), 03683 S_OR(acf->synopsis, "")); 03684 } 03685 } 03686 AST_RWLIST_UNLOCK(&acf_root); 03687 03688 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03689 03690 return CLI_SUCCESS; 03691 }
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 7454 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.
07455 { 07456 int i = 0; 07457 struct ast_var_t *newvariable; 07458 07459 switch (cmd) { 07460 case CLI_INIT: 07461 e->command = "dialplan show globals"; 07462 e->usage = 07463 "Usage: dialplan show globals\n" 07464 " List current global dialplan variables and their values\n"; 07465 return NULL; 07466 case CLI_GENERATE: 07467 return NULL; 07468 } 07469 07470 ast_rwlock_rdlock(&globalslock); 07471 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 07472 i++; 07473 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 07474 } 07475 ast_rwlock_unlock(&globalslock); 07476 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 07477 07478 return CLI_SUCCESS; 07479 }
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 6685 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.
06686 { 06687 struct ast_hint *hint; 06688 int watchers; 06689 int num = 0, extenlen; 06690 struct ao2_iterator i; 06691 06692 switch (cmd) { 06693 case CLI_INIT: 06694 e->command = "core show hint"; 06695 e->usage = 06696 "Usage: core show hint <exten>\n" 06697 " List registered hint.\n" 06698 " Hint details are shown in four columns. In order from left to right, they are:\n" 06699 " 1. Hint extension URI.\n" 06700 " 2. Mapped device state identifiers.\n" 06701 " 3. Current extension state. The aggregate of mapped device states.\n" 06702 " 4. Watchers - number of subscriptions and other entities watching this hint.\n"; 06703 06704 return NULL; 06705 case CLI_GENERATE: 06706 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 06707 } 06708 06709 if (a->argc < 4) 06710 return CLI_SHOWUSAGE; 06711 06712 if (ao2_container_count(hints) == 0) { 06713 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06714 return CLI_SUCCESS; 06715 } 06716 06717 extenlen = strlen(a->argv[3]); 06718 i = ao2_iterator_init(hints, 0); 06719 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06720 ao2_lock(hint); 06721 if (!hint->exten) { 06722 /* The extension has already been destroyed */ 06723 ao2_unlock(hint); 06724 continue; 06725 } 06726 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 06727 watchers = ao2_container_count(hint->callbacks); 06728 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06729 ast_get_extension_name(hint->exten), 06730 ast_get_context_name(ast_get_extension_context(hint->exten)), 06731 ast_get_extension_app(hint->exten), 06732 ast_extension_state2str(hint->laststate), watchers); 06733 num++; 06734 } 06735 ao2_unlock(hint); 06736 } 06737 ao2_iterator_destroy(&i); 06738 if (!num) 06739 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 06740 else 06741 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 06742 return CLI_SUCCESS; 06743 }
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 6594 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.
06595 { 06596 struct ast_hint *hint; 06597 int num = 0; 06598 int watchers; 06599 struct ao2_iterator i; 06600 06601 switch (cmd) { 06602 case CLI_INIT: 06603 e->command = "core show hints"; 06604 e->usage = 06605 "Usage: core show hints\n" 06606 " List registered hints.\n" 06607 " Hint details are shown in four columns. In order from left to right, they are:\n" 06608 " 1. Hint extension URI.\n" 06609 " 2. Mapped device state identifiers.\n" 06610 " 3. Current extension state. The aggregate of mapped device states.\n" 06611 " 4. Watchers - number of subscriptions and other entities watching this hint.\n"; 06612 return NULL; 06613 case CLI_GENERATE: 06614 return NULL; 06615 } 06616 06617 if (ao2_container_count(hints) == 0) { 06618 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06619 return CLI_SUCCESS; 06620 } 06621 /* ... we have hints ... */ 06622 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 06623 06624 i = ao2_iterator_init(hints, 0); 06625 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06626 ao2_lock(hint); 06627 if (!hint->exten) { 06628 /* The extension has already been destroyed */ 06629 ao2_unlock(hint); 06630 continue; 06631 } 06632 watchers = ao2_container_count(hint->callbacks); 06633 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06634 ast_get_extension_name(hint->exten), 06635 ast_get_context_name(ast_get_extension_context(hint->exten)), 06636 ast_get_extension_app(hint->exten), 06637 ast_extension_state2str(hint->laststate), watchers); 06638 ao2_unlock(hint); 06639 num++; 06640 } 06641 ao2_iterator_destroy(&i); 06642 06643 ast_cli(a->fd, "----------------\n"); 06644 ast_cli(a->fd, "- %d hints registered\n", num); 06645 return CLI_SUCCESS; 06646 }
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 6747 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.
06748 { 06749 struct ast_switch *sw; 06750 06751 switch (cmd) { 06752 case CLI_INIT: 06753 e->command = "core show switches"; 06754 e->usage = 06755 "Usage: core show switches\n" 06756 " List registered switches\n"; 06757 return NULL; 06758 case CLI_GENERATE: 06759 return NULL; 06760 } 06761 06762 AST_RWLIST_RDLOCK(&switches); 06763 06764 if (AST_RWLIST_EMPTY(&switches)) { 06765 AST_RWLIST_UNLOCK(&switches); 06766 ast_cli(a->fd, "There are no registered alternative switches\n"); 06767 return CLI_SUCCESS; 06768 } 06769 06770 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 06771 AST_RWLIST_TRAVERSE(&switches, sw, list) 06772 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 06773 06774 AST_RWLIST_UNLOCK(&switches); 06775 06776 return CLI_SUCCESS; 06777 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4936 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().
04937 { 04938 struct ast_hint *hint; 04939 struct ast_str *hint_app; 04940 struct statechange *sc = datap; 04941 struct ao2_iterator i; 04942 struct ao2_iterator cb_iter; 04943 char context_name[AST_MAX_CONTEXT]; 04944 char exten_name[AST_MAX_EXTENSION]; 04945 04946 hint_app = ast_str_create(1024); 04947 if (!hint_app) { 04948 ast_free(sc); 04949 return -1; 04950 } 04951 04952 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ 04953 i = ao2_iterator_init(hints, 0); 04954 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 04955 struct ast_state_cb *state_cb; 04956 char *cur, *parse; 04957 int state; 04958 04959 ao2_lock(hint); 04960 if (!hint->exten) { 04961 /* The extension has already been destroyed */ 04962 ao2_unlock(hint); 04963 continue; 04964 } 04965 04966 /* Does this hint monitor the device that changed state? */ 04967 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04968 parse = ast_str_buffer(hint_app); 04969 while ((cur = strsep(&parse, "&"))) { 04970 if (!strcasecmp(cur, sc->dev)) { 04971 /* The hint monitors the device. */ 04972 break; 04973 } 04974 } 04975 if (!cur) { 04976 /* The hint does not monitor the device. */ 04977 ao2_unlock(hint); 04978 continue; 04979 } 04980 04981 /* 04982 * Save off strings in case the hint extension gets destroyed 04983 * while we are notifying the watchers. 04984 */ 04985 ast_copy_string(context_name, 04986 ast_get_context_name(ast_get_extension_context(hint->exten)), 04987 sizeof(context_name)); 04988 ast_copy_string(exten_name, ast_get_extension_name(hint->exten), 04989 sizeof(exten_name)); 04990 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04991 ao2_unlock(hint); 04992 04993 /* 04994 * Get device state for this hint. 04995 * 04996 * NOTE: We cannot hold any locks while determining the hint 04997 * device state or notifying the watchers without causing a 04998 * deadlock. (conlock, hints, and hint) 04999 */ 05000 state = ast_extension_state3(hint_app); 05001 if (state == hint->laststate) { 05002 continue; 05003 } 05004 05005 /* Device state changed since last check - notify the watchers. */ 05006 hint->laststate = state; /* record we saw the change */ 05007 05008 /* For general callbacks */ 05009 cb_iter = ao2_iterator_init(statecbs, 0); 05010 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 05011 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 05012 } 05013 ao2_iterator_destroy(&cb_iter); 05014 05015 /* For extension callbacks */ 05016 cb_iter = ao2_iterator_init(hint->callbacks, 0); 05017 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 05018 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 05019 } 05020 ao2_iterator_destroy(&cb_iter); 05021 } 05022 ao2_iterator_destroy(&i); 05023 ast_mutex_unlock(&context_merge_lock); 05024 05025 ast_free(hint_app); 05026 ast_free(sc); 05027 return 0; 05028 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7634 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.
07635 { 07636 int oldval = 0; 07637 07638 switch (cmd) { 07639 case CLI_INIT: 07640 e->command = "dialplan set extenpatternmatchnew false"; 07641 e->usage = 07642 "Usage: dialplan set extenpatternmatchnew true|false\n" 07643 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07644 return NULL; 07645 case CLI_GENERATE: 07646 return NULL; 07647 } 07648 07649 if (a->argc != 4) 07650 return CLI_SHOWUSAGE; 07651 07652 oldval = pbx_set_extenpatternmatchnew(0); 07653 07654 if (!oldval) 07655 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07656 else 07657 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07658 07659 return CLI_SUCCESS; 07660 }
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 1174 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 1146 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().
01147 { 01148 const struct ast_exten *ac = ah_a; 01149 const struct ast_exten *bc = ah_b; 01150 int x = strcmp(ac->exten, bc->exten); 01151 if (x) { /* if exten names are diff, then return */ 01152 return x; 01153 } 01154 01155 /* but if they are the same, do the cidmatch values match? */ 01156 /* not sure which side may be using ast_ext_matchcid_types, so check both */ 01157 if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) { 01158 return 0; 01159 } 01160 if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) { 01161 return 0; 01162 } 01163 if (ac->matchcid != bc->matchcid) { 01164 return 1; 01165 } 01166 /* all other cases already disposed of, match now required on callerid string (cidmatch) */ 01167 /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */ 01168 if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) { 01169 return 0; 01170 } 01171 return strcmp(ac->cidmatch, bc->cidmatch); 01172 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1194 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().
01195 { 01196 const struct ast_exten *ac = obj; 01197 unsigned int x = ast_hashtab_hash_string(ac->exten); 01198 unsigned int y = 0; 01199 if (ac->matchcid == AST_EXT_MATCHCID_ON) 01200 y = ast_hashtab_hash_string(ac->cidmatch); 01201 return x+y; 01202 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1210 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01211 { 01212 const struct ast_exten *ac = obj; 01213 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01214 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1204 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01205 { 01206 const struct ast_exten *ac = obj; 01207 return ast_hashtab_hash_int(ac->priority); 01208 }
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 11355 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().
11356 { 11357 const struct ast_hint *hint = obj; 11358 const char *exten_name; 11359 int res; 11360 11361 exten_name = ast_get_extension_name(hint->exten); 11362 if (ast_strlen_zero(exten_name)) { 11363 /* 11364 * If the exten or extension name isn't set, return 0 so that 11365 * the ao2_find() search will start in the first bucket. 11366 */ 11367 res = 0; 11368 } else { 11369 res = ast_str_case_hash(exten_name); 11370 } 11371 11372 return res; 11373 }
static int hint_id_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 5191 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
05192 { 05193 const struct ast_state_cb *cb = obj; 05194 int *id = arg; 05195 05196 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 05197 }
static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 10928 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.
10930 { 10931 struct ast_data *data_hint; 10932 struct ast_hint *hint; 10933 int watchers; 10934 struct ao2_iterator i; 10935 10936 if (ao2_container_count(hints) == 0) { 10937 return 0; 10938 } 10939 10940 i = ao2_iterator_init(hints, 0); 10941 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 10942 watchers = ao2_container_count(hint->callbacks); 10943 data_hint = ast_data_add_node(data_root, "hint"); 10944 if (!data_hint) { 10945 continue; 10946 } 10947 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 10948 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 10949 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 10950 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 10951 ast_data_add_int(data_hint, "watchers", watchers); 10952 10953 if (!ast_data_search_match(search, data_hint)) { 10954 ast_data_remove_node(data_root, data_hint); 10955 } 10956 } 10957 ao2_iterator_destroy(&i); 10958 10959 return 0; 10960 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1565 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01566 { 01567 if (!i->hastime) 01568 return 1; 01569 01570 return ast_check_timing(&(i->timing)); 01571 }
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 5790 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().
05791 { 05792 int failed = 0; 05793 double curloadavg; 05794 #if defined(HAVE_SYSINFO) 05795 long curfreemem; 05796 struct sysinfo sys_info; 05797 #endif 05798 05799 ast_mutex_lock(&maxcalllock); 05800 if (option_maxcalls) { 05801 if (countcalls >= option_maxcalls) { 05802 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 05803 failed = -1; 05804 } 05805 } 05806 if (option_maxload) { 05807 getloadavg(&curloadavg, 1); 05808 if (curloadavg >= option_maxload) { 05809 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 05810 failed = -1; 05811 } 05812 } 05813 #if defined(HAVE_SYSINFO) 05814 if (option_minmemfree) { 05815 if (!sysinfo(&sys_info)) { 05816 /* make sure that the free system memory is above the configured low watermark 05817 * convert the amount of freeram from mem_units to MB */ 05818 curfreemem = sys_info.freeram * sys_info.mem_unit; 05819 curfreemem /= 1024 * 1024; 05820 if (curfreemem < option_minmemfree) { 05821 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 05822 failed = -1; 05823 } 05824 } 05825 } 05826 #endif 05827 05828 if (!failed) { 05829 countcalls++; 05830 totalcalls++; 05831 } 05832 ast_mutex_unlock(&maxcalllock); 05833 05834 return failed; 05835 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1983 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01984 { 01985 struct match_char *curr, *lcurr; 01986 01987 /* insert node into the tree at "current", so the alt_char list from current is 01988 sorted in increasing value as you go to the leaves */ 01989 if (!(*parent_ptr)) { 01990 *parent_ptr = node; 01991 return; 01992 } 01993 01994 if ((*parent_ptr)->specificity > node->specificity) { 01995 /* insert at head */ 01996 node->alt_char = (*parent_ptr); 01997 *parent_ptr = node; 01998 return; 01999 } 02000 02001 lcurr = *parent_ptr; 02002 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 02003 if (curr->specificity > node->specificity) { 02004 node->alt_char = curr; 02005 lcurr->alt_char = node; 02006 break; 02007 } 02008 lcurr = curr; 02009 } 02010 02011 if (!curr) { 02012 lcurr->alt_char = node; 02013 } 02014 02015 }
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 4119 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().
04120 { 04121 if (!acfptr) { 04122 return 1; 04123 } 04124 04125 if (!read_escalates(acfptr)) { 04126 return 1; 04127 } 04128 04129 if (!thread_inhibits_escalations()) { 04130 return 1; 04131 } 04132 04133 if (live_dangerously) { 04134 /* Global setting overrides the thread's preference */ 04135 ast_debug(2, "Reading %s from a dangerous context\n", 04136 acfptr->name); 04137 return 1; 04138 } 04139 04140 /* We have no reason to allow this function to execute */ 04141 return 0; 04142 }
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 4152 of file pbx.c.
References ast_debug, ast_custom_function::name, thread_inhibits_escalations(), and write_escalates().
Referenced by ast_func_write().
04153 { 04154 if (!acfptr) { 04155 return 1; 04156 } 04157 04158 if (!write_escalates(acfptr)) { 04159 return 1; 04160 } 04161 04162 if (!thread_inhibits_escalations()) { 04163 return 1; 04164 } 04165 04166 if (live_dangerously) { 04167 /* Global setting overrides the thread's preference */ 04168 ast_debug(2, "Writing %s from a dangerous context\n", 04169 acfptr->name); 04170 return 1; 04171 } 04172 04173 /* We have no reason to allow this function to execute */ 04174 return 0; 04175 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 10996 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().
10997 { 10998 int x; 10999 11000 ast_register_atexit(unload_pbx); 11001 11002 /* Initialize the PBX */ 11003 ast_verb(1, "Asterisk PBX Core Initializing\n"); 11004 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 11005 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 11006 } 11007 11008 ast_verb(1, "Registering builtin applications:\n"); 11009 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 11010 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 11011 __ast_custom_function_register(&exception_function, NULL); 11012 __ast_custom_function_register(&testtime_function, NULL); 11013 11014 /* Register builtin applications */ 11015 for (x = 0; x < ARRAY_LEN(builtins); x++) { 11016 ast_verb(1, "[%s]\n", builtins[x].name); 11017 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 11018 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 11019 return -1; 11020 } 11021 } 11022 11023 /* Register manager application */ 11024 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 11025 11026 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 11027 AST_EVENT_IE_END))) { 11028 return -1; 11029 } 11030 11031 return 0; 11032 }
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 8159 of file pbx.c.
Referenced by get_range().
08160 { 08161 int i; 08162 08163 if (names && *s > '9') { 08164 for (i = 0; names[i]; i++) { 08165 if (!strcasecmp(s, names[i])) { 08166 return i; 08167 } 08168 } 08169 } 08170 08171 /* Allow months and weekdays to be specified as numbers, as well */ 08172 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 08173 /* What the array offset would have been: "1" would be at offset 0 */ 08174 return i - 1; 08175 } 08176 return -1; /* error return */ 08177 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 7252 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().
07253 { 07254 astman_send_listack(s, m, "DialPlan list will follow", "start"); 07255 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 7397 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().
07398 { 07399 const char *exten, *context; 07400 const char *id = astman_get_header(m, "ActionID"); 07401 char idtext[256]; 07402 07403 /* Variables used for different counters */ 07404 struct dialplan_counters counters; 07405 07406 if (!ast_strlen_zero(id)) 07407 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 07408 else 07409 idtext[0] = '\0'; 07410 07411 memset(&counters, 0, sizeof(counters)); 07412 07413 exten = astman_get_header(m, "Extension"); 07414 context = astman_get_header(m, "Context"); 07415 07416 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 07417 07418 if (!ast_strlen_zero(context) && !counters.context_existence) { 07419 char errorbuf[BUFSIZ]; 07420 07421 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 07422 astman_send_error(s, m, errorbuf); 07423 return 0; 07424 } 07425 if (!ast_strlen_zero(exten) && !counters.extension_existence) { 07426 char errorbuf[BUFSIZ]; 07427 07428 if (!ast_strlen_zero(context)) 07429 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 07430 else 07431 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 07432 astman_send_error(s, m, errorbuf); 07433 return 0; 07434 } 07435 07436 if (!counters.total_items) { 07437 manager_dpsendack(s, m); 07438 } 07439 07440 astman_append(s, "Event: ShowDialPlanComplete\r\n" 07441 "EventList: Complete\r\n" 07442 "ListItems: %d\r\n" 07443 "ListExtensions: %d\r\n" 07444 "ListPriorities: %d\r\n" 07445 "ListContexts: %d\r\n" 07446 "%s" 07447 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 07448 07449 /* everything ok */ 07450 return 0; 07451 }
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 7261 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().
07265 { 07266 struct ast_context *c; 07267 int res = 0, old_total_exten = dpc->total_exten; 07268 07269 if (ast_strlen_zero(exten)) 07270 exten = NULL; 07271 if (ast_strlen_zero(context)) 07272 context = NULL; 07273 07274 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 07275 07276 /* try to lock contexts */ 07277 if (ast_rdlock_contexts()) { 07278 astman_send_error(s, m, "Failed to lock contexts"); 07279 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 07280 return -1; 07281 } 07282 07283 c = NULL; /* walk all contexts ... */ 07284 while ( (c = ast_walk_contexts(c)) ) { 07285 struct ast_exten *e; 07286 struct ast_include *i; 07287 struct ast_ignorepat *ip; 07288 07289 if (context && strcmp(ast_get_context_name(c), context) != 0) 07290 continue; /* not the name we want */ 07291 07292 dpc->context_existence = 1; 07293 dpc->total_context++; 07294 07295 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 07296 07297 if (ast_rdlock_context(c)) { /* failed to lock */ 07298 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 07299 continue; 07300 } 07301 07302 /* XXX note- an empty context is not printed */ 07303 e = NULL; /* walk extensions in context */ 07304 while ( (e = ast_walk_context_extensions(c, e)) ) { 07305 struct ast_exten *p; 07306 07307 /* looking for extension? is this our extension? */ 07308 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 07309 /* not the one we are looking for, continue */ 07310 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 07311 continue; 07312 } 07313 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 07314 07315 dpc->extension_existence = 1; 07316 07317 dpc->total_exten++; 07318 07319 p = NULL; /* walk next extension peers */ 07320 while ( (p = ast_walk_extension_priorities(e, p)) ) { 07321 int prio = ast_get_extension_priority(p); 07322 07323 dpc->total_prio++; 07324 if (!dpc->total_items++) 07325 manager_dpsendack(s, m); 07326 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07327 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 07328 07329 /* XXX maybe make this conditional, if p != e ? */ 07330 if (ast_get_extension_label(p)) 07331 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 07332 07333 if (prio == PRIORITY_HINT) { 07334 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 07335 } else { 07336 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)); 07337 } 07338 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 07339 } 07340 } 07341 07342 i = NULL; /* walk included and write info ... */ 07343 while ( (i = ast_walk_context_includes(c, i)) ) { 07344 if (exten) { 07345 /* Check all includes for the requested extension */ 07346 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 07347 } else { 07348 if (!dpc->total_items++) 07349 manager_dpsendack(s, m); 07350 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07351 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)); 07352 astman_append(s, "\r\n"); 07353 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 07354 } 07355 } 07356 07357 ip = NULL; /* walk ignore patterns and write info ... */ 07358 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 07359 const char *ipname = ast_get_ignorepat_name(ip); 07360 char ignorepat[AST_MAX_EXTENSION]; 07361 07362 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 07363 if (!exten || ast_extension_match(ignorepat, exten)) { 07364 if (!dpc->total_items++) 07365 manager_dpsendack(s, m); 07366 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07367 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 07368 astman_append(s, "\r\n"); 07369 } 07370 } 07371 if (!rinclude) { 07372 struct ast_sw *sw = NULL; 07373 while ( (sw = ast_walk_context_switches(c, sw)) ) { 07374 if (!dpc->total_items++) 07375 manager_dpsendack(s, m); 07376 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07377 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)); 07378 astman_append(s, "\r\n"); 07379 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 07380 } 07381 } 07382 07383 ast_unlock_context(c); 07384 } 07385 ast_unlock_contexts(); 07386 07387 if (dpc->total_exten == old_total_exten) { 07388 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 07389 /* Nothing new under the sun */ 07390 return -1; 07391 } else { 07392 return res; 07393 } 07394 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 3001 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
03002 { 03003 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 03004 failing to get a number should count as a match, otherwise not */ 03005 03006 if (ast_strlen_zero(callerid)) { 03007 return ast_strlen_zero(cidpattern) ? 1 : 0; 03008 } 03009 03010 return ast_extension_match(cidpattern, callerid); 03011 }
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 1807 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().
01808 { 01809 struct match_char *p; /* note minimal stack storage requirements */ 01810 struct ast_exten pattern = { .label = label }; 01811 #ifdef DEBUG_THIS 01812 if (tree) 01813 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01814 else 01815 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01816 #endif 01817 for (p = tree; p; p = p->alt_char) { 01818 if (p->is_pattern) { 01819 if (p->x[0] == 'N') { 01820 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01821 #define NEW_MATCHER_CHK_MATCH \ 01822 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01823 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01824 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01825 if (!p->deleted) { \ 01826 if (action == E_FINDLABEL) { \ 01827 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01828 ast_debug(4, "Found label in preferred extension\n"); \ 01829 return; \ 01830 } \ 01831 } else { \ 01832 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01833 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01834 } \ 01835 } \ 01836 } \ 01837 } 01838 01839 #define NEW_MATCHER_RECURSE \ 01840 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01841 || p->next_char->x[0] == '!')) { \ 01842 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01843 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01844 if (score->exten) { \ 01845 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01846 return; /* the first match is all we need */ \ 01847 } \ 01848 } else { \ 01849 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01850 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01851 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01852 "NULL"); \ 01853 return; /* the first match is all we need */ \ 01854 } \ 01855 } \ 01856 } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \ 01857 score->canmatch = 1; \ 01858 score->canmatch_exten = get_canmatch_exten(p); \ 01859 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01860 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01861 return; \ 01862 } \ 01863 } 01864 01865 NEW_MATCHER_CHK_MATCH; 01866 NEW_MATCHER_RECURSE; 01867 } 01868 } else if (p->x[0] == 'Z') { 01869 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01870 NEW_MATCHER_CHK_MATCH; 01871 NEW_MATCHER_RECURSE; 01872 } 01873 } else if (p->x[0] == 'X') { 01874 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01875 NEW_MATCHER_CHK_MATCH; 01876 NEW_MATCHER_RECURSE; 01877 } 01878 } else if (p->x[0] == '.' && p->x[1] == 0) { 01879 /* how many chars will the . match against? */ 01880 int i = 0; 01881 const char *str2 = str; 01882 while (*str2 && *str2 != '/') { 01883 str2++; 01884 i++; 01885 } 01886 if (p->exten && *str2 != '/') { 01887 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01888 if (score->exten) { 01889 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01890 return; /* the first match is all we need */ 01891 } 01892 } 01893 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01894 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01895 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01896 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01897 return; /* the first match is all we need */ 01898 } 01899 } 01900 } else if (p->x[0] == '!' && p->x[1] == 0) { 01901 /* how many chars will the . match against? */ 01902 int i = 1; 01903 const char *str2 = str; 01904 while (*str2 && *str2 != '/') { 01905 str2++; 01906 i++; 01907 } 01908 if (p->exten && *str2 != '/') { 01909 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01910 if (score->exten) { 01911 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01912 return; /* the first match is all we need */ 01913 } 01914 } 01915 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01916 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01917 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01918 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01919 return; /* the first match is all we need */ 01920 } 01921 } 01922 } else if (p->x[0] == '/' && p->x[1] == 0) { 01923 /* the pattern in the tree includes the cid match! */ 01924 if (p->next_char && callerid && *callerid) { 01925 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01926 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01927 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01928 return; /* the first match is all we need */ 01929 } 01930 } 01931 } else if (strchr(p->x, *str)) { 01932 ast_debug(4, "Nothing strange about this match\n"); 01933 NEW_MATCHER_CHK_MATCH; 01934 NEW_MATCHER_RECURSE; 01935 } 01936 } else if (strchr(p->x, *str)) { 01937 ast_debug(4, "Nothing strange about this match\n"); 01938 NEW_MATCHER_CHK_MATCH; 01939 NEW_MATCHER_RECURSE; 01940 } 01941 } 01942 ast_debug(4, "return at end of func\n"); 01943 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 3311 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
03312 { 03313 int parens = 0; 03314 03315 *offset = 0; 03316 *length = INT_MAX; 03317 *isfunc = 0; 03318 for (; *var; var++) { 03319 if (*var == '(') { 03320 (*isfunc)++; 03321 parens++; 03322 } else if (*var == ')') { 03323 parens--; 03324 } else if (*var == ':' && parens == 0) { 03325 *var++ = '\0'; 03326 sscanf(var, "%30d:%30d", offset, length); 03327 return 1; /* offset:length valid */ 03328 } 03329 } 03330 return 0; 03331 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10709 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().
10710 { 10711 struct ast_var_t *vardata; 10712 10713 ast_rwlock_wrlock(&globalslock); 10714 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10715 ast_var_delete(vardata); 10716 ast_rwlock_unlock(&globalslock); 10717 }
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 10475 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().
10476 { 10477 struct ast_var_t *variables; 10478 const char *ret = NULL; 10479 int i; 10480 struct varshead *places[2] = { NULL, &globals }; 10481 10482 if (!name) 10483 return NULL; 10484 10485 if (chan) { 10486 ast_channel_lock(chan); 10487 places[0] = &chan->varshead; 10488 } 10489 10490 for (i = 0; i < 2; i++) { 10491 if (!places[i]) 10492 continue; 10493 if (places[i] == &globals) 10494 ast_rwlock_rdlock(&globalslock); 10495 AST_LIST_TRAVERSE(places[i], variables, entries) { 10496 if (!strcmp(name, ast_var_name(variables))) { 10497 ret = ast_var_value(variables); 10498 break; 10499 } 10500 } 10501 if (places[i] == &globals) 10502 ast_rwlock_unlock(&globalslock); 10503 if (ret) 10504 break; 10505 } 10506 10507 if (chan) 10508 ast_channel_unlock(chan); 10509 10510 return ret; 10511 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10731 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), and pbx_checkcondition().
10732 { 10733 char *condition, *branch1, *branch2, *branch; 10734 char *stringp; 10735 10736 if (ast_strlen_zero(data)) { 10737 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 10738 return 0; 10739 } 10740 10741 stringp = ast_strdupa(data); 10742 condition = strsep(&stringp,"?"); 10743 branch1 = strsep(&stringp,":"); 10744 branch2 = strsep(&stringp,""); 10745 branch = pbx_checkcondition(condition) ? branch1 : branch2; 10746 10747 if (ast_strlen_zero(branch)) { 10748 ast_debug(1, "Not taking any branch\n"); 10749 return 0; 10750 } 10751 10752 return pbx_builtin_goto(chan, branch); 10753 }
int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10669 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.
10670 { 10671 char *name; 10672 char *value; 10673 char *channel; 10674 char tmp[VAR_BUF_SIZE]; 10675 static int deprecation_warning = 0; 10676 10677 if (ast_strlen_zero(data)) { 10678 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 10679 return 0; 10680 } 10681 tmp[0] = 0; 10682 if (!deprecation_warning) { 10683 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 10684 deprecation_warning = 1; 10685 } 10686 10687 value = ast_strdupa(data); 10688 name = strsep(&value,"="); 10689 channel = strsep(&value,","); 10690 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 10691 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 10692 if (chan2) { 10693 char *s = ast_alloca(strlen(value) + 4); 10694 sprintf(s, "${%s}", value); 10695 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 10696 chan2 = ast_channel_unref(chan2); 10697 } 10698 pbx_builtin_setvar_helper(chan, name, tmp); 10699 } 10700 10701 return(0); 10702 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 9996 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().
09997 { 09998 const char *options = data; 09999 int answer = 1; 10000 10001 /* Some channels can receive DTMF in unanswered state; some cannot */ 10002 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 10003 answer = 0; 10004 } 10005 10006 /* If the channel is hungup, stop waiting */ 10007 if (ast_check_hangup(chan)) { 10008 return -1; 10009 } else if (chan->_state != AST_STATE_UP && answer) { 10010 __ast_answer(chan, 0, 1); 10011 } 10012 10013 ast_indicate(chan, AST_CONTROL_INCOMPLETE); 10014 10015 return AST_PBX_INCOMPLETE; 10016 }
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 10513 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().
10514 { 10515 struct ast_var_t *newvariable; 10516 struct varshead *headp; 10517 10518 if (name[strlen(name)-1] == ')') { 10519 char *function = ast_strdupa(name); 10520 10521 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10522 ast_func_write(chan, function, value); 10523 return; 10524 } 10525 10526 if (chan) { 10527 ast_channel_lock(chan); 10528 headp = &chan->varshead; 10529 } else { 10530 ast_rwlock_wrlock(&globalslock); 10531 headp = &globals; 10532 } 10533 10534 if (value && (newvariable = ast_var_assign(name, value))) { 10535 if (headp == &globals) 10536 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10537 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10538 } 10539 10540 if (chan) 10541 ast_channel_unlock(chan); 10542 else 10543 ast_rwlock_unlock(&globalslock); 10544 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason | |||
) |
Definition at line 3620 of file pbx.c.
References raise_exception().
03621 { 03622 /* Priority will become 1, next time through the AUTOLOOP */ 03623 return raise_exception(chan, reason, 0); 03624 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10792 of file pbx.c.
References ast_say_character_str().
10793 { 10794 int res = 0; 10795 10796 if (data) 10797 res = ast_say_character_str(chan, data, "", chan->language); 10798 return res; 10799 }
static int pbx_builtin_saydate | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10810 of file pbx.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_date, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), and pbx_builtin_setvar_helper().
10811 { 10812 int res = 0; 10813 char *parse; 10814 int unixdate = 0; 10815 char charascii[2]; 10816 10817 AST_DECLARE_APP_ARGS(args, 10818 AST_APP_ARG(datestr); 10819 AST_APP_ARG(digits); 10820 ); 10821 10822 10823 if (ast_strlen_zero(data)) { 10824 ast_log(LOG_WARNING, "SayDate requires an argument (date)\n"); 10825 return -1; 10826 } 10827 10828 if (!(parse = ast_strdupa(data))) { 10829 ast_log(LOG_WARNING, "Memory Error!\n"); 10830 return -1; 10831 } 10832 10833 AST_STANDARD_APP_ARGS(args, parse); 10834 10835 if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) { 10836 ast_log(LOG_WARNING, "SayDate escape digits must be a subset from '0123456789*#'\n"); 10837 args.digits = ""; 10838 } 10839 10840 if (sscanf(args.datestr, "%d", &unixdate) != 1) { 10841 ast_log(LOG_WARNING, "Firt argument to SayDate must be numeric (date)\n"); 10842 return -1; 10843 } 10844 10845 res = ast_say_date(chan, (time_t)unixdate, args.digits, chan->language); 10846 if (res > 0) { 10847 if (isdigit(res) || (res == '*') || (res == '#')) { 10848 snprintf(charascii, 2, "%c", res); 10849 pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii); 10850 res = 0; 10851 } else { 10852 ast_log(LOG_WARNING, "SayDate: invalid return value (%d) detected\n", res); 10853 } 10854 } 10855 return res; 10856 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10783 of file pbx.c.
References ast_say_digit_str().
10784 { 10785 int res = 0; 10786 10787 if (data) 10788 res = ast_say_digit_str(chan, data, "", chan->language); 10789 return res; 10790 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10755 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), and LOG_WARNING.
10756 { 10757 char tmp[256]; 10758 char *number = tmp; 10759 char *options; 10760 10761 if (ast_strlen_zero(data)) { 10762 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 10763 return -1; 10764 } 10765 ast_copy_string(tmp, data, sizeof(tmp)); 10766 strsep(&number, ","); 10767 options = strsep(&number, ","); 10768 if (options) { 10769 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 10770 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 10771 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 10772 return -1; 10773 } 10774 } 10775 10776 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 10777 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 10778 } 10779 10780 return 0; 10781 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10801 of file pbx.c.
References ast_say_phonetic_str().
10802 { 10803 int res = 0; 10804 10805 if (data) 10806 res = ast_say_phonetic_str(chan, data, "", chan->language); 10807 return res; 10808 }
static int pbx_builtin_saytime | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10858 of file pbx.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_time, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), and pbx_builtin_setvar_helper().
10859 { 10860 int res = 0; 10861 char *parse; 10862 int secs = 0; 10863 char charascii[2]; 10864 10865 AST_DECLARE_APP_ARGS(args, 10866 AST_APP_ARG(timestr); 10867 AST_APP_ARG(digits); 10868 ); 10869 10870 if (ast_strlen_zero(data)) { 10871 ast_log(LOG_WARNING, "SayTime requires an argument (time in seconds)\n"); 10872 return -1; 10873 } 10874 10875 if (!(parse = ast_strdupa(data))) { 10876 ast_log(LOG_WARNING, "Memory Error!\n"); 10877 return -1; 10878 } 10879 10880 AST_STANDARD_APP_ARGS(args, parse); 10881 10882 if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) { 10883 ast_log(LOG_WARNING, "SayTime escape digits must be a subset from '0123456789*#'\n"); 10884 args.digits = ""; 10885 } 10886 10887 if (sscanf(args.timestr, "%d", &secs) != 1) { 10888 ast_log(LOG_WARNING, "Firt argument to SayTime must be numeric (time in seconds)\n"); 10889 return -1; 10890 } 10891 10892 res = ast_say_time(chan, (time_t)secs, args.digits, chan->language); 10893 if (res > 0) { 10894 if (isdigit(res) || (res == '*') || (res == '#')) { 10895 snprintf(charascii, 2, "%c", res); 10896 pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii); 10897 res = 0; 10898 } else { 10899 ast_log(LOG_WARNING, "SayTime: invalid return value (%d) detected\n", res); 10900 } 10901 } 10902 return res; 10903 }
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 10444 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().
10445 { 10446 struct ast_var_t *variables; 10447 const char *var, *val; 10448 int total = 0; 10449 10450 if (!chan) 10451 return 0; 10452 10453 ast_str_reset(*buf); 10454 10455 ast_channel_lock(chan); 10456 10457 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10458 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10459 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10460 ) { 10461 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10462 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10463 break; 10464 } else 10465 total++; 10466 } else 10467 break; 10468 } 10469 10470 ast_channel_unlock(chan); 10471 10472 return total; 10473 }
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 10603 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().
10604 { 10605 char *name, *value, *mydata; 10606 10607 if (ast_compat_app_set) { 10608 return pbx_builtin_setvar_multiple(chan, data); 10609 } 10610 10611 if (ast_strlen_zero(data)) { 10612 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10613 return 0; 10614 } 10615 10616 mydata = ast_strdupa(data); 10617 name = strsep(&mydata, "="); 10618 value = mydata; 10619 if (!value) { 10620 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10621 return 0; 10622 } 10623 10624 if (strchr(name, ' ')) { 10625 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10626 } 10627 10628 pbx_builtin_setvar_helper(chan, name, value); 10629 10630 return 0; 10631 }
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 10546 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_saydate(), pbx_builtin_saytime(), 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().
10547 { 10548 struct ast_var_t *newvariable; 10549 struct varshead *headp; 10550 const char *nametail = name; 10551 10552 if (name[strlen(name) - 1] == ')') { 10553 char *function = ast_strdupa(name); 10554 10555 return ast_func_write(chan, function, value); 10556 } 10557 10558 if (chan) { 10559 ast_channel_lock(chan); 10560 headp = &chan->varshead; 10561 } else { 10562 ast_rwlock_wrlock(&globalslock); 10563 headp = &globals; 10564 } 10565 10566 /* For comparison purposes, we have to strip leading underscores */ 10567 if (*nametail == '_') { 10568 nametail++; 10569 if (*nametail == '_') 10570 nametail++; 10571 } 10572 10573 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10574 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10575 /* there is already such a variable, delete it */ 10576 AST_LIST_REMOVE_CURRENT(entries); 10577 ast_var_delete(newvariable); 10578 break; 10579 } 10580 } 10581 AST_LIST_TRAVERSE_SAFE_END; 10582 10583 if (value && (newvariable = ast_var_assign(name, value))) { 10584 if (headp == &globals) 10585 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10586 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10587 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10588 "Channel: %s\r\n" 10589 "Variable: %s\r\n" 10590 "Value: %s\r\n" 10591 "Uniqueid: %s\r\n", 10592 chan ? chan->name : "none", name, value, 10593 chan ? chan->uniqueid : "none"); 10594 } 10595 10596 if (chan) 10597 ast_channel_unlock(chan); 10598 else 10599 ast_rwlock_unlock(&globalslock); 10600 return 0; 10601 }
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 10633 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().
10634 { 10635 char *data; 10636 int x; 10637 AST_DECLARE_APP_ARGS(args, 10638 AST_APP_ARG(pair)[24]; 10639 ); 10640 AST_DECLARE_APP_ARGS(pair, 10641 AST_APP_ARG(name); 10642 AST_APP_ARG(value); 10643 ); 10644 10645 if (ast_strlen_zero(vdata)) { 10646 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10647 return 0; 10648 } 10649 10650 data = ast_strdupa(vdata); 10651 AST_STANDARD_APP_ARGS(args, data); 10652 10653 for (x = 0; x < args.argc; x++) { 10654 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10655 if (pair.argc == 2) { 10656 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10657 if (strchr(pair.name, ' ')) 10658 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); 10659 } else if (!chan) { 10660 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10661 } else { 10662 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10663 } 10664 } 10665 10666 return 0; 10667 }
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 10719 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().
10720 { 10721 int res; 10722 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10723 return 0; 10724 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10725 return res; 10726 } else { /* Strings are true */ 10727 return 1; 10728 } 10729 }
static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 1573 of file pbx.c.
References ast_free.
Referenced by __ast_pbx_run().
01574 { 01575 ast_free(p); 01576 }
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 1497 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().
01500 { 01501 int res; 01502 struct ast_module_user *u = NULL; 01503 const char *saved_c_appl; 01504 const char *saved_c_data; 01505 01506 if (c->cdr && !ast_check_hangup(c)) 01507 ast_cdr_setapp(c->cdr, app->name, data); 01508 01509 /* save channel values */ 01510 saved_c_appl= c->appl; 01511 saved_c_data= c->data; 01512 01513 c->appl = app->name; 01514 c->data = data; 01515 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01516 01517 if (app->module) 01518 u = __ast_module_user_add(app->module, c); 01519 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01520 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01521 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01522 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01523 app->name, (char *) data); 01524 } 01525 res = app->execute(c, S_OR(data, "")); 01526 if (app->module && u) 01527 __ast_module_user_remove(app->module, u); 01528 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01529 /* restore channel values */ 01530 c->appl = saved_c_appl; 01531 c->data = saved_c_data; 01532 return res; 01533 }
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 4706 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().
04709 { 04710 struct ast_exten *e; 04711 struct ast_app *app; 04712 char *substitute = NULL; 04713 int res; 04714 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04715 char passdata[EXT_DATA_SIZE]; 04716 04717 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04718 04719 ast_rdlock_contexts(); 04720 if (found) 04721 *found = 0; 04722 04723 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04724 if (e) { 04725 if (found) 04726 *found = 1; 04727 if (matching_action) { 04728 ast_unlock_contexts(); 04729 return -1; /* success, we found it */ 04730 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04731 res = e->priority; 04732 ast_unlock_contexts(); 04733 return res; /* the priority we were looking for */ 04734 } else { /* spawn */ 04735 if (!e->cached_app) 04736 e->cached_app = pbx_findapp(e->app); 04737 app = e->cached_app; 04738 if (ast_strlen_zero(e->data)) { 04739 *passdata = '\0'; 04740 } else { 04741 const char *tmp; 04742 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 04743 /* no variables to substitute, copy on through */ 04744 ast_copy_string(passdata, e->data, sizeof(passdata)); 04745 } else { 04746 /* save e->data on stack for later processing after lock released */ 04747 substitute = ast_strdupa(e->data); 04748 } 04749 } 04750 ast_unlock_contexts(); 04751 if (!app) { 04752 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04753 return -1; 04754 } 04755 if (c->context != context) 04756 ast_copy_string(c->context, context, sizeof(c->context)); 04757 if (c->exten != exten) 04758 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04759 c->priority = priority; 04760 if (substitute) { 04761 pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1); 04762 } 04763 #ifdef CHANNEL_TRACE 04764 ast_channel_trace_update(c); 04765 #endif 04766 ast_debug(1, "Launching '%s'\n", app->name); 04767 if (VERBOSITY_ATLEAST(3)) { 04768 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04769 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04770 exten, context, priority, 04771 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04772 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04773 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04774 "in new stack"); 04775 } 04776 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04777 "Channel: %s\r\n" 04778 "Context: %s\r\n" 04779 "Extension: %s\r\n" 04780 "Priority: %d\r\n" 04781 "Application: %s\r\n" 04782 "AppData: %s\r\n" 04783 "Uniqueid: %s\r\n", 04784 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 04785 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04786 } 04787 } else if (q.swo) { /* not found here, but in another switch */ 04788 if (found) 04789 *found = 1; 04790 ast_unlock_contexts(); 04791 if (matching_action) { 04792 return -1; 04793 } else { 04794 if (!q.swo->exec) { 04795 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04796 res = -1; 04797 } 04798 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04799 } 04800 } else { /* not found anywhere, see what happened */ 04801 ast_unlock_contexts(); 04802 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04803 switch (q.status) { 04804 case STATUS_NO_CONTEXT: 04805 if (!matching_action && !combined_find_spawn) 04806 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04807 break; 04808 case STATUS_NO_EXTENSION: 04809 if (!matching_action && !combined_find_spawn) 04810 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04811 break; 04812 case STATUS_NO_PRIORITY: 04813 if (!matching_action && !combined_find_spawn) 04814 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04815 break; 04816 case STATUS_NO_LABEL: 04817 if (context && !combined_find_spawn) 04818 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04819 break; 04820 default: 04821 ast_debug(1, "Shouldn't happen!\n"); 04822 } 04823 04824 return (matching_action) ? 0 : -1; 04825 } 04826 }
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 3013 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().
03017 { 03018 int x, res; 03019 struct ast_context *tmp = NULL; 03020 struct ast_exten *e = NULL, *eroot = NULL; 03021 struct ast_include *i = NULL; 03022 struct ast_sw *sw = NULL; 03023 struct ast_exten pattern = {NULL, }; 03024 struct scoreboard score = {0, }; 03025 struct ast_str *tmpdata = NULL; 03026 03027 pattern.label = label; 03028 pattern.priority = priority; 03029 #ifdef NEED_DEBUG_HERE 03030 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 03031 #endif 03032 03033 /* Initialize status if appropriate */ 03034 if (q->stacklen == 0) { 03035 q->status = STATUS_NO_CONTEXT; 03036 q->swo = NULL; 03037 q->data = NULL; 03038 q->foundcontext = NULL; 03039 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 03040 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 03041 return NULL; 03042 } 03043 03044 /* Check first to see if we've already been checked */ 03045 for (x = 0; x < q->stacklen; x++) { 03046 if (!strcasecmp(q->incstack[x], context)) 03047 return NULL; 03048 } 03049 03050 if (bypass) { /* bypass means we only look there */ 03051 tmp = bypass; 03052 } else { /* look in contexts */ 03053 tmp = find_context(context); 03054 if (!tmp) { 03055 return NULL; 03056 } 03057 } 03058 03059 if (q->status < STATUS_NO_EXTENSION) 03060 q->status = STATUS_NO_EXTENSION; 03061 03062 /* Do a search for matching extension */ 03063 03064 eroot = NULL; 03065 score.total_specificity = 0; 03066 score.exten = 0; 03067 score.total_length = 0; 03068 if (!tmp->pattern_tree && tmp->root_table) { 03069 create_match_char_tree(tmp); 03070 #ifdef NEED_DEBUG 03071 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 03072 log_match_char_tree(tmp->pattern_tree," "); 03073 #endif 03074 } 03075 #ifdef NEED_DEBUG 03076 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03077 log_match_char_tree(tmp->pattern_tree, ":: "); 03078 #endif 03079 03080 do { 03081 if (!ast_strlen_zero(overrideswitch)) { 03082 char *osw = ast_strdupa(overrideswitch), *name; 03083 struct ast_switch *asw; 03084 ast_switch_f *aswf = NULL; 03085 char *datap; 03086 int eval = 0; 03087 03088 name = strsep(&osw, "/"); 03089 asw = pbx_findswitch(name); 03090 03091 if (!asw) { 03092 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03093 break; 03094 } 03095 03096 if (osw && strchr(osw, '$')) { 03097 eval = 1; 03098 } 03099 03100 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03101 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03102 break; 03103 } else if (eval) { 03104 /* Substitute variables now */ 03105 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03106 datap = ast_str_buffer(tmpdata); 03107 } else { 03108 datap = osw; 03109 } 03110 03111 /* equivalent of extension_match_core() at the switch level */ 03112 if (action == E_CANMATCH) 03113 aswf = asw->canmatch; 03114 else if (action == E_MATCHMORE) 03115 aswf = asw->matchmore; 03116 else /* action == E_MATCH */ 03117 aswf = asw->exists; 03118 if (!aswf) { 03119 res = 0; 03120 } else { 03121 if (chan) { 03122 ast_autoservice_start(chan); 03123 } 03124 res = aswf(chan, context, exten, priority, callerid, datap); 03125 if (chan) { 03126 ast_autoservice_stop(chan); 03127 } 03128 } 03129 if (res) { /* Got a match */ 03130 q->swo = asw; 03131 q->data = datap; 03132 q->foundcontext = context; 03133 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03134 return NULL; 03135 } 03136 } 03137 } while (0); 03138 03139 if (extenpatternmatchnew) { 03140 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03141 eroot = score.exten; 03142 03143 if (score.last_char == '!' && action == E_MATCHMORE) { 03144 /* We match an extension ending in '!'. 03145 * The decision in this case is final and is NULL (no match). 03146 */ 03147 #ifdef NEED_DEBUG_HERE 03148 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03149 #endif 03150 return NULL; 03151 } 03152 03153 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03154 q->status = STATUS_SUCCESS; 03155 #ifdef NEED_DEBUG_HERE 03156 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03157 #endif 03158 return score.canmatch_exten; 03159 } 03160 03161 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03162 if (score.node) { 03163 struct ast_exten *z = trie_find_next_match(score.node); 03164 if (z) { 03165 #ifdef NEED_DEBUG_HERE 03166 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03167 #endif 03168 } else { 03169 if (score.canmatch_exten) { 03170 #ifdef NEED_DEBUG_HERE 03171 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03172 #endif 03173 return score.canmatch_exten; 03174 } else { 03175 #ifdef NEED_DEBUG_HERE 03176 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03177 #endif 03178 } 03179 } 03180 return z; 03181 } 03182 #ifdef NEED_DEBUG_HERE 03183 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03184 #endif 03185 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03186 } 03187 03188 if (eroot) { 03189 /* found entry, now look for the right priority */ 03190 if (q->status < STATUS_NO_PRIORITY) 03191 q->status = STATUS_NO_PRIORITY; 03192 e = NULL; 03193 if (action == E_FINDLABEL && label ) { 03194 if (q->status < STATUS_NO_LABEL) 03195 q->status = STATUS_NO_LABEL; 03196 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03197 } else { 03198 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03199 } 03200 if (e) { /* found a valid match */ 03201 q->status = STATUS_SUCCESS; 03202 q->foundcontext = context; 03203 #ifdef NEED_DEBUG_HERE 03204 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03205 #endif 03206 return e; 03207 } 03208 } 03209 } else { /* the old/current default exten pattern match algorithm */ 03210 03211 /* scan the list trying to match extension and CID */ 03212 eroot = NULL; 03213 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03214 int match = extension_match_core(eroot->exten, exten, action); 03215 /* 0 on fail, 1 on match, 2 on earlymatch */ 03216 03217 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03218 continue; /* keep trying */ 03219 if (match == 2 && action == E_MATCHMORE) { 03220 /* We match an extension ending in '!'. 03221 * The decision in this case is final and is NULL (no match). 03222 */ 03223 return NULL; 03224 } 03225 /* found entry, now look for the right priority */ 03226 if (q->status < STATUS_NO_PRIORITY) 03227 q->status = STATUS_NO_PRIORITY; 03228 e = NULL; 03229 if (action == E_FINDLABEL && label ) { 03230 if (q->status < STATUS_NO_LABEL) 03231 q->status = STATUS_NO_LABEL; 03232 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03233 } else { 03234 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03235 } 03236 if (e) { /* found a valid match */ 03237 q->status = STATUS_SUCCESS; 03238 q->foundcontext = context; 03239 return e; 03240 } 03241 } 03242 } 03243 03244 /* Check alternative switches */ 03245 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03246 struct ast_switch *asw = pbx_findswitch(sw->name); 03247 ast_switch_f *aswf = NULL; 03248 char *datap; 03249 03250 if (!asw) { 03251 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03252 continue; 03253 } 03254 03255 /* Substitute variables now */ 03256 if (sw->eval) { 03257 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03258 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03259 continue; 03260 } 03261 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03262 } 03263 03264 /* equivalent of extension_match_core() at the switch level */ 03265 if (action == E_CANMATCH) 03266 aswf = asw->canmatch; 03267 else if (action == E_MATCHMORE) 03268 aswf = asw->matchmore; 03269 else /* action == E_MATCH */ 03270 aswf = asw->exists; 03271 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03272 if (!aswf) 03273 res = 0; 03274 else { 03275 if (chan) 03276 ast_autoservice_start(chan); 03277 res = aswf(chan, context, exten, priority, callerid, datap); 03278 if (chan) 03279 ast_autoservice_stop(chan); 03280 } 03281 if (res) { /* Got a match */ 03282 q->swo = asw; 03283 q->data = datap; 03284 q->foundcontext = context; 03285 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03286 return NULL; 03287 } 03288 } 03289 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03290 /* Now try any includes we have in this context */ 03291 for (i = tmp->includes; i; i = i->next) { 03292 if (include_valid(i)) { 03293 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03294 #ifdef NEED_DEBUG_HERE 03295 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03296 #endif 03297 return e; 03298 } 03299 if (q->swo) 03300 return NULL; 03301 } 03302 } 03303 return NULL; 03304 }
struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 1537 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().
01538 { 01539 struct ast_app *tmp; 01540 01541 AST_RWLIST_RDLOCK(&apps); 01542 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01543 if (!strcasecmp(tmp->name, app)) 01544 break; 01545 } 01546 AST_RWLIST_UNLOCK(&apps); 01547 01548 return tmp; 01549 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 1551 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
01552 { 01553 struct ast_switch *asw; 01554 01555 AST_RWLIST_RDLOCK(&switches); 01556 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01557 if (!strcasecmp(asw->name, sw)) 01558 break; 01559 } 01560 AST_RWLIST_UNLOCK(&switches); 01561 01562 return asw; 01563 }
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 4059 of file pbx.c.
References ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by ast_readconfig().
04060 { 04061 if (new_live_dangerously && !live_dangerously) { 04062 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n" 04063 "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n"); 04064 } 04065 04066 if (!new_live_dangerously && live_dangerously) { 04067 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n"); 04068 } 04069 live_dangerously = new_live_dangerously; 04070 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 11271 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().
11272 { 11273 char *exten, *pri, *context; 11274 char *stringp; 11275 int ipri; 11276 int mode = 0; 11277 11278 if (ast_strlen_zero(goto_string)) { 11279 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 11280 return -1; 11281 } 11282 stringp = ast_strdupa(goto_string); 11283 context = strsep(&stringp, ","); /* guaranteed non-null */ 11284 exten = strsep(&stringp, ","); 11285 pri = strsep(&stringp, ","); 11286 if (!exten) { /* Only a priority in this one */ 11287 pri = context; 11288 exten = NULL; 11289 context = NULL; 11290 } else if (!pri) { /* Only an extension and priority in this one */ 11291 pri = exten; 11292 exten = context; 11293 context = NULL; 11294 } 11295 if (*pri == '+') { 11296 mode = 1; 11297 pri++; 11298 } else if (*pri == '-') { 11299 mode = -1; 11300 pri++; 11301 } 11302 if (sscanf(pri, "%30d", &ipri) != 1) { 11303 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 11304 exten ? exten : chan->exten, pri, 11305 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 11306 if (ipri < 1) { 11307 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 11308 return -1; 11309 } else 11310 mode = 0; 11311 } 11312 /* At this point we have a priority and maybe an extension and a context */ 11313 11314 if (mode) 11315 ipri = chan->priority + (ipri * mode); 11316 11317 if (async) 11318 ast_async_goto(chan, context, exten, ipri); 11319 else 11320 ast_explicit_goto(chan, context, exten, ipri); 11321 11322 return 0; 11323 11324 }
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 3434 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().
03435 { 03436 struct ast_str *str = ast_str_create(16); 03437 const char *cret; 03438 03439 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03440 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03441 *ret = cret ? workspace : NULL; 03442 ast_free(str); 03443 }
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 5941 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05942 { 05943 int oldval = autofallthrough; 05944 autofallthrough = newval; 05945 return oldval; 05946 }
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 5948 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05949 { 05950 int oldval = extenpatternmatchnew; 05951 extenpatternmatchnew = newval; 05952 return oldval; 05953 }
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 5955 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05956 { 05957 if (overrideswitch) { 05958 ast_free(overrideswitch); 05959 } 05960 if (!ast_strlen_zero(newval)) { 05961 overrideswitch = ast_strdup(newval); 05962 } else { 05963 overrideswitch = NULL; 05964 } 05965 }
static void pbx_shutdown | ( | void | ) | [static] |
Definition at line 11391 of file pbx.c.
References ao2_ref, ast_hashtab_destroy(), contexts_table, hints, pbx_builtin_clear_globals(), and statecbs.
Referenced by ast_pbx_init().
11392 { 11393 if (hints) { 11394 ao2_ref(hints, -1); 11395 hints = NULL; 11396 } 11397 if (statecbs) { 11398 ao2_ref(statecbs, -1); 11399 statecbs = NULL; 11400 } 11401 if (contexts_table) { 11402 ast_hashtab_destroy(contexts_table, NULL); 11403 } 11404 pbx_builtin_clear_globals(); 11405 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4676 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().
04677 { 04678 size_t used; 04679 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04680 }
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 4480 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().
04481 { 04482 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04483 char *cp4 = NULL; 04484 const char *tmp, *whereweare, *orig_cp2 = cp2; 04485 int length, offset, offset2, isfunction; 04486 char *workspace = NULL; 04487 char *ltmp = NULL, *var = NULL; 04488 char *nextvar, *nextexp, *nextthing; 04489 char *vars, *vare; 04490 int pos, brackets, needsub, len; 04491 04492 *cp2 = 0; /* just in case nothing ends up there */ 04493 whereweare=tmp=cp1; 04494 while (!ast_strlen_zero(whereweare) && count) { 04495 /* Assume we're copying the whole remaining string */ 04496 pos = strlen(whereweare); 04497 nextvar = NULL; 04498 nextexp = NULL; 04499 nextthing = strchr(whereweare, '$'); 04500 if (nextthing) { 04501 switch (nextthing[1]) { 04502 case '{': 04503 nextvar = nextthing; 04504 pos = nextvar - whereweare; 04505 break; 04506 case '[': 04507 nextexp = nextthing; 04508 pos = nextexp - whereweare; 04509 break; 04510 default: 04511 pos = 1; 04512 } 04513 } 04514 04515 if (pos) { 04516 /* Can't copy more than 'count' bytes */ 04517 if (pos > count) 04518 pos = count; 04519 04520 /* Copy that many bytes */ 04521 memcpy(cp2, whereweare, pos); 04522 04523 count -= pos; 04524 cp2 += pos; 04525 whereweare += pos; 04526 *cp2 = 0; 04527 } 04528 04529 if (nextvar) { 04530 /* We have a variable. Find the start and end, and determine 04531 if we are going to have to recursively call ourselves on the 04532 contents */ 04533 vars = vare = nextvar + 2; 04534 brackets = 1; 04535 needsub = 0; 04536 04537 /* Find the end of it */ 04538 while (brackets && *vare) { 04539 if ((vare[0] == '$') && (vare[1] == '{')) { 04540 needsub++; 04541 } else if (vare[0] == '{') { 04542 brackets++; 04543 } else if (vare[0] == '}') { 04544 brackets--; 04545 } else if ((vare[0] == '$') && (vare[1] == '[')) 04546 needsub++; 04547 vare++; 04548 } 04549 if (brackets) 04550 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04551 len = vare - vars - 1; 04552 04553 /* Skip totally over variable string */ 04554 whereweare += (len + 3); 04555 04556 if (!var) 04557 var = ast_alloca(VAR_BUF_SIZE); 04558 04559 /* Store variable name (and truncate) */ 04560 ast_copy_string(var, vars, len + 1); 04561 04562 /* Substitute if necessary */ 04563 if (needsub) { 04564 size_t used; 04565 if (!ltmp) 04566 ltmp = ast_alloca(VAR_BUF_SIZE); 04567 04568 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04569 vars = ltmp; 04570 } else { 04571 vars = var; 04572 } 04573 04574 if (!workspace) 04575 workspace = ast_alloca(VAR_BUF_SIZE); 04576 04577 workspace[0] = '\0'; 04578 04579 parse_variable_name(vars, &offset, &offset2, &isfunction); 04580 if (isfunction) { 04581 /* Evaluate function */ 04582 if (c || !headp) 04583 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04584 else { 04585 struct varshead old; 04586 struct ast_channel *c = ast_dummy_channel_alloc(); 04587 if (c) { 04588 memcpy(&old, &c->varshead, sizeof(old)); 04589 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04590 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04591 /* Don't deallocate the varshead that was passed in */ 04592 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04593 c = ast_channel_unref(c); 04594 } else { 04595 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04596 } 04597 } 04598 ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)"); 04599 } else { 04600 /* Retrieve variable value */ 04601 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04602 } 04603 if (cp4) { 04604 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04605 04606 length = strlen(cp4); 04607 if (length > count) 04608 length = count; 04609 memcpy(cp2, cp4, length); 04610 count -= length; 04611 cp2 += length; 04612 *cp2 = 0; 04613 } 04614 } else if (nextexp) { 04615 /* We have an expression. Find the start and end, and determine 04616 if we are going to have to recursively call ourselves on the 04617 contents */ 04618 vars = vare = nextexp + 2; 04619 brackets = 1; 04620 needsub = 0; 04621 04622 /* Find the end of it */ 04623 while (brackets && *vare) { 04624 if ((vare[0] == '$') && (vare[1] == '[')) { 04625 needsub++; 04626 brackets++; 04627 vare++; 04628 } else if (vare[0] == '[') { 04629 brackets++; 04630 } else if (vare[0] == ']') { 04631 brackets--; 04632 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04633 needsub++; 04634 vare++; 04635 } 04636 vare++; 04637 } 04638 if (brackets) 04639 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04640 len = vare - vars - 1; 04641 04642 /* Skip totally over expression */ 04643 whereweare += (len + 3); 04644 04645 if (!var) 04646 var = ast_alloca(VAR_BUF_SIZE); 04647 04648 /* Store variable name (and truncate) */ 04649 ast_copy_string(var, vars, len + 1); 04650 04651 /* Substitute if necessary */ 04652 if (needsub) { 04653 size_t used; 04654 if (!ltmp) 04655 ltmp = ast_alloca(VAR_BUF_SIZE); 04656 04657 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04658 vars = ltmp; 04659 } else { 04660 vars = var; 04661 } 04662 04663 length = ast_expr(vars, cp2, count, c); 04664 04665 if (length) { 04666 ast_debug(1, "Expression result is '%s'\n", cp2); 04667 count -= length; 04668 cp2 += length; 04669 *cp2 = 0; 04670 } 04671 } 04672 } 04673 *used = cp2 - orig_cp2; 04674 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4682 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04683 { 04684 size_t used; 04685 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04686 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5859 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05860 { 05861 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05862 answer this channel and get it going. 05863 */ 05864 /* NOTE: 05865 The launcher of this function _MUST_ increment 'countcalls' 05866 before invoking the function; it will be decremented when the 05867 PBX has finished running on the channel 05868 */ 05869 struct ast_channel *c = data; 05870 05871 __ast_pbx_run(c, NULL); 05872 decrease_call_count(); 05873 05874 pthread_exit(NULL); 05875 05876 return NULL; 05877 }
static void print_app_docs | ( | struct ast_app * | aa, | |
int | fd | |||
) | [static] |
Definition at line 6468 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().
06469 { 06470 /* Maximum number of characters added by terminal coloring is 22 */ 06471 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 06472 char seealsotitle[40]; 06473 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 06474 char *seealso = NULL; 06475 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 06476 06477 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 06478 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 06479 06480 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 06481 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 06482 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 06483 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 06484 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 06485 06486 #ifdef AST_XML_DOCS 06487 if (aa->docsrc == AST_XML_DOC) { 06488 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 06489 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 06490 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 06491 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 06492 06493 if (!synopsis || !description || !arguments || !seealso) { 06494 goto return_cleanup; 06495 } 06496 } else 06497 #endif 06498 { 06499 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06500 synopsis = ast_malloc(synopsis_size); 06501 06502 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06503 description = ast_malloc(description_size); 06504 06505 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06506 arguments = ast_malloc(arguments_size); 06507 06508 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06509 seealso = ast_malloc(seealso_size); 06510 06511 if (!synopsis || !description || !arguments || !seealso) { 06512 goto return_cleanup; 06513 } 06514 06515 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 06516 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 06517 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 06518 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 06519 } 06520 06521 /* Handle the syntax the same for both XML and raw docs */ 06522 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06523 if (!(syntax = ast_malloc(syntax_size))) { 06524 goto return_cleanup; 06525 } 06526 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 06527 06528 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 06529 infotitle, syntitle, synopsis, destitle, description, 06530 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 06531 06532 return_cleanup: 06533 ast_free(description); 06534 ast_free(arguments); 06535 ast_free(synopsis); 06536 ast_free(seealso); 06537 ast_free(syntax); 06538 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 6905 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().
06906 { 06907 int prio = ast_get_extension_priority(e); 06908 if (prio == PRIORITY_HINT) { 06909 snprintf(buf, buflen, "hint: %s", 06910 ast_get_extension_app(e)); 06911 } else { 06912 snprintf(buf, buflen, "%d. %s(%s)", 06913 prio, ast_get_extension_app(e), 06914 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06915 } 06916 }
static int raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason, | |||
int | priority | |||
) | [static] |
Definition at line 3594 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().
03595 { 03596 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03597 struct pbx_exception *exception = NULL; 03598 03599 if (!ds) { 03600 ds = ast_datastore_alloc(&exception_store_info, NULL); 03601 if (!ds) 03602 return -1; 03603 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03604 ast_datastore_free(ds); 03605 return -1; 03606 } 03607 ds->data = exception; 03608 ast_channel_datastore_add(chan, ds); 03609 } else 03610 exception = ds->data; 03611 03612 ast_string_field_set(exception, reason, reason); 03613 ast_string_field_set(exception, context, chan->context); 03614 ast_string_field_set(exception, exten, chan->exten); 03615 exception->priority = chan->priority; 03616 set_ext_pri(chan, "e", priority); 03617 return 0; 03618 }
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 3856 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().
03856 { 03857 int res = 0; 03858 struct ast_custom_escalating_function *cur_escalation; 03859 03860 AST_RWLIST_RDLOCK(&escalation_root); 03861 AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) { 03862 if (cur_escalation->acf == acf) { 03863 res = cur_escalation->read_escalates; 03864 break; 03865 } 03866 } 03867 AST_RWLIST_UNLOCK(&escalation_root); 03868 return res; 03869 }
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 5431 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().
05432 { 05433 ast_channel_lock(c); 05434 ast_copy_string(c->exten, exten, sizeof(c->exten)); 05435 c->priority = pri; 05436 ast_channel_unlock(c); 05437 }
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 7074 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().
07075 { 07076 struct ast_context *c = NULL; 07077 int res = 0, old_total_exten = dpc->total_exten; 07078 07079 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 07080 07081 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 07082 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 07083 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 07084 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 07085 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 07086 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 07087 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 07088 ast_rdlock_contexts(); 07089 07090 /* walk all contexts ... */ 07091 while ( (c = ast_walk_contexts(c)) ) { 07092 int context_info_printed = 0; 07093 07094 if (context && strcmp(ast_get_context_name(c), context)) 07095 continue; /* skip this one, name doesn't match */ 07096 07097 dpc->context_existence = 1; 07098 07099 if (!c->pattern_tree) { 07100 /* Ignore check_return warning from Coverity for ast_exists_extension below */ 07101 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 07102 } 07103 07104 ast_rdlock_context(c); 07105 07106 dpc->total_context++; 07107 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 07108 ast_get_context_name(c), ast_get_context_registrar(c)); 07109 context_info_printed = 1; 07110 07111 if (c->pattern_tree) 07112 { 07113 cli_match_char_tree(c->pattern_tree, " ", fd); 07114 } else { 07115 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 07116 } 07117 07118 ast_unlock_context(c); 07119 07120 /* if we print something in context, make an empty line */ 07121 if (context_info_printed) 07122 ast_cli(fd, "\n"); 07123 } 07124 ast_unlock_contexts(); 07125 07126 return (dpc->total_exten == old_total_exten) ? -1 : res; 07127 }
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 6919 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().
06920 { 06921 struct ast_context *c = NULL; 06922 int res = 0, old_total_exten = dpc->total_exten; 06923 06924 ast_rdlock_contexts(); 06925 06926 /* walk all contexts ... */ 06927 while ( (c = ast_walk_contexts(c)) ) { 06928 struct ast_exten *e; 06929 struct ast_include *i; 06930 struct ast_ignorepat *ip; 06931 #ifndef LOW_MEMORY 06932 char buf[1024], buf2[1024]; 06933 #else 06934 char buf[256], buf2[256]; 06935 #endif 06936 int context_info_printed = 0; 06937 06938 if (context && strcmp(ast_get_context_name(c), context)) 06939 continue; /* skip this one, name doesn't match */ 06940 06941 dpc->context_existence = 1; 06942 06943 ast_rdlock_context(c); 06944 06945 /* are we looking for exten too? if yes, we print context 06946 * only if we find our extension. 06947 * Otherwise print context even if empty ? 06948 * XXX i am not sure how the rinclude is handled. 06949 * I think it ought to go inside. 06950 */ 06951 if (!exten) { 06952 dpc->total_context++; 06953 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06954 ast_get_context_name(c), ast_get_context_registrar(c)); 06955 context_info_printed = 1; 06956 } 06957 06958 /* walk extensions ... */ 06959 e = NULL; 06960 while ( (e = ast_walk_context_extensions(c, e)) ) { 06961 struct ast_exten *p; 06962 06963 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06964 continue; /* skip, extension match failed */ 06965 06966 dpc->extension_existence = 1; 06967 06968 /* may we print context info? */ 06969 if (!context_info_printed) { 06970 dpc->total_context++; 06971 if (rinclude) { /* TODO Print more info about rinclude */ 06972 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06973 ast_get_context_name(c), ast_get_context_registrar(c)); 06974 } else { 06975 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06976 ast_get_context_name(c), ast_get_context_registrar(c)); 06977 } 06978 context_info_printed = 1; 06979 } 06980 dpc->total_prio++; 06981 06982 /* write extension name and first peer */ 06983 if (e->matchcid == AST_EXT_MATCHCID_ON) 06984 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06985 else 06986 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06987 06988 print_ext(e, buf2, sizeof(buf2)); 06989 06990 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06991 ast_get_extension_registrar(e)); 06992 06993 dpc->total_exten++; 06994 /* walk next extension peers */ 06995 p = e; /* skip the first one, we already got it */ 06996 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06997 const char *el = ast_get_extension_label(p); 06998 dpc->total_prio++; 06999 if (el) 07000 snprintf(buf, sizeof(buf), " [%s]", el); 07001 else 07002 buf[0] = '\0'; 07003 print_ext(p, buf2, sizeof(buf2)); 07004 07005 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 07006 ast_get_extension_registrar(p)); 07007 } 07008 } 07009 07010 /* walk included and write info ... */ 07011 i = NULL; 07012 while ( (i = ast_walk_context_includes(c, i)) ) { 07013 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 07014 if (exten) { 07015 /* Check all includes for the requested extension */ 07016 if (includecount >= AST_PBX_MAX_STACK) { 07017 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 07018 } else { 07019 int dupe = 0; 07020 int x; 07021 for (x = 0; x < includecount; x++) { 07022 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 07023 dupe++; 07024 break; 07025 } 07026 } 07027 if (!dupe) { 07028 includes[includecount] = ast_get_include_name(i); 07029 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 07030 } else { 07031 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 07032 } 07033 } 07034 } else { 07035 ast_cli(fd, " Include => %-45s [%s]\n", 07036 buf, ast_get_include_registrar(i)); 07037 } 07038 } 07039 07040 /* walk ignore patterns and write info ... */ 07041 ip = NULL; 07042 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 07043 const char *ipname = ast_get_ignorepat_name(ip); 07044 char ignorepat[AST_MAX_EXTENSION]; 07045 snprintf(buf, sizeof(buf), "'%s'", ipname); 07046 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 07047 if (!exten || ast_extension_match(ignorepat, exten)) { 07048 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 07049 buf, ast_get_ignorepat_registrar(ip)); 07050 } 07051 } 07052 if (!rinclude) { 07053 struct ast_sw *sw = NULL; 07054 while ( (sw = ast_walk_context_switches(c, sw)) ) { 07055 snprintf(buf, sizeof(buf), "'%s/%s'", 07056 ast_get_switch_name(sw), 07057 ast_get_switch_data(sw)); 07058 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 07059 buf, ast_get_switch_registrar(sw)); 07060 } 07061 } 07062 07063 ast_unlock_context(c); 07064 07065 /* if we print something in context, make an empty line */ 07066 if (context_info_printed) 07067 ast_cli(fd, "\n"); 07068 } 07069 ast_unlock_contexts(); 07070 07071 return (dpc->total_exten == old_total_exten) ? -1 : res; 07072 }
static int statecbs_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11383 of file pbx.c.
References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
11384 { 11385 const struct ast_state_cb *state_cb = obj; 11386 ast_state_cb_type change_cb = arg; 11387 11388 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; 11389 }
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 3344 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
03345 { 03346 char *ret = workspace; 03347 int lr; /* length of the input string after the copy */ 03348 03349 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 03350 03351 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 03352 03353 /* Quick check if no need to do anything */ 03354 if (offset == 0 && length >= lr) /* take the whole string */ 03355 return ret; 03356 03357 if (offset < 0) { /* translate negative offset into positive ones */ 03358 offset = lr + offset; 03359 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03360 offset = 0; 03361 } 03362 03363 /* too large offset result in empty string so we know what to return */ 03364 if (offset >= lr) 03365 return ret + lr; /* the final '\0' */ 03366 03367 ret += offset; /* move to the start position */ 03368 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 03369 ret[length] = '\0'; 03370 else if (length < 0) { 03371 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 03372 ret[lr + length - offset] = '\0'; 03373 else 03374 ret[0] = '\0'; 03375 } 03376 03377 return ret; 03378 }
static int thread_inhibits_escalations | ( | void | ) | [static] |
Indicates whether the current thread inhibits the execution of dangerous functions.
Definition at line 4095 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().
04096 { 04097 int *thread_inhibit_escalations; 04098 04099 thread_inhibit_escalations = ast_threadstorage_get( 04100 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04101 04102 if (thread_inhibit_escalations == NULL) { 04103 ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n"); 04104 /* On error, assume that we are inhibiting */ 04105 return 1; 04106 } 04107 04108 return *thread_inhibit_escalations; 04109 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1748 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().
01749 { 01750 struct match_char *m3; 01751 struct match_char *m4; 01752 struct ast_exten *e3; 01753 01754 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01755 return node->exten; 01756 } 01757 01758 if (node && node->x[0] == '!' && !node->x[1]) { 01759 return node->exten; 01760 } 01761 01762 if (!node || !node->next_char) { 01763 return NULL; 01764 } 01765 01766 m3 = node->next_char; 01767 01768 if (m3->exten) { 01769 return m3->exten; 01770 } 01771 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01772 if (m4->exten) { 01773 return m4->exten; 01774 } 01775 } 01776 for (m4 = m3; m4; m4 = m4->alt_char) { 01777 e3 = trie_find_next_match(m3); 01778 if (e3) { 01779 return e3; 01780 } 01781 } 01782 01783 return NULL; 01784 }
static void unload_pbx | ( | void | ) | [static] |
Definition at line 10973 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().
10974 { 10975 int x; 10976 10977 if (device_state_sub) { 10978 device_state_sub = ast_event_unsubscribe(device_state_sub); 10979 } 10980 if (device_state_tps) { 10981 ast_taskprocessor_unreference(device_state_tps); 10982 device_state_tps = NULL; 10983 } 10984 10985 /* Unregister builtin applications */ 10986 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10987 ast_unregister_application(builtins[x].name); 10988 } 10989 ast_manager_unregister("ShowDialPlan"); 10990 ast_cli_unregister_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10991 ast_custom_function_unregister(&exception_function); 10992 ast_custom_function_unregister(&testtime_function); 10993 ast_data_unregister(NULL); 10994 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 7686 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().
07687 { 07688 struct ast_context *context = NULL; 07689 struct ast_exten *eroot = NULL, *e = NULL; 07690 07691 ast_rdlock_contexts(); 07692 while ((context = ast_walk_contexts(context))) { 07693 while ((eroot = ast_walk_context_extensions(context, eroot))) { 07694 while ((e = ast_walk_extension_priorities(eroot, e))) { 07695 if (e->cached_app == app) 07696 e->cached_app = NULL; 07697 } 07698 } 07699 } 07700 ast_unlock_contexts(); 07701 07702 return; 07703 }
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 1652 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().
01653 { 01654 /* if this extension is marked as deleted, then skip this -- if it never shows 01655 on the scoreboard, it will never be found, nor will halt the traversal. */ 01656 if (deleted) 01657 return; 01658 board->total_specificity = spec; 01659 board->total_length = length; 01660 board->exten = exten; 01661 board->last_char = last; 01662 board->node = node; 01663 #ifdef NEED_DEBUG_HERE 01664 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01665 #endif 01666 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
const void * | data | |||
) | [static] |
Definition at line 9882 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().
09883 { 09884 int res; 09885 struct ast_frame *f; 09886 double waitsec; 09887 int waittime; 09888 09889 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 09890 waitsec = -1; 09891 if (waitsec > -1) { 09892 waittime = waitsec * 1000.0; 09893 ast_safe_sleep(chan, waittime); 09894 } else do { 09895 res = ast_waitfor(chan, -1); 09896 if (res < 0) 09897 return; 09898 f = ast_read(chan); 09899 if (f) 09900 ast_frfree(f); 09901 } while(f); 09902 }
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 3878 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().
03878 { 03879 int res = 0; 03880 struct ast_custom_escalating_function *cur_escalation; 03881 03882 AST_RWLIST_RDLOCK(&escalation_root); 03883 AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) { 03884 if (cur_escalation->acf == acf) { 03885 res = cur_escalation->write_escalates; 03886 break; 03887 } 03888 } 03889 AST_RWLIST_UNLOCK(&escalation_root); 03890 return res; 03891 }
int autofallthrough = 1 [static] |
Definition at line 1220 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 849 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 1294 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 1299 of file pbx.c.
Referenced by ast_merge_contexts_and_delete(), and handle_statechange().
struct ast_context* contexts [static] |
Definition at line 1285 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 1286 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 1228 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
const char* const days[] [static] |
Definition at line 8285 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 1225 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 3646 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 3578 of file pbx.c.
Referenced by acf_exception_read(), and raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1221 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 865 of file pbx.c.
Referenced by ast_extension_state2().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
Definition at line 1218 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 1217 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 1314 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 870 of file pbx.c.
Referenced by ast_readconfig().
ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 1227 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
const char* const months[] [static] |
Definition at line 8297 of file pbx.c.
Referenced by ast_build_timing().
char* overrideswitch = NULL [static] |
Definition at line 1222 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 7665 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 10967 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 10023 of file pbx.c.
Referenced by pbx_builtin_resetcdr().
struct ao2_container* statecbs [static] |
Definition at line 1316 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 1305 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 864 of file pbx.c.
Referenced by pbx_find_extension().
struct ast_custom_function testtime_function [static] |
{ .name = "TESTTIME", .write = testtime_write, }
Definition at line 10114 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 870 of file pbx.c.
Referenced by ast_thread_inhibit_escalations(), and thread_inhibits_escalations().
int totalcalls [static] |
Definition at line 1229 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 857 of file pbx.c.
Referenced by pbx_builtin_waitexten().