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 | agimaskvars |
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 | setmaskvars |
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. | |
void | mask_string (char *str, int ini, int end, int findeq) |
static int | matchcid (const char *cidpattern, const char *callerid) |
static void | new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action) |
static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
extract offset:length from variable name. | |
static int | pbx_builtin_answer (struct ast_channel *, const char *) |
static int | pbx_builtin_background (struct ast_channel *, const char *) |
static int | pbx_builtin_busy (struct ast_channel *, const char *) |
void | pbx_builtin_clear_globals (void) |
static int | pbx_builtin_congestion (struct ast_channel *, const char *) |
static int | pbx_builtin_execiftime (struct ast_channel *, const char *) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
Return a pointer to the value of the corresponding channel variable. | |
static int | pbx_builtin_goto (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoif (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoiftime (struct ast_channel *, const char *) |
static int | pbx_builtin_hangup (struct ast_channel *, const char *) |
static int | pbx_builtin_importvar (struct ast_channel *, const char *) |
static int | pbx_builtin_incomplete (struct ast_channel *, const char *) |
static int | pbx_builtin_noop (struct ast_channel *, const char *) |
static int | pbx_builtin_proceeding (struct ast_channel *, const char *) |
static int | pbx_builtin_progress (struct ast_channel *, const char *) |
void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, without removing any previously set value. | |
int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason) |
static int | pbx_builtin_resetcdr (struct ast_channel *, const char *) |
static int | pbx_builtin_ringing (struct ast_channel *, const char *) |
static int | pbx_builtin_saycharacters (struct ast_channel *, const char *) |
static int | pbx_builtin_saydigits (struct ast_channel *, const char *) |
static int | pbx_builtin_saynumber (struct ast_channel *, const char *) |
static int | pbx_builtin_sayphonetic (struct ast_channel *, const char *) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
Create a human-readable string, specifying all variables and their corresponding values. | |
static int | pbx_builtin_setamaflags (struct ast_channel *, const char *) |
int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
static int | pbx_builtin_wait (struct ast_channel *, const char *) |
static int | pbx_builtin_waitexten (struct ast_channel *, const char *) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
static void | pbx_destroy (struct ast_pbx *p) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
Execute an application. | |
static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn) |
The return value depends on the action:. | |
struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
struct ast_app * | pbx_findapp (const char *app) |
Find application handle in linked list. | |
static struct ast_switch * | pbx_findswitch (const char *sw) |
void | pbx_live_dangerously (int new_live_dangerously) |
Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.). | |
static int | pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async) |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
Support for Asterisk built-in variables in the dialplan. | |
int | pbx_set_autofallthrough (int newval) |
int | pbx_set_extenpatternmatchnew (int newval) |
void | pbx_set_overrideswitch (const char *newval) |
static void | pbx_shutdown (void) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
static void * | pbx_thread (void *data) |
static void | print_app_docs (struct ast_app *aa, int fd) |
static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
helper function to print an extension | |
static int | raise_exception (struct ast_channel *chan, const char *reason, int priority) |
static int | read_escalates (const struct ast_custom_function *acf) |
Returns true if given custom function escalates privileges on read. | |
static void | set_ext_pri (struct ast_channel *c, const char *exten, int pri) |
static int | show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static int | show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static int | statecbs_cmp (void *obj, void *arg, int flags) |
static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
takes a substring. It is ok to call with value == workspace. | |
static int | testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value) |
static int | thread_inhibits_escalations (void) |
Indicates whether the current thread inhibits the execution of dangerous functions. | |
static struct ast_exten * | trie_find_next_match (struct match_char *node) |
static void | unload_pbx (void) |
static void | unreference_cached_app (struct ast_app *app) |
static void | update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node) |
static void | wait_for_hangup (struct ast_channel *chan, const void *data) |
static int | write_escalates (const struct ast_custom_function *acf) |
Returns true if given custom function escalates privileges on write. | |
Variables | |
static int | autofallthrough = 1 |
static struct ast_app_option | background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} |
static struct pbx_builtin | builtins [] |
Declaration of builtin applications. | |
static ast_mutex_t | conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Lock for the ast_context list. | |
static ast_mutex_t | context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete. | |
static struct ast_context * | contexts |
static struct ast_hashtab * | contexts_table = NULL |
static int | countcalls |
static const char *const | days [] |
static struct ast_event_sub * | device_state_sub |
Subscription for device state change events. | |
static struct ast_taskprocessor * | device_state_tps |
static struct ast_custom_function | exception_function |
static struct ast_datastore_info | exception_store_info |
static int | extenpatternmatchnew = 0 |
static struct cfextension_states | extension_states [] |
static struct ast_threadstorage | extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } |
static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
static ast_rwlock_t | globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } |
static struct ao2_container * | hints |
static struct ast_data_handler | hints_data_provider |
static int | live_dangerously |
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. | |
static ast_mutex_t | maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static const char *const | months [] |
static char * | overrideswitch = NULL |
static struct ast_cli_entry | pbx_cli [] |
static struct ast_data_entry | pbx_data_providers [] |
static struct ast_app_option | resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} |
static struct ao2_container * | statecbs |
static int | stateid = 1 |
static struct ast_threadstorage | switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } |
static struct ast_custom_function | testtime_function |
static struct ast_threadstorage | thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , } |
static int | totalcalls |
static struct ast_app_option | waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} |
Core PBX routines.
Definition in file pbx.c.
#define BACKGROUND_MATCHEXTEN (1 << 2) |
Definition at line 799 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_NOANSWER (1 << 1) |
Definition at line 798 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_PLAYBACK (1 << 3) |
Definition at line 800 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_SKIP (1 << 0) |
Definition at line 797 of file pbx.c.
Referenced by pbx_builtin_background().
#define BITS_PER 8 |
Referenced by ext_cmp_pattern_pos().
#define EXT_DATA_SIZE 8192 |
The speed of extension handling will likely be among the most important aspects of this PBX. The switching scheme as it exists right now isn't terribly bad (it's O(N+M), where N is the # of extensions and M is the avg # of priorities, but a constant search time here would be great ;-)
A new algorithm to do searching based on a 'compiled' pattern tree is introduced here, and shows a fairly flat (constant) search time, even for over 10000 patterns.
Also, using a hash table for context/priority name lookup can help prevent the find_extension routines from absorbing exponential cpu cycles as the number of contexts/priorities grow. I've previously tested find_extension with red-black trees, which have O(log2(n)) speed. Right now, I'm using hash tables, which do searches (ideally) in O(1) time. While these techniques do not yield much speed in small dialplans, they are worth the trouble in large dialplans.
Definition at line 786 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
#define HASH_EXTENHINT_SIZE 563 |
Definition at line 986 of file pbx.c.
Referenced by ast_pbx_init().
#define INC_DST_OVERFLOW_CHECK |
Referenced by get_pattern_node().
#define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
#define NEW_MATCHER_RECURSE |
Referenced by new_find_extension().
#define VAR_BUF_SIZE 4096 |
Definition at line 791 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_DIALTONE (1 << 1) |
Definition at line 810 of file pbx.c.
Referenced by pbx_builtin_waitexten().
#define WAITEXTEN_MOH (1 << 0) |
Definition at line 809 of file pbx.c.
Referenced by pbx_builtin_waitexten().
void __ast_context_destroy | ( | struct ast_context * | list, | |
struct ast_hashtab * | contexttab, | |||
struct ast_context * | con, | |||
const char * | registrar | |||
) |
Definition at line 9723 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().
09724 { 09725 struct ast_context *tmp, *tmpl=NULL; 09726 struct ast_exten *exten_item, *prio_item; 09727 09728 for (tmp = list; tmp; ) { 09729 struct ast_context *next = NULL; /* next starting point */ 09730 /* The following code used to skip forward to the next 09731 context with matching registrar, but this didn't 09732 make sense; individual priorities registrar'd to 09733 the matching registrar could occur in any context! */ 09734 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 09735 if (con) { 09736 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 09737 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 09738 if ( !strcasecmp(tmp->name, con->name) ) { 09739 break; /* found it */ 09740 } 09741 } 09742 } 09743 09744 if (!tmp) /* not found, we are done */ 09745 break; 09746 ast_wrlock_context(tmp); 09747 09748 if (registrar) { 09749 /* then search thru and remove any extens that match registrar. */ 09750 struct ast_hashtab_iter *exten_iter; 09751 struct ast_hashtab_iter *prio_iter; 09752 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 09753 struct ast_include *i, *pi = NULL, *ni = NULL; 09754 struct ast_sw *sw = NULL; 09755 09756 /* remove any ignorepats whose registrar matches */ 09757 for (ip = tmp->ignorepats; ip; ip = ipn) { 09758 ipn = ip->next; 09759 if (!strcmp(ip->registrar, registrar)) { 09760 if (ipl) { 09761 ipl->next = ip->next; 09762 ast_free(ip); 09763 continue; /* don't change ipl */ 09764 } else { 09765 tmp->ignorepats = ip->next; 09766 ast_free(ip); 09767 continue; /* don't change ipl */ 09768 } 09769 } 09770 ipl = ip; 09771 } 09772 /* remove any includes whose registrar matches */ 09773 for (i = tmp->includes; i; i = ni) { 09774 ni = i->next; 09775 if (strcmp(i->registrar, registrar) == 0) { 09776 /* remove from list */ 09777 if (pi) { 09778 pi->next = i->next; 09779 /* free include */ 09780 ast_free(i); 09781 continue; /* don't change pi */ 09782 } else { 09783 tmp->includes = i->next; 09784 /* free include */ 09785 ast_free(i); 09786 continue; /* don't change pi */ 09787 } 09788 } 09789 pi = i; 09790 } 09791 /* remove any switches whose registrar matches */ 09792 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 09793 if (strcmp(sw->registrar,registrar) == 0) { 09794 AST_LIST_REMOVE_CURRENT(list); 09795 ast_free(sw); 09796 } 09797 } 09798 AST_LIST_TRAVERSE_SAFE_END; 09799 09800 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 09801 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 09802 while ((exten_item=ast_hashtab_next(exten_iter))) { 09803 int end_traversal = 1; 09804 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 09805 while ((prio_item=ast_hashtab_next(prio_iter))) { 09806 char extension[AST_MAX_EXTENSION]; 09807 char cidmatch[AST_MAX_EXTENSION]; 09808 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 09809 continue; 09810 } 09811 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 09812 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 09813 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 09814 if (prio_item->cidmatch) { 09815 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 09816 } 09817 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1); 09818 } 09819 /* Explanation: 09820 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 09821 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 09822 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 09823 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 09824 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 09825 * free the iterator 09826 */ 09827 if (end_traversal) { 09828 ast_hashtab_end_traversal(prio_iter); 09829 } else { 09830 ast_free(prio_iter); 09831 } 09832 } 09833 ast_hashtab_end_traversal(exten_iter); 09834 } 09835 09836 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 09837 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 09838 another registrar. It's not empty if there are any extensions */ 09839 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 09840 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09841 ast_hashtab_remove_this_object(contexttab, tmp); 09842 09843 next = tmp->next; 09844 if (tmpl) 09845 tmpl->next = next; 09846 else 09847 contexts = next; 09848 /* Okay, now we're safe to let it go -- in a sense, we were 09849 ready to let it go as soon as we locked it. */ 09850 ast_unlock_context(tmp); 09851 __ast_internal_context_destroy(tmp); 09852 } else { 09853 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 09854 tmp->refcount, tmp->root); 09855 ast_unlock_context(tmp); 09856 next = tmp->next; 09857 tmpl = tmp; 09858 } 09859 } else if (con) { 09860 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 09861 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09862 ast_hashtab_remove_this_object(contexttab, tmp); 09863 09864 next = tmp->next; 09865 if (tmpl) 09866 tmpl->next = next; 09867 else 09868 contexts = next; 09869 /* Okay, now we're safe to let it go -- in a sense, we were 09870 ready to let it go as soon as we locked it. */ 09871 ast_unlock_context(tmp); 09872 __ast_internal_context_destroy(tmp); 09873 } 09874 09875 /* if we have a specific match, we are done, otherwise continue */ 09876 tmp = con ? NULL : next; 09877 } 09878 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3903 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by __ast_custom_function_register_escalating(), and load_pbx().
03904 { 03905 struct ast_custom_function *cur; 03906 char tmps[80]; 03907 03908 if (!acf) { 03909 return -1; 03910 } 03911 03912 acf->mod = mod; 03913 #ifdef AST_XML_DOCS 03914 acf->docsrc = AST_STATIC_DOC; 03915 #endif 03916 03917 if (acf_retrieve_docs(acf)) { 03918 return -1; 03919 } 03920 03921 AST_RWLIST_WRLOCK(&acf_root); 03922 03923 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03924 if (!strcmp(acf->name, cur->name)) { 03925 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03926 AST_RWLIST_UNLOCK(&acf_root); 03927 return -1; 03928 } 03929 } 03930 03931 /* Store in alphabetical order */ 03932 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03933 if (strcasecmp(acf->name, cur->name) < 0) { 03934 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03935 break; 03936 } 03937 } 03938 AST_RWLIST_TRAVERSE_SAFE_END; 03939 03940 if (!cur) { 03941 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03942 } 03943 03944 AST_RWLIST_UNLOCK(&acf_root); 03945 03946 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03947 03948 return 0; 03949 }
int __ast_custom_function_register_escalating | ( | struct ast_custom_function * | acf, | |
enum ast_custom_function_escalation | escalation, | |||
struct ast_module * | mod | |||
) |
Register a custom function which requires escalated privileges.
Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).
Definition at line 3951 of file pbx.c.
References __ast_custom_function_register(), ast_custom_escalating_function::acf, ast_calloc, AST_CFE_BOTH, AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, ast_custom_function_unregister(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_custom_escalating_function::read_escalates, and ast_custom_escalating_function::write_escalates.
03952 { 03953 struct ast_custom_escalating_function *acf_escalation = NULL; 03954 int res; 03955 03956 res = __ast_custom_function_register(acf, mod); 03957 if (res != 0) { 03958 return -1; 03959 } 03960 03961 if (escalation == AST_CFE_NONE) { 03962 /* No escalations; no need to do anything else */ 03963 return 0; 03964 } 03965 03966 acf_escalation = ast_calloc(1, sizeof(*acf_escalation)); 03967 if (!acf_escalation) { 03968 ast_custom_function_unregister(acf); 03969 return -1; 03970 } 03971 03972 acf_escalation->acf = acf; 03973 switch (escalation) { 03974 case AST_CFE_NONE: 03975 break; 03976 case AST_CFE_READ: 03977 acf_escalation->read_escalates = 1; 03978 break; 03979 case AST_CFE_WRITE: 03980 acf_escalation->write_escalates = 1; 03981 break; 03982 case AST_CFE_BOTH: 03983 acf_escalation->read_escalates = 1; 03984 acf_escalation->write_escalates = 1; 03985 break; 03986 } 03987 03988 AST_RWLIST_WRLOCK(&escalation_root); 03989 AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list); 03990 AST_RWLIST_UNLOCK(&escalation_root); 03991 03992 return 0; 03993 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 11150 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().
11151 { 11152 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 11153 11154 if (!chan) 11155 return -2; 11156 11157 if (context == NULL) 11158 context = chan->context; 11159 if (exten == NULL) 11160 exten = chan->exten; 11161 11162 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 11163 if (ast_exists_extension(chan, context, exten, priority, 11164 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 11165 return goto_func(chan, context, exten, priority); 11166 else { 11167 return AST_PBX_GOTO_FAILED; 11168 } 11169 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 9675 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().
09676 { 09677 struct ast_include *tmpi; 09678 struct ast_sw *sw; 09679 struct ast_exten *e, *el, *en; 09680 struct ast_ignorepat *ipi; 09681 struct ast_context *tmp = con; 09682 09683 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 09684 struct ast_include *tmpil = tmpi; 09685 tmpi = tmpi->next; 09686 ast_free(tmpil); 09687 } 09688 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 09689 struct ast_ignorepat *ipl = ipi; 09690 ipi = ipi->next; 09691 ast_free(ipl); 09692 } 09693 if (tmp->registrar) 09694 ast_free(tmp->registrar); 09695 09696 /* destroy the hash tabs */ 09697 if (tmp->root_table) { 09698 ast_hashtab_destroy(tmp->root_table, 0); 09699 } 09700 /* and destroy the pattern tree */ 09701 if (tmp->pattern_tree) 09702 destroy_pattern_tree(tmp->pattern_tree); 09703 09704 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 09705 ast_free(sw); 09706 for (e = tmp->root; e;) { 09707 for (en = e->peer; en;) { 09708 el = en; 09709 en = en->peer; 09710 destroy_exten(el); 09711 } 09712 el = e; 09713 e = e->next; 09714 destroy_exten(el); 09715 } 09716 tmp->root = NULL; 09717 ast_rwlock_destroy(&tmp->lock); 09718 ast_mutex_destroy(&tmp->macrolock); 09719 ast_free(tmp); 09720 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 5478 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().
05480 { 05481 int found = 0; /* set if we find at least one match */ 05482 int res = 0; 05483 int autoloopflag; 05484 int error = 0; /* set an error conditions */ 05485 05486 /* A little initial setup here */ 05487 if (c->pbx) { 05488 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 05489 /* XXX and now what ? */ 05490 ast_free(c->pbx); 05491 } 05492 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 05493 return -1; 05494 /* Set reasonable defaults */ 05495 c->pbx->rtimeoutms = 10000; 05496 c->pbx->dtimeoutms = 5000; 05497 05498 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 05499 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 05500 05501 /* Start by trying whatever the channel is set to */ 05502 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05503 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05504 /* If not successful fall back to 's' */ 05505 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); 05506 /* XXX the original code used the existing priority in the call to 05507 * ast_exists_extension(), and reset it to 1 afterwards. 05508 * I believe the correct thing is to set it to 1 immediately. 05509 */ 05510 set_ext_pri(c, "s", 1); 05511 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05512 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05513 /* JK02: And finally back to default if everything else failed */ 05514 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); 05515 ast_copy_string(c->context, "default", sizeof(c->context)); 05516 } 05517 } 05518 ast_channel_lock(c); 05519 if (c->cdr) { 05520 /* allow CDR variables that have been collected after channel was created to be visible during call */ 05521 ast_cdr_update(c); 05522 } 05523 ast_channel_unlock(c); 05524 for (;;) { 05525 char dst_exten[256]; /* buffer to accumulate digits */ 05526 int pos = 0; /* XXX should check bounds */ 05527 int digit = 0; 05528 int invalid = 0; 05529 int timeout = 0; 05530 05531 /* No digits pressed yet */ 05532 dst_exten[pos] = '\0'; 05533 05534 /* loop on priorities in this context/exten */ 05535 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05536 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05537 &found, 1))) { 05538 if (!ast_check_hangup(c)) { 05539 ++c->priority; 05540 continue; 05541 } 05542 05543 /* Check softhangup flags. */ 05544 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05545 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05546 continue; 05547 } 05548 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05549 if (ast_exists_extension(c, c->context, "T", 1, 05550 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05551 set_ext_pri(c, "T", 1); 05552 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05553 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05554 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05555 continue; 05556 } else if (ast_exists_extension(c, c->context, "e", 1, 05557 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05558 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05559 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05560 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05561 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05562 continue; 05563 } 05564 05565 /* Call timed out with no special extension to jump to. */ 05566 error = 1; 05567 break; 05568 } 05569 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 05570 c->exten, c->priority); 05571 error = 1; 05572 break; 05573 } /* end while - from here on we can use 'break' to go out */ 05574 if (found && res) { 05575 /* Something bad happened, or a hangup has been requested. */ 05576 if (strchr("0123456789ABCDEF*#", res)) { 05577 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 05578 pos = 0; 05579 dst_exten[pos++] = digit = res; 05580 dst_exten[pos] = '\0'; 05581 } else if (res == AST_PBX_INCOMPLETE) { 05582 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05583 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05584 05585 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 05586 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 05587 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05588 invalid = 1; 05589 } else { 05590 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 05591 digit = 1; 05592 pos = strlen(dst_exten); 05593 } 05594 } else { 05595 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05596 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05597 05598 if ((res == AST_PBX_ERROR) 05599 && ast_exists_extension(c, c->context, "e", 1, 05600 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05601 /* if we are already on the 'e' exten, don't jump to it again */ 05602 if (!strcmp(c->exten, "e")) { 05603 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); 05604 error = 1; 05605 } else { 05606 raise_exception(c, "ERROR", 1); 05607 continue; 05608 } 05609 } 05610 05611 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05612 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05613 continue; 05614 } 05615 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05616 if (ast_exists_extension(c, c->context, "T", 1, 05617 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05618 set_ext_pri(c, "T", 1); 05619 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05620 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05621 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05622 continue; 05623 } else if (ast_exists_extension(c, c->context, "e", 1, 05624 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05625 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05626 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05627 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05628 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05629 continue; 05630 } 05631 /* Call timed out with no special extension to jump to. */ 05632 } 05633 ast_channel_lock(c); 05634 if (c->cdr) { 05635 ast_cdr_update(c); 05636 } 05637 ast_channel_unlock(c); 05638 error = 1; 05639 break; 05640 } 05641 } 05642 if (error) 05643 break; 05644 05645 /*!\note 05646 * We get here on a failure of some kind: non-existing extension or 05647 * hangup. We have options, here. We can either catch the failure 05648 * and continue, or we can drop out entirely. */ 05649 05650 if (invalid 05651 || (ast_strlen_zero(dst_exten) && 05652 !ast_exists_extension(c, c->context, c->exten, 1, 05653 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) { 05654 /*!\note 05655 * If there is no match at priority 1, it is not a valid extension anymore. 05656 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 05657 * neither exist. 05658 */ 05659 if (ast_exists_extension(c, c->context, "i", 1, 05660 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05661 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 05662 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 05663 set_ext_pri(c, "i", 1); 05664 } else if (ast_exists_extension(c, c->context, "e", 1, 05665 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05666 raise_exception(c, "INVALID", 1); 05667 } else { 05668 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 05669 c->name, c->exten, c->context); 05670 error = 1; /* we know what to do with it */ 05671 break; 05672 } 05673 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05674 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 05675 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05676 } else { /* keypress received, get more digits for a full extension */ 05677 int waittime = 0; 05678 if (digit) 05679 waittime = c->pbx->dtimeoutms; 05680 else if (!autofallthrough) 05681 waittime = c->pbx->rtimeoutms; 05682 if (!waittime) { 05683 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 05684 if (!status) 05685 status = "UNKNOWN"; 05686 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 05687 if (!strcasecmp(status, "CONGESTION")) 05688 res = pbx_builtin_congestion(c, "10"); 05689 else if (!strcasecmp(status, "CHANUNAVAIL")) 05690 res = pbx_builtin_congestion(c, "10"); 05691 else if (!strcasecmp(status, "BUSY")) 05692 res = pbx_builtin_busy(c, "10"); 05693 error = 1; /* XXX disable message */ 05694 break; /* exit from the 'for' loop */ 05695 } 05696 05697 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 05698 break; 05699 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 05700 timeout = 1; 05701 if (!timeout 05702 && ast_exists_extension(c, c->context, dst_exten, 1, 05703 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 05704 set_ext_pri(c, dst_exten, 1); 05705 } else { 05706 /* No such extension */ 05707 if (!timeout && !ast_strlen_zero(dst_exten)) { 05708 /* An invalid extension */ 05709 if (ast_exists_extension(c, c->context, "i", 1, 05710 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05711 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 05712 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 05713 set_ext_pri(c, "i", 1); 05714 } else if (ast_exists_extension(c, c->context, "e", 1, 05715 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05716 raise_exception(c, "INVALID", 1); 05717 } else { 05718 ast_log(LOG_WARNING, 05719 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", 05720 dst_exten, c->context); 05721 found = 1; /* XXX disable message */ 05722 break; 05723 } 05724 } else { 05725 /* A simple timeout */ 05726 if (ast_exists_extension(c, c->context, "t", 1, 05727 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05728 ast_verb(3, "Timeout on %s\n", c->name); 05729 set_ext_pri(c, "t", 1); 05730 } else if (ast_exists_extension(c, c->context, "e", 1, 05731 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05732 raise_exception(c, "RESPONSETIMEOUT", 1); 05733 } else { 05734 ast_log(LOG_WARNING, 05735 "Timeout, but no rule 't' or 'e' in context '%s'\n", 05736 c->context); 05737 found = 1; /* XXX disable message */ 05738 break; 05739 } 05740 } 05741 } 05742 ast_channel_lock(c); 05743 if (c->cdr) { 05744 ast_verb(2, "CDR updated on %s\n",c->name); 05745 ast_cdr_update(c); 05746 } 05747 ast_channel_unlock(c); 05748 } 05749 } 05750 05751 if (!found && !error) { 05752 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 05753 } 05754 05755 if (!args || !args->no_hangup_chan) { 05756 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 05757 } 05758 05759 if ((!args || !args->no_hangup_chan) 05760 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 05761 && ast_exists_extension(c, c->context, "h", 1, 05762 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05763 set_ext_pri(c, "h", 1); 05764 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 05765 ast_cdr_end(c->cdr); 05766 } 05767 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05768 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05769 &found, 1)) == 0) { 05770 c->priority++; 05771 } 05772 if (found && res) { 05773 /* Something bad happened, or a hangup has been requested. */ 05774 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05775 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05776 } 05777 } 05778 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 05779 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 05780 pbx_destroy(c->pbx); 05781 c->pbx = NULL; 05782 05783 if (!args || !args->no_hangup_chan) { 05784 ast_hangup(c); 05785 } 05786 05787 return 0; 05788 }
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 2696 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().
02697 { 02698 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02699 02700 #ifdef NEED_DEBUG_HERE 02701 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02702 #endif 02703 02704 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02705 int lp = ext_cmp_exten_strlen(pattern); 02706 int ld = ext_cmp_exten_strlen(data); 02707 02708 if (lp < ld) { /* pattern too short, cannot match */ 02709 #ifdef NEED_DEBUG_HERE 02710 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02711 #endif 02712 return 0; 02713 } 02714 /* depending on the mode, accept full or partial match or both */ 02715 if (mode == E_MATCH) { 02716 #ifdef NEED_DEBUG_HERE 02717 ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data); 02718 #endif 02719 return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */ 02720 } 02721 if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */ 02722 #ifdef NEED_DEBUG_HERE 02723 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02724 #endif 02725 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02726 } else { 02727 #ifdef NEED_DEBUG_HERE 02728 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02729 #endif 02730 return 0; 02731 } 02732 } 02733 if (mode == E_MATCH && data[0] == '_') { 02734 /* 02735 * XXX It is bad design that we don't know if we should be 02736 * comparing data and pattern as patterns or comparing data if 02737 * it conforms to pattern when the function is called. First, 02738 * assume they are both patterns. If they don't match then try 02739 * to see if data conforms to the given pattern. 02740 * 02741 * note: if this test is left out, then _x. will not match _x. !!! 02742 */ 02743 #ifdef NEED_DEBUG_HERE 02744 ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data); 02745 #endif 02746 if (!ext_cmp_pattern(pattern + 1, data + 1)) { 02747 #ifdef NEED_DEBUG_HERE 02748 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02749 #endif 02750 return 1; 02751 } 02752 } 02753 02754 ++pattern; /* skip leading _ */ 02755 /* 02756 * XXX below we stop at '/' which is a separator for the CID info. However we should 02757 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02758 */ 02759 for (;;) { 02760 const char *end; 02761 02762 /* Ignore '-' chars as eye candy fluff. */ 02763 while (*data == '-') { 02764 ++data; 02765 } 02766 while (*pattern == '-') { 02767 ++pattern; 02768 } 02769 if (!*data || !*pattern || *pattern == '/') { 02770 break; 02771 } 02772 02773 switch (*pattern) { 02774 case '[': /* a range */ 02775 ++pattern; 02776 end = strchr(pattern, ']'); /* XXX should deal with escapes ? */ 02777 if (!end) { 02778 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02779 return 0; /* unconditional failure */ 02780 } 02781 if (pattern == end) { 02782 /* Ignore empty character sets. */ 02783 ++pattern; 02784 continue; 02785 } 02786 for (; pattern < end; ++pattern) { 02787 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02788 if (*data >= pattern[0] && *data <= pattern[2]) 02789 break; /* match found */ 02790 else { 02791 pattern += 2; /* skip a total of 3 chars */ 02792 continue; 02793 } 02794 } else if (*data == pattern[0]) 02795 break; /* match found */ 02796 } 02797 if (pattern >= end) { 02798 #ifdef NEED_DEBUG_HERE 02799 ast_log(LOG_NOTICE,"return (0) when pattern>=end\n"); 02800 #endif 02801 return 0; 02802 } 02803 pattern = end; /* skip and continue */ 02804 break; 02805 case 'n': 02806 case 'N': 02807 if (*data < '2' || *data > '9') { 02808 #ifdef NEED_DEBUG_HERE 02809 ast_log(LOG_NOTICE,"return (0) N is not matched\n"); 02810 #endif 02811 return 0; 02812 } 02813 break; 02814 case 'x': 02815 case 'X': 02816 if (*data < '0' || *data > '9') { 02817 #ifdef NEED_DEBUG_HERE 02818 ast_log(LOG_NOTICE,"return (0) X is not matched\n"); 02819 #endif 02820 return 0; 02821 } 02822 break; 02823 case 'z': 02824 case 'Z': 02825 if (*data < '1' || *data > '9') { 02826 #ifdef NEED_DEBUG_HERE 02827 ast_log(LOG_NOTICE,"return (0) Z is not matched\n"); 02828 #endif 02829 return 0; 02830 } 02831 break; 02832 case '.': /* Must match, even with more digits */ 02833 #ifdef NEED_DEBUG_HERE 02834 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02835 #endif 02836 return 1; 02837 case '!': /* Early match */ 02838 #ifdef NEED_DEBUG_HERE 02839 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02840 #endif 02841 return 2; 02842 default: 02843 if (*data != *pattern) { 02844 #ifdef NEED_DEBUG_HERE 02845 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02846 #endif 02847 return 0; 02848 } 02849 break; 02850 } 02851 ++data; 02852 ++pattern; 02853 } 02854 if (*data) /* data longer than pattern, no match */ { 02855 #ifdef NEED_DEBUG_HERE 02856 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02857 #endif 02858 return 0; 02859 } 02860 02861 /* 02862 * match so far, but ran off the end of data. 02863 * Depending on what is next, determine match or not. 02864 */ 02865 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02866 #ifdef NEED_DEBUG_HERE 02867 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02868 #endif 02869 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02870 } else if (*pattern == '!') { /* early match */ 02871 #ifdef NEED_DEBUG_HERE 02872 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02873 #endif 02874 return 2; 02875 } else { /* partial match */ 02876 #ifdef NEED_DEBUG_HERE 02877 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02878 #endif 02879 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02880 } 02881 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 3583 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.
03584 { 03585 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03586 struct pbx_exception *exception = NULL; 03587 if (!ds || !ds->data) 03588 return -1; 03589 exception = ds->data; 03590 if (!strcasecmp(data, "REASON")) 03591 ast_copy_string(buf, exception->reason, buflen); 03592 else if (!strcasecmp(data, "CONTEXT")) 03593 ast_copy_string(buf, exception->context, buflen); 03594 else if (!strncasecmp(data, "EXTEN", 5)) 03595 ast_copy_string(buf, exception->exten, buflen); 03596 else if (!strcasecmp(data, "PRIORITY")) 03597 snprintf(buf, buflen, "%d", exception->priority); 03598 else 03599 return -1; 03600 return 0; 03601 }
static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3858 of file pbx.c.
References ast_free, ast_module_name(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, and synopsis.
Referenced by __ast_custom_function_register().
03859 { 03860 #ifdef AST_XML_DOCS 03861 char *tmpxml; 03862 03863 /* Let's try to find it in the Documentation XML */ 03864 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03865 return 0; 03866 } 03867 03868 if (ast_string_field_init(acf, 128)) { 03869 return -1; 03870 } 03871 03872 /* load synopsis */ 03873 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); 03874 ast_string_field_set(acf, synopsis, tmpxml); 03875 ast_free(tmpxml); 03876 03877 /* load description */ 03878 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); 03879 ast_string_field_set(acf, desc, tmpxml); 03880 ast_free(tmpxml); 03881 03882 /* load syntax */ 03883 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod)); 03884 ast_string_field_set(acf, syntax, tmpxml); 03885 ast_free(tmpxml); 03886 03887 /* load arguments */ 03888 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod)); 03889 ast_string_field_set(acf, arguments, tmpxml); 03890 ast_free(tmpxml); 03891 03892 /* load seealso */ 03893 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod)); 03894 ast_string_field_set(acf, seealso, tmpxml); 03895 ast_free(tmpxml); 03896 03897 acf->docsrc = AST_XML_DOC; 03898 #endif 03899 03900 return 0; 03901 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static, read] |
Definition at line 2179 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().
02180 { 02181 struct match_char *m1 = NULL; 02182 struct match_char *m2 = NULL; 02183 struct match_char **m0; 02184 const char *pos; 02185 int already; 02186 int pattern = 0; 02187 int idx_cur; 02188 int idx_next; 02189 char extenbuf[512]; 02190 struct pattern_node pat_node[2]; 02191 02192 if (e1->matchcid) { 02193 if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) { 02194 ast_log(LOG_ERROR, 02195 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", 02196 e1->exten, e1->cidmatch); 02197 return NULL; 02198 } 02199 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */ 02200 } else { 02201 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 02202 } 02203 02204 #ifdef NEED_DEBUG 02205 ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf); 02206 #endif 02207 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 02208 m0 = &con->pattern_tree; 02209 already = 1; 02210 02211 pos = extenbuf; 02212 if (*pos == '_') { 02213 pattern = 1; 02214 ++pos; 02215 } 02216 idx_cur = 0; 02217 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf); 02218 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) { 02219 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node); 02220 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf); 02221 02222 /* See about adding node to tree. */ 02223 m2 = NULL; 02224 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern)) 02225 && m2->next_char) { 02226 if (!pat_node[idx_next].buf[0]) { 02227 /* 02228 * This is the end of the pattern, but not the end of the tree. 02229 * Mark this node with the exten... a shorter pattern might win 02230 * if the longer one doesn't match. 02231 */ 02232 if (findonly) { 02233 return m2; 02234 } 02235 if (m2->exten) { 02236 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02237 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02238 } 02239 m2->exten = e1; 02240 m2->deleted = 0; 02241 } 02242 m1 = m2->next_char; /* m1 points to the node to compare against */ 02243 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02244 } else { /* not already OR not m2 OR nor m2->next_char */ 02245 if (m2) { 02246 if (findonly) { 02247 return m2; 02248 } 02249 m1 = m2; /* while m0 stays the same */ 02250 } else { 02251 if (findonly) { 02252 return m1; 02253 } 02254 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0); 02255 if (!m1) { /* m1 is the node just added */ 02256 return NULL; 02257 } 02258 m0 = &m1->next_char; 02259 } 02260 if (!pat_node[idx_next].buf[0]) { 02261 if (m2 && m2->exten) { 02262 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02263 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02264 } 02265 m1->deleted = 0; 02266 m1->exten = e1; 02267 } 02268 02269 /* The 'already' variable is a mini-optimization designed to make it so that we 02270 * don't have to call already_in_tree when we know it will return false. 02271 */ 02272 already = 0; 02273 } 02274 } 02275 return m1; 02276 }
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 1981 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().
01982 { 01983 struct match_char *m; 01984 01985 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) { 01986 return NULL; 01987 } 01988 01989 /* strcpy is safe here since we know its size and have allocated 01990 * just enough space for when we allocated m 01991 */ 01992 strcpy(m->x, pattern->buf); 01993 01994 /* the specificity scores are the same as used in the old 01995 pattern matcher. */ 01996 m->is_pattern = is_pattern; 01997 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') { 01998 m->specificity = 0x0832; 01999 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') { 02000 m->specificity = 0x0931; 02001 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') { 02002 m->specificity = 0x0a30; 02003 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') { 02004 m->specificity = 0x18000; 02005 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') { 02006 m->specificity = 0x28000; 02007 } else { 02008 m->specificity = pattern->specif; 02009 } 02010 02011 if (!con->pattern_tree) { 02012 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 02013 } else { 02014 if (already) { /* switch to the new regime (traversing vs appending)*/ 02015 insert_in_next_chars_alt_char_list(nextcharptr, m); 02016 } else { 02017 insert_in_next_chars_alt_char_list(¤t->next_char, m); 02018 } 02019 } 02020 02021 return m; 02022 }
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 8861 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().
08863 { 08864 struct ast_exten *ep; 08865 struct ast_exten *eh=e; 08866 int repeated_label = 0; /* Track if this label is a repeat, assume no. */ 08867 08868 for (ep = NULL; e ; ep = e, e = e->peer) { 08869 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) { 08870 if (strcmp(e->exten, tmp->exten)) { 08871 ast_log(LOG_WARNING, 08872 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n", 08873 tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority); 08874 } else { 08875 ast_log(LOG_WARNING, 08876 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n", 08877 tmp->exten, tmp->priority, con->name, tmp->label, e->priority); 08878 } 08879 repeated_label = 1; 08880 } 08881 if (e->priority >= tmp->priority) { 08882 break; 08883 } 08884 } 08885 08886 if (repeated_label) { /* Discard the label since it's a repeat. */ 08887 tmp->label = NULL; 08888 } 08889 08890 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 08891 ast_hashtab_insert_safe(eh->peer_table, tmp); 08892 08893 if (tmp->label) { 08894 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08895 } 08896 ep->peer = tmp; 08897 return 0; /* success */ 08898 } 08899 if (e->priority == tmp->priority) { 08900 /* Can't have something exactly the same. Is this a 08901 replacement? If so, replace, otherwise, bonk. */ 08902 if (!replace) { 08903 if (strcmp(e->exten, tmp->exten)) { 08904 ast_log(LOG_WARNING, 08905 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n", 08906 tmp->exten, tmp->priority, con->name, e->exten); 08907 } else { 08908 ast_log(LOG_WARNING, 08909 "Unable to register extension '%s' priority %d in '%s', already in use\n", 08910 tmp->exten, tmp->priority, con->name); 08911 } 08912 if (tmp->datad) { 08913 tmp->datad(tmp->data); 08914 /* if you free this, null it out */ 08915 tmp->data = NULL; 08916 } 08917 08918 ast_free(tmp); 08919 return -1; 08920 } 08921 /* we are replacing e, so copy the link fields and then update 08922 * whoever pointed to e to point to us 08923 */ 08924 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 08925 tmp->peer = e->peer; /* always meaningful */ 08926 if (ep) { /* We're in the peer list, just insert ourselves */ 08927 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 08928 08929 if (e->label) { 08930 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 08931 } 08932 08933 ast_hashtab_insert_safe(eh->peer_table,tmp); 08934 if (tmp->label) { 08935 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 08936 } 08937 08938 ep->peer = tmp; 08939 } else if (el) { /* We're the first extension. Take over e's functions */ 08940 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08941 tmp->peer_table = e->peer_table; 08942 tmp->peer_label_table = e->peer_label_table; 08943 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 08944 ast_hashtab_insert_safe(tmp->peer_table,tmp); 08945 if (e->label) { 08946 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08947 } 08948 if (tmp->label) { 08949 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08950 } 08951 08952 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08953 ast_hashtab_insert_safe(con->root_table, tmp); 08954 el->next = tmp; 08955 /* The pattern trie points to this exten; replace the pointer, 08956 and all will be well */ 08957 if (x) { /* if the trie isn't formed yet, don't sweat this */ 08958 if (x->exten) { /* this test for safety purposes */ 08959 x->exten = tmp; /* replace what would become a bad pointer */ 08960 } else { 08961 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08962 } 08963 } 08964 } else { /* We're the very first extension. */ 08965 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08966 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08967 ast_hashtab_insert_safe(con->root_table, tmp); 08968 tmp->peer_table = e->peer_table; 08969 tmp->peer_label_table = e->peer_label_table; 08970 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 08971 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08972 if (e->label) { 08973 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08974 } 08975 if (tmp->label) { 08976 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08977 } 08978 08979 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08980 ast_hashtab_insert_safe(con->root_table, tmp); 08981 con->root = tmp; 08982 /* The pattern trie points to this exten; replace the pointer, 08983 and all will be well */ 08984 if (x) { /* if the trie isn't formed yet; no problem */ 08985 if (x->exten) { /* this test for safety purposes */ 08986 x->exten = tmp; /* replace what would become a bad pointer */ 08987 } else { 08988 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08989 } 08990 } 08991 } 08992 if (tmp->priority == PRIORITY_HINT) 08993 ast_change_hint(e,tmp); 08994 /* Destroy the old one */ 08995 if (e->datad) 08996 e->datad(e->data); 08997 ast_free(e); 08998 } else { /* Slip ourselves in just before e */ 08999 tmp->peer = e; 09000 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 09001 if (ep) { /* Easy enough, we're just in the peer list */ 09002 if (tmp->label) { 09003 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 09004 } 09005 ast_hashtab_insert_safe(eh->peer_table, tmp); 09006 ep->peer = tmp; 09007 } else { /* we are the first in some peer list, so link in the ext list */ 09008 tmp->peer_table = e->peer_table; 09009 tmp->peer_label_table = e->peer_label_table; 09010 e->peer_table = 0; 09011 e->peer_label_table = 0; 09012 ast_hashtab_insert_safe(tmp->peer_table, tmp); 09013 if (tmp->label) { 09014 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 09015 } 09016 ast_hashtab_remove_object_via_lookup(con->root_table, e); 09017 ast_hashtab_insert_safe(con->root_table, tmp); 09018 if (el) 09019 el->next = tmp; /* in the middle... */ 09020 else 09021 con->root = tmp; /* ... or at the head */ 09022 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 09023 } 09024 /* And immediately return success. */ 09025 if (tmp->priority == PRIORITY_HINT) { 09026 ast_add_hint(tmp); 09027 } 09028 } 09029 return 0; 09030 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat, | |||
int | is_pattern | |||
) | [static, read] |
Definition at line 1919 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01920 { 01921 struct match_char *t; 01922 01923 if (!current) { 01924 return 0; 01925 } 01926 01927 for (t = current; t; t = t->alt_char) { 01928 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01929 return t; 01930 } 01931 } 01932 01933 return 0; 01934 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5936 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05937 { 05938 return countcalls; 05939 }
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 8696 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().
08699 { 08700 int ret = -1; 08701 struct ast_context *c; 08702 08703 c = find_context_locked(context); 08704 if (c) { 08705 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08706 application, data, datad, registrar); 08707 ast_unlock_contexts(); 08708 } 08709 08710 return ret; 08711 }
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 9057 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().
09061 { 09062 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 09063 application, data, datad, registrar, 1); 09064 }
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 9073 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().
09077 { 09078 /* 09079 * Sort extensions (or patterns) according to the rules indicated above. 09080 * These are implemented by the function ext_cmp()). 09081 * All priorities for the same ext/pattern/cid are kept in a list, 09082 * using the 'peer' field as a link field.. 09083 */ 09084 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 09085 int res; 09086 int length; 09087 char *p; 09088 char expand_buf[VAR_BUF_SIZE]; 09089 struct ast_exten dummy_exten = {0}; 09090 char dummy_name[1024]; 09091 09092 if (ast_strlen_zero(extension)) { 09093 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", 09094 con->name); 09095 return -1; 09096 } 09097 09098 /* If we are adding a hint evalulate in variables and global variables */ 09099 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') { 09100 struct ast_channel *c = ast_dummy_channel_alloc(); 09101 09102 if (c) { 09103 ast_copy_string(c->exten, extension, sizeof(c->exten)); 09104 ast_copy_string(c->context, con->name, sizeof(c->context)); 09105 } 09106 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 09107 application = expand_buf; 09108 if (c) { 09109 ast_channel_unref(c); 09110 } 09111 } 09112 09113 length = sizeof(struct ast_exten); 09114 length += strlen(extension) + 1; 09115 length += strlen(application) + 1; 09116 if (label) 09117 length += strlen(label) + 1; 09118 if (callerid) 09119 length += strlen(callerid) + 1; 09120 else 09121 length ++; /* just the '\0' */ 09122 09123 /* Be optimistic: Build the extension structure first */ 09124 if (!(tmp = ast_calloc(1, length))) 09125 return -1; 09126 09127 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 09128 label = 0; 09129 09130 /* use p as dst in assignments, as the fields are const char * */ 09131 p = tmp->stuff; 09132 if (label) { 09133 tmp->label = p; 09134 strcpy(p, label); 09135 p += strlen(label) + 1; 09136 } 09137 tmp->exten = p; 09138 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 09139 tmp->priority = priority; 09140 tmp->cidmatch = p; /* but use p for assignments below */ 09141 09142 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 09143 if (callerid) { 09144 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 09145 tmp->matchcid = AST_EXT_MATCHCID_ON; 09146 } else { 09147 *p++ = '\0'; 09148 tmp->matchcid = AST_EXT_MATCHCID_OFF; 09149 } 09150 tmp->app = p; 09151 strcpy(p, application); 09152 tmp->parent = con; 09153 tmp->data = data; 09154 tmp->datad = datad; 09155 tmp->registrar = registrar; 09156 09157 if (lock_context) { 09158 ast_wrlock_context(con); 09159 } 09160 09161 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 09162 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 09163 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 09164 dummy_exten.exten = dummy_name; 09165 dummy_exten.matchcid = AST_EXT_MATCHCID_OFF; 09166 dummy_exten.cidmatch = 0; 09167 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 09168 if (!tmp2) { 09169 /* hmmm, not in the trie; */ 09170 add_exten_to_pattern_tree(con, tmp, 0); 09171 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 09172 } 09173 } 09174 res = 0; /* some compilers will think it is uninitialized otherwise */ 09175 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 09176 res = ext_cmp(e->exten, tmp->exten); 09177 if (res == 0) { /* extension match, now look at cidmatch */ 09178 if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF) 09179 res = 0; 09180 else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF) 09181 res = 1; 09182 else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF) 09183 res = -1; 09184 else 09185 res = ext_cmp(e->cidmatch, tmp->cidmatch); 09186 } 09187 if (res >= 0) 09188 break; 09189 } 09190 if (e && res == 0) { /* exact match, insert in the priority chain */ 09191 res = add_priority(con, tmp, el, e, replace); 09192 if (lock_context) { 09193 ast_unlock_context(con); 09194 } 09195 if (res < 0) { 09196 errno = EEXIST; /* XXX do we care ? */ 09197 return 0; /* XXX should we return -1 maybe ? */ 09198 } 09199 } else { 09200 /* 09201 * not an exact match, this is the first entry with this pattern, 09202 * so insert in the main list right before 'e' (if any) 09203 */ 09204 tmp->next = e; 09205 if (el) { /* there is another exten already in this context */ 09206 el->next = tmp; 09207 tmp->peer_table = ast_hashtab_create(13, 09208 hashtab_compare_exten_numbers, 09209 ast_hashtab_resize_java, 09210 ast_hashtab_newsize_java, 09211 hashtab_hash_priority, 09212 0); 09213 tmp->peer_label_table = ast_hashtab_create(7, 09214 hashtab_compare_exten_labels, 09215 ast_hashtab_resize_java, 09216 ast_hashtab_newsize_java, 09217 hashtab_hash_labels, 09218 0); 09219 if (label) { 09220 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 09221 } 09222 ast_hashtab_insert_safe(tmp->peer_table, tmp); 09223 } else { /* this is the first exten in this context */ 09224 if (!con->root_table) 09225 con->root_table = ast_hashtab_create(27, 09226 hashtab_compare_extens, 09227 ast_hashtab_resize_java, 09228 ast_hashtab_newsize_java, 09229 hashtab_hash_extens, 09230 0); 09231 con->root = tmp; 09232 con->root->peer_table = ast_hashtab_create(13, 09233 hashtab_compare_exten_numbers, 09234 ast_hashtab_resize_java, 09235 ast_hashtab_newsize_java, 09236 hashtab_hash_priority, 09237 0); 09238 con->root->peer_label_table = ast_hashtab_create(7, 09239 hashtab_compare_exten_labels, 09240 ast_hashtab_resize_java, 09241 ast_hashtab_newsize_java, 09242 hashtab_hash_labels, 09243 0); 09244 if (label) { 09245 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 09246 } 09247 ast_hashtab_insert_safe(con->root->peer_table, tmp); 09248 09249 } 09250 ast_hashtab_insert_safe(con->root_table, tmp); 09251 if (lock_context) { 09252 ast_unlock_context(con); 09253 } 09254 if (tmp->priority == PRIORITY_HINT) { 09255 ast_add_hint(tmp); 09256 } 09257 } 09258 if (option_debug) { 09259 if (tmp->matchcid == AST_EXT_MATCHCID_ON) { 09260 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 09261 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 09262 } else { 09263 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 09264 tmp->exten, tmp->priority, con->name, con); 09265 } 09266 } 09267 09268 if (tmp->matchcid == AST_EXT_MATCHCID_ON) { 09269 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 09270 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 09271 } else { 09272 ast_verb(3, "Added extension '%s' priority %d to %s\n", 09273 tmp->exten, tmp->priority, con->name); 09274 } 09275 09276 return 0; 09277 }
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 8676 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
08679 { 08680 int ret = -1; 08681 struct ast_context *c; 08682 08683 c = find_context(context); 08684 if (c) { 08685 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 08686 application, data, datad, registrar, 1); 08687 } 08688 08689 return ret; 08690 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 5275 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().
05276 { 05277 struct ast_hint *hint_new; 05278 struct ast_hint *hint_found; 05279 05280 if (!e) { 05281 return -1; 05282 } 05283 05284 /* 05285 * We must create the hint we wish to add before determining if 05286 * it is already in the hints container to avoid possible 05287 * deadlock when getting the current extension state. 05288 */ 05289 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint); 05290 if (!hint_new) { 05291 return -1; 05292 } 05293 05294 /* Initialize new hint. */ 05295 hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); 05296 if (!hint_new->callbacks) { 05297 ao2_ref(hint_new, -1); 05298 return -1; 05299 } 05300 hint_new->exten = e; 05301 if (strstr(e->app, "${") && e->exten[0] == '_') { 05302 hint_new->laststate = AST_DEVICE_INVALID; 05303 } else { 05304 hint_new->laststate = ast_extension_state2(e); 05305 } 05306 05307 /* Prevent multiple add hints from adding the same hint at the same time. */ 05308 ao2_lock(hints); 05309 05310 /* Search if hint exists, do nothing */ 05311 hint_found = ao2_find(hints, e, 0); 05312 if (hint_found) { 05313 ao2_ref(hint_found, -1); 05314 ao2_unlock(hints); 05315 ao2_ref(hint_new, -1); 05316 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", 05317 ast_get_extension_name(e), ast_get_extension_app(e)); 05318 return -1; 05319 } 05320 05321 /* Add new hint to the hints container */ 05322 ast_debug(2, "HINTS: Adding hint %s: %s\n", 05323 ast_get_extension_name(e), ast_get_extension_app(e)); 05324 ao2_link(hints, hint_new); 05325 05326 ao2_unlock(hints); 05327 ao2_ref(hint_new, -1); 05328 05329 return 0; 05330 }
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 8736 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().
08737 { 08738 int res = 0; 08739 struct ast_channel *tmpchan; 08740 struct { 08741 char *accountcode; 08742 char *exten; 08743 char *context; 08744 char *linkedid; 08745 char *name; 08746 struct ast_cdr *cdr; 08747 int amaflags; 08748 int state; 08749 format_t readformat; 08750 format_t writeformat; 08751 } tmpvars = { 0, }; 08752 08753 ast_channel_lock(chan); 08754 if (chan->pbx) { /* This channel is currently in the PBX */ 08755 ast_explicit_goto(chan, context, exten, priority + 1); 08756 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08757 ast_channel_unlock(chan); 08758 return res; 08759 } 08760 08761 /* In order to do it when the channel doesn't really exist within 08762 * the PBX, we have to make a new channel, masquerade, and start the PBX 08763 * at the new location */ 08764 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08765 tmpvars.exten = ast_strdupa(chan->exten); 08766 tmpvars.context = ast_strdupa(chan->context); 08767 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08768 tmpvars.name = ast_strdupa(chan->name); 08769 tmpvars.amaflags = chan->amaflags; 08770 tmpvars.state = chan->_state; 08771 tmpvars.writeformat = chan->writeformat; 08772 tmpvars.readformat = chan->readformat; 08773 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08774 08775 ast_channel_unlock(chan); 08776 08777 /* Do not hold any channel locks while calling channel_alloc() since the function 08778 * locks the channel container when linking the new channel in. */ 08779 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08780 ast_cdr_discard(tmpvars.cdr); 08781 return -1; 08782 } 08783 08784 /* copy the cdr info over */ 08785 if (tmpvars.cdr) { 08786 ast_cdr_discard(tmpchan->cdr); 08787 tmpchan->cdr = tmpvars.cdr; 08788 tmpvars.cdr = NULL; 08789 } 08790 08791 /* Make formats okay */ 08792 tmpchan->readformat = tmpvars.readformat; 08793 tmpchan->writeformat = tmpvars.writeformat; 08794 08795 /* Setup proper location. Never hold another channel lock while calling this function. */ 08796 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08797 08798 /* Masquerade into tmp channel */ 08799 if (ast_channel_masquerade(tmpchan, chan)) { 08800 /* Failed to set up the masquerade. It's probably chan_local 08801 * in the middle of optimizing itself out. Sad. :( */ 08802 ast_hangup(tmpchan); 08803 tmpchan = NULL; 08804 res = -1; 08805 } else { 08806 ast_do_masquerade(tmpchan); 08807 /* Start the PBX going on our stolen channel */ 08808 if (ast_pbx_start(tmpchan)) { 08809 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08810 ast_hangup(tmpchan); 08811 res = -1; 08812 } 08813 } 08814 08815 return res; 08816 }
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 8818 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08819 { 08820 struct ast_channel *chan; 08821 int res = -1; 08822 08823 if ((chan = ast_channel_get_by_name(channame))) { 08824 res = ast_async_goto(chan, context, exten, priority); 08825 chan = ast_channel_unref(chan); 08826 } 08827 08828 return res; 08829 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11176 of file pbx.c.
References __ast_goto_if_exists().
11177 { 11178 return __ast_goto_if_exists(chan, context, exten, priority, 1); 11179 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11241 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
11242 { 11243 return pbx_parseable_goto(chan, goto_string, 1); 11244 }
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 8319 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().
08320 { 08321 char *info; 08322 int j, num_fields, last_sep = -1; 08323 08324 i->timezone = NULL; 08325 08326 /* Check for empty just in case */ 08327 if (ast_strlen_zero(info_in)) { 08328 return 0; 08329 } 08330 08331 /* make a copy just in case we were passed a static string */ 08332 info = ast_strdupa(info_in); 08333 08334 /* count the number of fields in the timespec */ 08335 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08336 if (info[j] == ',') { 08337 last_sep = j; 08338 num_fields++; 08339 } 08340 } 08341 08342 /* save the timezone, if it is specified */ 08343 if (num_fields == 5) { 08344 i->timezone = ast_strdup(info + last_sep + 1); 08345 } 08346 08347 /* Assume everything except time */ 08348 i->monthmask = 0xfff; /* 12 bits */ 08349 i->daymask = 0x7fffffffU; /* 31 bits */ 08350 i->dowmask = 0x7f; /* 7 bits */ 08351 /* on each call, use strsep() to move info to the next argument */ 08352 get_timerange(i, strsep(&info, "|,")); 08353 if (info) 08354 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08355 if (info) 08356 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08357 if (info) 08358 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08359 return 1; 08360 }
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 5420 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().
05421 { 05422 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05423 }
Change hint for an extension.
Definition at line 5333 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().
05334 { 05335 struct ast_hint *hint; 05336 05337 if (!oe || !ne) { 05338 return -1; 05339 } 05340 05341 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */ 05342 05343 /* 05344 * Unlink the hint from the hints container as the extension 05345 * name (which is the hash value) could change. 05346 */ 05347 hint = ao2_find(hints, oe, OBJ_UNLINK); 05348 if (!hint) { 05349 ao2_unlock(hints); 05350 return -1; 05351 } 05352 05353 /* Update the hint and put it back in the hints container. */ 05354 ao2_lock(hint); 05355 hint->exten = ne; 05356 ao2_unlock(hint); 05357 ao2_link(hints, hint); 05358 05359 ao2_unlock(hints); 05360 ao2_ref(hint, -1); 05361 05362 return 0; 05363 }
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 8362 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08363 { 08364 return ast_check_timing2(i, ast_tvnow()); 08365 }
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 8367 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().
08368 { 08369 struct ast_tm tm; 08370 08371 ast_localtime(&tv, &tm, i->timezone); 08372 08373 /* If it's not the right month, return */ 08374 if (!(i->monthmask & (1 << tm.tm_mon))) 08375 return 0; 08376 08377 /* If it's not that time of the month.... */ 08378 /* Warning, tm_mday has range 1..31! */ 08379 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08380 return 0; 08381 08382 /* If it's not the right day of the week */ 08383 if (!(i->dowmask & (1 << tm.tm_wday))) 08384 return 0; 08385 08386 /* Sanity check the hour just to be safe */ 08387 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08388 ast_log(LOG_WARNING, "Insane time...\n"); 08389 return 0; 08390 } 08391 08392 /* Now the tough part, we calculate if it fits 08393 in the right time based on min/hour */ 08394 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)))) 08395 return 0; 08396 08397 /* If we got this far, then we're good */ 08398 return 1; 08399 }
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 11246 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().
11247 { 11248 struct ast_app *app = NULL; 11249 int which = 0; 11250 char *ret = NULL; 11251 size_t wordlen = strlen(word); 11252 11253 AST_RWLIST_RDLOCK(&apps); 11254 AST_RWLIST_TRAVERSE(&apps, app, list) { 11255 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 11256 ret = ast_strdup(app->name); 11257 break; 11258 } 11259 } 11260 AST_RWLIST_UNLOCK(&apps); 11261 11262 return ret; 11263 }
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 8603 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08604 { 08605 int ret = -1; 08606 struct ast_context *c; 08607 08608 c = find_context_locked(context); 08609 if (c) { 08610 ret = ast_context_add_ignorepat2(c, value, registrar); 08611 ast_unlock_contexts(); 08612 } 08613 return ret; 08614 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 8616 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().
08617 { 08618 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08619 int length; 08620 char *pattern; 08621 length = sizeof(struct ast_ignorepat); 08622 length += strlen(value) + 1; 08623 if (!(ignorepat = ast_calloc(1, length))) 08624 return -1; 08625 /* The cast to char * is because we need to write the initial value. 08626 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08627 * sees the cast as dereferencing a type-punned pointer and warns about 08628 * it. This is the workaround (we're telling gcc, yes, that's really 08629 * what we wanted to do). 08630 */ 08631 pattern = (char *) ignorepat->pattern; 08632 strcpy(pattern, value); 08633 ignorepat->next = NULL; 08634 ignorepat->registrar = registrar; 08635 ast_wrlock_context(con); 08636 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08637 ignorepatl = ignorepatc; 08638 if (!strcasecmp(ignorepatc->pattern, value)) { 08639 /* Already there */ 08640 ast_unlock_context(con); 08641 ast_free(ignorepat); 08642 errno = EEXIST; 08643 return -1; 08644 } 08645 } 08646 if (ignorepatl) 08647 ignorepatl->next = ignorepat; 08648 else 08649 con->ignorepats = ignorepat; 08650 ast_unlock_context(con); 08651 return 0; 08652 08653 }
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 8147 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
08148 { 08149 int ret = -1; 08150 struct ast_context *c; 08151 08152 c = find_context_locked(context); 08153 if (c) { 08154 ret = ast_context_add_include2(c, include, registrar); 08155 ast_unlock_contexts(); 08156 } 08157 return ret; 08158 }
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 8416 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().
08418 { 08419 struct ast_include *new_include; 08420 char *c; 08421 struct ast_include *i, *il = NULL; /* include, include_last */ 08422 int length; 08423 char *p; 08424 08425 length = sizeof(struct ast_include); 08426 length += 2 * (strlen(value) + 1); 08427 08428 /* allocate new include structure ... */ 08429 if (!(new_include = ast_calloc(1, length))) 08430 return -1; 08431 /* Fill in this structure. Use 'p' for assignments, as the fields 08432 * in the structure are 'const char *' 08433 */ 08434 p = new_include->stuff; 08435 new_include->name = p; 08436 strcpy(p, value); 08437 p += strlen(value) + 1; 08438 new_include->rname = p; 08439 strcpy(p, value); 08440 /* Strip off timing info, and process if it is there */ 08441 if ( (c = strchr(p, ',')) ) { 08442 *c++ = '\0'; 08443 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08444 } 08445 new_include->next = NULL; 08446 new_include->registrar = registrar; 08447 08448 ast_wrlock_context(con); 08449 08450 /* ... go to last include and check if context is already included too... */ 08451 for (i = con->includes; i; i = i->next) { 08452 if (!strcasecmp(i->name, new_include->name)) { 08453 ast_destroy_timing(&(new_include->timing)); 08454 ast_free(new_include); 08455 ast_unlock_context(con); 08456 errno = EEXIST; 08457 return -1; 08458 } 08459 il = i; 08460 } 08461 08462 /* ... include new context into context list, unlock, return */ 08463 if (il) 08464 il->next = new_include; 08465 else 08466 con->includes = new_include; 08467 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08468 08469 ast_unlock_context(con); 08470 08471 return 0; 08472 }
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 8479 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08480 { 08481 int ret = -1; 08482 struct ast_context *c; 08483 08484 c = find_context_locked(context); 08485 if (c) { /* found, add switch to this context */ 08486 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08487 ast_unlock_contexts(); 08488 } 08489 return ret; 08490 }
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 8499 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().
08501 { 08502 struct ast_sw *new_sw; 08503 struct ast_sw *i; 08504 int length; 08505 char *p; 08506 08507 length = sizeof(struct ast_sw); 08508 length += strlen(value) + 1; 08509 if (data) 08510 length += strlen(data); 08511 length++; 08512 08513 /* allocate new sw structure ... */ 08514 if (!(new_sw = ast_calloc(1, length))) 08515 return -1; 08516 /* ... fill in this structure ... */ 08517 p = new_sw->stuff; 08518 new_sw->name = p; 08519 strcpy(new_sw->name, value); 08520 p += strlen(value) + 1; 08521 new_sw->data = p; 08522 if (data) { 08523 strcpy(new_sw->data, data); 08524 p += strlen(data) + 1; 08525 } else { 08526 strcpy(new_sw->data, ""); 08527 p++; 08528 } 08529 new_sw->eval = eval; 08530 new_sw->registrar = registrar; 08531 08532 /* ... try to lock this context ... */ 08533 ast_wrlock_context(con); 08534 08535 /* ... go to last sw and check if context is already swd too... */ 08536 AST_LIST_TRAVERSE(&con->alts, i, list) { 08537 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08538 ast_free(new_sw); 08539 ast_unlock_context(con); 08540 errno = EEXIST; 08541 return -1; 08542 } 08543 } 08544 08545 /* ... sw new context into context list, unlock, return */ 08546 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08547 08548 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08549 08550 ast_unlock_context(con); 08551 08552 return 0; 08553 }
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 9880 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().
09881 { 09882 ast_wrlock_contexts(); 09883 __ast_context_destroy(contexts, contexts_table, con,registrar); 09884 ast_unlock_contexts(); 09885 }
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 2928 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().
02929 { 02930 struct ast_context *tmp; 02931 struct fake_context item; 02932 02933 if (!name) { 02934 return NULL; 02935 } 02936 ast_rdlock_contexts(); 02937 if (contexts_table) { 02938 ast_copy_string(item.name, name, sizeof(item.name)); 02939 tmp = ast_hashtab_lookup(contexts_table, &item); 02940 } else { 02941 tmp = NULL; 02942 while ((tmp = ast_walk_contexts(tmp))) { 02943 if (!strcasecmp(name, tmp->name)) { 02944 break; 02945 } 02946 } 02947 } 02948 ast_unlock_contexts(); 02949 return tmp; 02950 }
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 7731 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().
07732 { 07733 struct ast_context *tmp, **local_contexts; 07734 struct fake_context search; 07735 int length = sizeof(struct ast_context) + strlen(name) + 1; 07736 07737 if (!contexts_table) { 07738 /* Protect creation of contexts_table from reentrancy. */ 07739 ast_wrlock_contexts(); 07740 if (!contexts_table) { 07741 contexts_table = ast_hashtab_create(17, 07742 ast_hashtab_compare_contexts, 07743 ast_hashtab_resize_java, 07744 ast_hashtab_newsize_java, 07745 ast_hashtab_hash_contexts, 07746 0); 07747 } 07748 ast_unlock_contexts(); 07749 } 07750 07751 ast_copy_string(search.name, name, sizeof(search.name)); 07752 if (!extcontexts) { 07753 ast_rdlock_contexts(); 07754 local_contexts = &contexts; 07755 tmp = ast_hashtab_lookup(contexts_table, &search); 07756 ast_unlock_contexts(); 07757 if (tmp) { 07758 tmp->refcount++; 07759 return tmp; 07760 } 07761 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07762 local_contexts = extcontexts; 07763 tmp = ast_hashtab_lookup(exttable, &search); 07764 if (tmp) { 07765 tmp->refcount++; 07766 return tmp; 07767 } 07768 } 07769 07770 if ((tmp = ast_calloc(1, length))) { 07771 ast_rwlock_init(&tmp->lock); 07772 ast_mutex_init(&tmp->macrolock); 07773 strcpy(tmp->name, name); 07774 tmp->root = NULL; 07775 tmp->root_table = NULL; 07776 tmp->registrar = ast_strdup(registrar); 07777 tmp->includes = NULL; 07778 tmp->ignorepats = NULL; 07779 tmp->refcount = 1; 07780 } else { 07781 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07782 return NULL; 07783 } 07784 07785 if (!extcontexts) { 07786 ast_wrlock_contexts(); 07787 tmp->next = *local_contexts; 07788 *local_contexts = tmp; 07789 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07790 ast_unlock_contexts(); 07791 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07792 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07793 } else { 07794 tmp->next = *local_contexts; 07795 if (exttable) 07796 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07797 07798 *local_contexts = tmp; 07799 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07800 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07801 } 07802 return tmp; 07803 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 6311 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06312 { 06313 struct ast_context *c; 06314 int ret = -1; 06315 06316 c = find_context_locked(context); 06317 if (c) { 06318 ast_unlock_contexts(); 06319 06320 /* if we found context, lock macrolock */ 06321 ret = ast_mutex_lock(&c->macrolock); 06322 } 06323 06324 return ret; 06325 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
Definition at line 6119 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().
06120 { 06121 return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar); 06122 }
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 6149 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().
06150 { 06151 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked); 06152 }
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 6124 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().
06125 { 06126 int ret = -1; /* default error return */ 06127 struct ast_context *c; 06128 06129 c = find_context_locked(context); 06130 if (c) { /* ... remove extension ... */ 06131 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 06132 matchcallerid, registrar, 0); 06133 ast_unlock_contexts(); 06134 } 06135 06136 return ret; 06137 }
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 6154 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().
06155 { 06156 struct ast_exten *exten, *prev_exten = NULL; 06157 struct ast_exten *peer; 06158 struct ast_exten ex, *exten2, *exten3; 06159 char dummy_name[1024]; 06160 struct ast_exten *previous_peer = NULL; 06161 struct ast_exten *next_peer = NULL; 06162 int found = 0; 06163 06164 if (!already_locked) 06165 ast_wrlock_context(con); 06166 06167 #ifdef NEED_DEBUG 06168 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 06169 #endif 06170 #ifdef CONTEXT_DEBUG 06171 check_contexts(__FILE__, __LINE__); 06172 #endif 06173 /* find this particular extension */ 06174 ex.exten = dummy_name; 06175 ex.matchcid = matchcallerid; 06176 ex.cidmatch = callerid; 06177 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 06178 exten = ast_hashtab_lookup(con->root_table, &ex); 06179 if (exten) { 06180 if (priority == 0) { 06181 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06182 if (!exten2) 06183 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); 06184 if (con->pattern_tree) { 06185 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06186 06187 if (x->exten) { /* this test for safety purposes */ 06188 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06189 x->exten = 0; /* get rid of what will become a bad pointer */ 06190 } else { 06191 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 06192 } 06193 } 06194 } else { 06195 ex.priority = priority; 06196 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 06197 if (exten2) { 06198 if (exten2->label) { /* if this exten has a label, remove that, too */ 06199 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 06200 if (!exten3) 06201 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); 06202 } 06203 06204 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 06205 if (!exten3) 06206 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); 06207 if (exten2 == exten && exten2->peer) { 06208 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 06209 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 06210 } 06211 if (ast_hashtab_size(exten->peer_table) == 0) { 06212 /* well, if the last priority of an exten is to be removed, 06213 then, the extension is removed, too! */ 06214 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 06215 if (!exten3) 06216 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 06217 if (con->pattern_tree) { 06218 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 06219 if (x->exten) { /* this test for safety purposes */ 06220 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 06221 x->exten = 0; /* get rid of what will become a bad pointer */ 06222 } 06223 } 06224 } 06225 } else { 06226 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 06227 priority, exten->exten, con->name); 06228 } 06229 } 06230 } else { 06231 /* hmmm? this exten is not in this pattern tree? */ 06232 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 06233 extension, con->name); 06234 } 06235 #ifdef NEED_DEBUG 06236 if (con->pattern_tree) { 06237 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 06238 log_match_char_tree(con->pattern_tree, " "); 06239 } 06240 #endif 06241 06242 /* scan the extension list to find first matching extension-registrar */ 06243 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 06244 if (!strcmp(exten->exten, extension) && 06245 (!registrar || !strcmp(exten->registrar, registrar)) && 06246 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 06247 break; 06248 } 06249 if (!exten) { 06250 /* we can't find right extension */ 06251 if (!already_locked) 06252 ast_unlock_context(con); 06253 return -1; 06254 } 06255 06256 /* scan the priority list to remove extension with exten->priority == priority */ 06257 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 06258 peer && !strcmp(peer->exten, extension) && 06259 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ; 06260 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 06261 06262 if ((priority == 0 || peer->priority == priority) && 06263 (!registrar || !strcmp(peer->registrar, registrar) )) { 06264 found = 1; 06265 06266 /* we are first priority extension? */ 06267 if (!previous_peer) { 06268 /* 06269 * We are first in the priority chain, so must update the extension chain. 06270 * The next node is either the next priority or the next extension 06271 */ 06272 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 06273 if (peer->peer) { 06274 /* move the peer_table and peer_label_table down to the next peer, if 06275 it is there */ 06276 peer->peer->peer_table = peer->peer_table; 06277 peer->peer->peer_label_table = peer->peer_label_table; 06278 peer->peer_table = NULL; 06279 peer->peer_label_table = NULL; 06280 } 06281 if (!prev_exten) { /* change the root... */ 06282 con->root = next_node; 06283 } else { 06284 prev_exten->next = next_node; /* unlink */ 06285 } 06286 if (peer->peer) { /* update the new head of the pri list */ 06287 peer->peer->next = peer->next; 06288 } 06289 } else { /* easy, we are not first priority in extension */ 06290 previous_peer->peer = peer->peer; 06291 } 06292 06293 06294 /* now, free whole priority extension */ 06295 destroy_exten(peer); 06296 } else { 06297 previous_peer = peer; 06298 } 06299 } 06300 if (!already_locked) 06301 ast_unlock_context(con); 06302 return found ? 0 : -1; 06303 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8559 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08560 { 08561 int ret = -1; 08562 struct ast_context *c; 08563 08564 c = find_context_locked(context); 08565 if (c) { 08566 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08567 ast_unlock_contexts(); 08568 } 08569 return ret; 08570 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8572 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().
08573 { 08574 struct ast_ignorepat *ip, *ipl = NULL; 08575 08576 ast_wrlock_context(con); 08577 08578 for (ip = con->ignorepats; ip; ip = ip->next) { 08579 if (!strcmp(ip->pattern, ignorepat) && 08580 (!registrar || (registrar == ip->registrar))) { 08581 if (ipl) { 08582 ipl->next = ip->next; 08583 ast_free(ip); 08584 } else { 08585 con->ignorepats = ip->next; 08586 ast_free(ip); 08587 } 08588 ast_unlock_context(con); 08589 return 0; 08590 } 08591 ipl = ip; 08592 } 08593 08594 ast_unlock_context(con); 08595 errno = EINVAL; 08596 return -1; 08597 }
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 6012 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
06013 { 06014 int ret = -1; 06015 struct ast_context *c; 06016 06017 c = find_context_locked(context); 06018 if (c) { 06019 /* found, remove include from this context ... */ 06020 ret = ast_context_remove_include2(c, include, registrar); 06021 ast_unlock_contexts(); 06022 } 06023 return ret; 06024 }
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 6035 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().
06036 { 06037 struct ast_include *i, *pi = NULL; 06038 int ret = -1; 06039 06040 ast_wrlock_context(con); 06041 06042 /* find our include */ 06043 for (i = con->includes; i; pi = i, i = i->next) { 06044 if (!strcmp(i->name, include) && 06045 (!registrar || !strcmp(i->registrar, registrar))) { 06046 /* remove from list */ 06047 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 06048 if (pi) 06049 pi->next = i->next; 06050 else 06051 con->includes = i->next; 06052 /* free include and return */ 06053 ast_destroy_timing(&(i->timing)); 06054 ast_free(i); 06055 ret = 0; 06056 break; 06057 } 06058 } 06059 06060 ast_unlock_context(con); 06061 06062 return ret; 06063 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 6070 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
06071 { 06072 int ret = -1; /* default error return */ 06073 struct ast_context *c; 06074 06075 c = find_context_locked(context); 06076 if (c) { 06077 /* remove switch from this context ... */ 06078 ret = ast_context_remove_switch2(c, sw, data, registrar); 06079 ast_unlock_contexts(); 06080 } 06081 return ret; 06082 }
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 6092 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().
06093 { 06094 struct ast_sw *i; 06095 int ret = -1; 06096 06097 ast_wrlock_context(con); 06098 06099 /* walk switches */ 06100 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 06101 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 06102 (!registrar || !strcmp(i->registrar, registrar))) { 06103 /* found, remove from list */ 06104 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 06105 AST_LIST_REMOVE_CURRENT(list); 06106 ast_free(i); /* free switch and return */ 06107 ret = 0; 06108 break; 06109 } 06110 } 06111 AST_LIST_TRAVERSE_SAFE_END; 06112 06113 ast_unlock_context(con); 06114 06115 return ret; 06116 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 6332 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06333 { 06334 struct ast_context *c; 06335 int ret = -1; 06336 06337 c = find_context_locked(context); 06338 if (c) { 06339 ast_unlock_contexts(); 06340 06341 /* if we found context, unlock macrolock */ 06342 ret = ast_mutex_unlock(&c->macrolock); 06343 } 06344 06345 return ret; 06346 }
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 11131 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().
11132 { 11133 struct ast_include *inc = NULL; 11134 int res = 0; 11135 11136 while ( (inc = ast_walk_context_includes(con, inc)) ) { 11137 if (ast_context_find(inc->rname)) 11138 continue; 11139 11140 res = -1; 11141 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 11142 ast_get_context_name(con), inc->rname); 11143 break; 11144 } 11145 11146 return res; 11147 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3757 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().
03758 { 03759 struct ast_custom_function *acf = NULL; 03760 03761 AST_RWLIST_RDLOCK(&acf_root); 03762 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03763 if (!strcmp(name, acf->name)) 03764 break; 03765 } 03766 AST_RWLIST_UNLOCK(&acf_root); 03767 03768 return acf; 03769 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3771 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().
03772 { 03773 struct ast_custom_function *cur; 03774 struct ast_custom_escalating_function *cur_escalation; 03775 03776 if (!acf) { 03777 return -1; 03778 } 03779 03780 AST_RWLIST_WRLOCK(&acf_root); 03781 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03782 #ifdef AST_XML_DOCS 03783 if (cur->docsrc == AST_XML_DOC) { 03784 ast_string_field_free_memory(acf); 03785 } 03786 #endif 03787 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03788 } 03789 AST_RWLIST_UNLOCK(&acf_root); 03790 03791 /* Remove from the escalation list */ 03792 AST_RWLIST_WRLOCK(&escalation_root); 03793 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) { 03794 if (cur_escalation->acf == acf) { 03795 AST_RWLIST_REMOVE_CURRENT(list); 03796 ast_free(cur_escalation); 03797 break; 03798 } 03799 } 03800 AST_RWLIST_TRAVERSE_SAFE_END; 03801 AST_RWLIST_UNLOCK(&escalation_root); 03802 03803 return cur ? 0 : -1; 03804 }
int ast_destroy_timing | ( | struct ast_timing * | i | ) |
Deallocates memory structures associated with a timing bitmap.
i | Pointer to an ast_timing structure. |
0 | success | |
non-zero | failure (number suitable to pass to |
Definition at line 8401 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 4849 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().
04850 { 04851 switch (devstate) { 04852 case AST_DEVICE_ONHOLD: 04853 return AST_EXTENSION_ONHOLD; 04854 case AST_DEVICE_BUSY: 04855 return AST_EXTENSION_BUSY; 04856 case AST_DEVICE_UNKNOWN: 04857 return AST_EXTENSION_NOT_INUSE; 04858 case AST_DEVICE_UNAVAILABLE: 04859 case AST_DEVICE_INVALID: 04860 return AST_EXTENSION_UNAVAILABLE; 04861 case AST_DEVICE_RINGINUSE: 04862 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04863 case AST_DEVICE_RINGING: 04864 return AST_EXTENSION_RINGING; 04865 case AST_DEVICE_INUSE: 04866 return AST_EXTENSION_INUSE; 04867 case AST_DEVICE_NOT_INUSE: 04868 return AST_EXTENSION_NOT_INUSE; 04869 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04870 break; 04871 } 04872 04873 return AST_EXTENSION_NOT_INUSE; 04874 }
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 5405 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().
05406 { 05407 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05408 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8713 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().
08714 { 08715 if (!chan) 08716 return -1; 08717 08718 ast_channel_lock(chan); 08719 08720 if (!ast_strlen_zero(context)) 08721 ast_copy_string(chan->context, context, sizeof(chan->context)); 08722 if (!ast_strlen_zero(exten)) 08723 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08724 if (priority > -1) { 08725 chan->priority = priority; 08726 /* see flag description in channel.h for explanation */ 08727 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08728 chan->priority--; 08729 } 08730 08731 ast_channel_unlock(chan); 08732 08733 return 0; 08734 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2905 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().
02906 { 02907 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02908 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02909 return extension_match_core(pattern, data, needmore); 02910 }
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 2670 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02671 { 02672 int cmp; 02673 02674 cmp = ext_cmp(a, b); 02675 if (cmp < 0) { 02676 return -1; 02677 } 02678 if (cmp > 0) { 02679 return 1; 02680 } 02681 return 0; 02682 }
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 2900 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().
02901 { 02902 return extension_match_core(pattern, data, E_MATCH); 02903 }
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 4919 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().
04920 { 04921 struct ast_exten *e; 04922 04923 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04924 return -1; /* No hint, return -1 */ 04925 } 04926 04927 if (e->exten[0] == '_') { 04928 /* Create this hint on-the-fly */ 04929 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04930 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04931 e->registrar); 04932 if (!(e = ast_hint_extension(c, context, exten))) { 04933 /* Improbable, but not impossible */ 04934 return -1; 04935 } 04936 } 04937 04938 return ast_extension_state2(e); /* Check all devices in the hint */ 04939 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4894 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().
04895 { 04896 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32); 04897 04898 if (!e || !hint_app) { 04899 return -1; 04900 } 04901 04902 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e)); 04903 return ast_extension_state3(hint_app); 04904 }
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 4907 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().
04908 { 04909 int i; 04910 04911 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04912 if (extension_states[i].extension_state == extension_state) 04913 return extension_states[i].text; 04914 } 04915 return "Unknown"; 04916 }
static int ast_extension_state3 | ( | struct ast_str * | hint_app | ) | [static] |
Definition at line 4876 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().
04877 { 04878 char *cur; 04879 char *rest; 04880 struct ast_devstate_aggregate agg; 04881 04882 /* One or more devices separated with a & character */ 04883 rest = ast_str_buffer(hint_app); 04884 04885 ast_devstate_aggregate_init(&agg); 04886 while ((cur = strsep(&rest, "&"))) { 04887 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04888 } 04889 04890 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04891 }
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 5140 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
05142 { 05143 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 05144 }
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 5053 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().
05055 { 05056 struct ast_hint *hint; 05057 struct ast_state_cb *state_cb; 05058 struct ast_exten *e; 05059 int id; 05060 05061 /* If there's no context and extension: add callback to statecbs list */ 05062 if (!context && !exten) { 05063 /* Prevent multiple adds from adding the same change_cb at the same time. */ 05064 ao2_lock(statecbs); 05065 05066 /* Remove any existing change_cb. */ 05067 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 05068 05069 /* Now insert the change_cb */ 05070 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05071 ao2_unlock(statecbs); 05072 return -1; 05073 } 05074 state_cb->id = 0; 05075 state_cb->change_cb = change_cb; 05076 state_cb->destroy_cb = destroy_cb; 05077 state_cb->data = data; 05078 ao2_link(statecbs, state_cb); 05079 05080 ao2_ref(state_cb, -1); 05081 ao2_unlock(statecbs); 05082 return 0; 05083 } 05084 05085 if (!context || !exten) 05086 return -1; 05087 05088 /* This callback type is for only one hint, so get the hint */ 05089 e = ast_hint_extension(NULL, context, exten); 05090 if (!e) { 05091 return -1; 05092 } 05093 05094 /* If this is a pattern, dynamically create a new extension for this 05095 * particular match. Note that this will only happen once for each 05096 * individual extension, because the pattern will no longer match first. 05097 */ 05098 if (e->exten[0] == '_') { 05099 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 05100 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 05101 e->registrar); 05102 e = ast_hint_extension(NULL, context, exten); 05103 if (!e || e->exten[0] == '_') { 05104 return -1; 05105 } 05106 } 05107 05108 /* Find the hint in the hints container */ 05109 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05110 hint = ao2_find(hints, e, 0); 05111 if (!hint) { 05112 ao2_unlock(hints); 05113 return -1; 05114 } 05115 05116 /* Now insert the callback in the callback list */ 05117 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 05118 ao2_ref(hint, -1); 05119 ao2_unlock(hints); 05120 return -1; 05121 } 05122 do { 05123 id = stateid++; /* Unique ID for this callback */ 05124 /* Do not allow id to ever be -1 or 0. */ 05125 } while (id == -1 || id == 0); 05126 state_cb->id = id; 05127 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 05128 state_cb->destroy_cb = destroy_cb; 05129 state_cb->data = data; /* Data for the callback */ 05130 ao2_link(hint->callbacks, state_cb); 05131 05132 ao2_ref(state_cb, -1); 05133 ao2_ref(hint, -1); 05134 ao2_unlock(hints); 05135 05136 return id; 05137 }
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 5162 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().
05163 { 05164 struct ast_state_cb *p_cur; 05165 int ret = -1; 05166 05167 if (!id) { /* id == 0 is a callback without extension */ 05168 if (!change_cb) { 05169 return ret; 05170 } 05171 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 05172 if (p_cur) { 05173 ret = 0; 05174 ao2_ref(p_cur, -1); 05175 } 05176 } else { /* callback with extension, find the callback based on ID */ 05177 struct ast_hint *hint; 05178 05179 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 05180 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 05181 if (hint) { 05182 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 05183 if (p_cur) { 05184 ret = 0; 05185 ao2_ref(p_cur, -1); 05186 } 05187 ao2_ref(hint, -1); 05188 } 05189 ao2_unlock(hints); 05190 } 05191 05192 return ret; 05193 }
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 5410 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().
05411 { 05412 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05413 }
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 5415 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05416 { 05417 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05418 }
int ast_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | workspace, | |||
size_t | len | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
workspace | A pointer to safe memory to use for a return value | |
len | the number of bytes in workspace |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 4134 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
04135 { 04136 char *copy = ast_strdupa(function); 04137 char *args = func_args(copy); 04138 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04139 int res; 04140 struct ast_module_user *u = NULL; 04141 04142 if (acfptr == NULL) { 04143 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04144 } else if (!acfptr->read && !acfptr->read2) { 04145 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04146 } else if (!is_read_allowed(acfptr)) { 04147 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04148 } else if (acfptr->read) { 04149 if (acfptr->mod) { 04150 u = __ast_module_user_add(acfptr->mod, chan); 04151 } 04152 res = acfptr->read(chan, copy, args, workspace, len); 04153 if (acfptr->mod && u) { 04154 __ast_module_user_remove(acfptr->mod, u); 04155 } 04156 return res; 04157 } else { 04158 struct ast_str *str = ast_str_create(16); 04159 if (acfptr->mod) { 04160 u = __ast_module_user_add(acfptr->mod, chan); 04161 } 04162 res = acfptr->read2(chan, copy, args, &str, 0); 04163 if (acfptr->mod && u) { 04164 __ast_module_user_remove(acfptr->mod, u); 04165 } 04166 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 04167 ast_free(str); 04168 return res; 04169 } 04170 return -1; 04171 }
int ast_func_read2 | ( | struct ast_channel * | chan, | |
const char * | function, | |||
struct ast_str ** | str, | |||
ssize_t | maxlen | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
str | A dynamic string buffer into which to place the result. | |
maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 4173 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
04174 { 04175 char *copy = ast_strdupa(function); 04176 char *args = func_args(copy); 04177 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04178 int res; 04179 struct ast_module_user *u = NULL; 04180 04181 if (acfptr == NULL) { 04182 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04183 } else if (!acfptr->read && !acfptr->read2) { 04184 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 04185 } else if (!is_read_allowed(acfptr)) { 04186 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy); 04187 } else { 04188 if (acfptr->mod) { 04189 u = __ast_module_user_add(acfptr->mod, chan); 04190 } 04191 ast_str_reset(*str); 04192 if (acfptr->read2) { 04193 /* ast_str enabled */ 04194 res = acfptr->read2(chan, copy, args, str, maxlen); 04195 } else { 04196 /* Legacy function pointer, allocate buffer for result */ 04197 int maxsize = ast_str_size(*str); 04198 if (maxlen > -1) { 04199 if (maxlen == 0) { 04200 if (acfptr->read_max) { 04201 maxsize = acfptr->read_max; 04202 } else { 04203 maxsize = VAR_BUF_SIZE; 04204 } 04205 } else { 04206 maxsize = maxlen; 04207 } 04208 ast_str_make_space(str, maxsize); 04209 } 04210 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 04211 } 04212 if (acfptr->mod && u) { 04213 __ast_module_user_remove(acfptr->mod, u); 04214 } 04215 return res; 04216 } 04217 return -1; 04218 }
int ast_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
const char * | value | |||
) |
executes a write operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
value | A value parameter to pass for writing |
This application executes a function in write mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 4220 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), is_write_allowed(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
04221 { 04222 char *copy = ast_strdupa(function); 04223 char *args = func_args(copy); 04224 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 04225 04226 if (acfptr == NULL) { 04227 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 04228 } else if (!acfptr->write) { 04229 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 04230 } else if (!is_write_allowed(acfptr)) { 04231 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy); 04232 } else { 04233 int res; 04234 struct ast_module_user *u = NULL; 04235 if (acfptr->mod) 04236 u = __ast_module_user_add(acfptr->mod, chan); 04237 res = acfptr->write(chan, copy, args, value); 04238 if (acfptr->mod && u) 04239 __ast_module_user_remove(acfptr->mod, u); 04240 return res; 04241 } 04242 04243 return -1; 04244 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10983 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().
10984 { 10985 return con ? con->name : NULL; 10986 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 11021 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
11022 { 11023 return c ? c->registrar : NULL; 11024 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 11051 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().
11052 { 11053 return e ? e->app : NULL; 11054 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 11056 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().
11057 { 11058 return e ? e->data : NULL; 11059 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 11046 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
11047 { 11048 return e ? e->cidmatch : NULL; 11049 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10988 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().
10989 { 10990 return exten ? exten->parent : NULL; 10991 }
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 10998 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10999 { 11000 return exten ? exten->label : NULL; 11001 }
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 11041 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
11042 { 11043 return e ? e->matchcid : 0; 11044 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10993 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().
10994 { 10995 return exten ? exten->exten : NULL; 10996 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 11013 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().
11014 { 11015 return exten ? exten->priority : -1; 11016 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 11026 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
11027 { 11028 return e ? e->registrar : NULL; 11029 }
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 5367 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().
05368 { 05369 struct ast_exten *e = ast_hint_extension(c, context, exten); 05370 05371 if (e) { 05372 if (hint) 05373 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05374 if (name) { 05375 const char *tmp = ast_get_extension_app_data(e); 05376 if (tmp) 05377 ast_copy_string(name, tmp, namesize); 05378 } 05379 return -1; 05380 } 05381 return 0; 05382 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 11008 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().
11009 { 11010 return ip ? ip->pattern : NULL; 11011 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 11036 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().
11037 { 11038 return ip ? ip->registrar : NULL; 11039 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 11003 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().
11004 { 11005 return inc ? inc->name : NULL; 11006 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 11031 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().
11032 { 11033 return i ? i->registrar : NULL; 11034 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 11066 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().
11067 { 11068 return sw ? sw->data : NULL; 11069 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 11071 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
11072 { 11073 return sw->eval; 11074 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 11061 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().
11062 { 11063 return sw ? sw->name : NULL; 11064 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 11076 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().
11077 { 11078 return sw ? sw->registrar : NULL; 11079 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 11171 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().
11172 { 11173 return __ast_goto_if_exists(chan, context, exten, priority, 0); 11174 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1092 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01093 { 01094 const struct ast_context *ac = ah_a; 01095 const struct ast_context *bc = ah_b; 01096 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01097 return 1; 01098 /* assume context names are registered in a string table! */ 01099 return strcmp(ac->name, bc->name); 01100 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1144 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01145 { 01146 const struct ast_context *ac = obj; 01147 return ast_hashtab_hash_string(ac->name); 01148 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static, read] |
Definition at line 4840 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().
04841 { 04842 struct ast_exten *e; 04843 ast_rdlock_contexts(); 04844 e = ast_hint_extension_nolock(c, context, exten); 04845 ast_unlock_contexts(); 04846 return e; 04847 }
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 4834 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().
04835 { 04836 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04837 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04838 }
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 8655 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().
08656 { 08657 struct ast_context *con = ast_context_find(context); 08658 08659 if (con) { 08660 struct ast_ignorepat *pat; 08661 08662 for (pat = con->ignorepats; pat; pat = pat->next) { 08663 if (ast_extension_match(pat->pattern, pattern)) 08664 return 1; 08665 } 08666 } 08667 08668 return 0; 08669 }
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 5425 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().
05426 { 05427 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05428 }
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 7942 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().
07943 { 07944 double ft; 07945 struct ast_context *tmp; 07946 struct ast_context *oldcontextslist; 07947 struct ast_hashtab *oldtable; 07948 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07949 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07950 struct store_hint *saved_hint; 07951 struct ast_hint *hint; 07952 struct ast_exten *exten; 07953 int length; 07954 struct ast_state_cb *thiscb; 07955 struct ast_hashtab_iter *iter; 07956 struct ao2_iterator i; 07957 struct timeval begintime; 07958 struct timeval writelocktime; 07959 struct timeval endlocktime; 07960 struct timeval enddeltime; 07961 07962 /* 07963 * It is very important that this function hold the hints 07964 * container lock _and_ the conlock during its operation; not 07965 * only do we need to ensure that the list of contexts and 07966 * extensions does not change, but also that no hint callbacks 07967 * (watchers) are added or removed during the merge/delete 07968 * process 07969 * 07970 * In addition, the locks _must_ be taken in this order, because 07971 * there are already other code paths that use this order 07972 */ 07973 07974 begintime = ast_tvnow(); 07975 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07976 ast_wrlock_contexts(); 07977 07978 if (!contexts_table) { 07979 /* Well, that's odd. There are no contexts. */ 07980 contexts_table = exttable; 07981 contexts = *extcontexts; 07982 ast_unlock_contexts(); 07983 ast_mutex_unlock(&context_merge_lock); 07984 return; 07985 } 07986 07987 iter = ast_hashtab_start_traversal(contexts_table); 07988 while ((tmp = ast_hashtab_next(iter))) { 07989 context_merge(extcontexts, exttable, tmp, registrar); 07990 } 07991 ast_hashtab_end_traversal(iter); 07992 07993 ao2_lock(hints); 07994 writelocktime = ast_tvnow(); 07995 07996 /* preserve all watchers for hints */ 07997 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07998 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07999 if (ao2_container_count(hint->callbacks)) { 08000 ao2_lock(hint); 08001 if (!hint->exten) { 08002 /* The extension has already been destroyed. (Should never happen here) */ 08003 ao2_unlock(hint); 08004 continue; 08005 } 08006 08007 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 08008 + sizeof(*saved_hint); 08009 if (!(saved_hint = ast_calloc(1, length))) { 08010 ao2_unlock(hint); 08011 continue; 08012 } 08013 08014 /* This removes all the callbacks from the hint into saved_hint. */ 08015 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 08016 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 08017 /* 08018 * We intentionally do not unref thiscb to account for the 08019 * non-ao2 reference in saved_hint->callbacks 08020 */ 08021 } 08022 08023 saved_hint->laststate = hint->laststate; 08024 saved_hint->context = saved_hint->data; 08025 strcpy(saved_hint->data, hint->exten->parent->name); 08026 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 08027 strcpy(saved_hint->exten, hint->exten->exten); 08028 ao2_unlock(hint); 08029 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 08030 } 08031 } 08032 ao2_iterator_destroy(&i); 08033 08034 /* save the old table and list */ 08035 oldtable = contexts_table; 08036 oldcontextslist = contexts; 08037 08038 /* move in the new table and list */ 08039 contexts_table = exttable; 08040 contexts = *extcontexts; 08041 08042 /* 08043 * Restore the watchers for hints that can be found; notify 08044 * those that cannot be restored. 08045 */ 08046 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 08047 struct pbx_find_info q = { .stacklen = 0 }; 08048 08049 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 08050 PRIORITY_HINT, NULL, "", E_MATCH); 08051 /* 08052 * If this is a pattern, dynamically create a new extension for this 08053 * particular match. Note that this will only happen once for each 08054 * individual extension, because the pattern will no longer match first. 08055 */ 08056 if (exten && exten->exten[0] == '_') { 08057 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 08058 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 08059 exten->registrar); 08060 /* rwlocks are not recursive locks */ 08061 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 08062 saved_hint->exten); 08063 } 08064 08065 /* Find the hint in the hints container */ 08066 hint = exten ? ao2_find(hints, exten, 0) : NULL; 08067 if (!hint) { 08068 /* 08069 * Notify watchers of this removed hint later when we aren't 08070 * encumberd by so many locks. 08071 */ 08072 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 08073 } else { 08074 ao2_lock(hint); 08075 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08076 ao2_link(hint->callbacks, thiscb); 08077 /* Ref that we added when putting into saved_hint->callbacks */ 08078 ao2_ref(thiscb, -1); 08079 } 08080 hint->laststate = saved_hint->laststate; 08081 ao2_unlock(hint); 08082 ao2_ref(hint, -1); 08083 ast_free(saved_hint); 08084 } 08085 } 08086 08087 ao2_unlock(hints); 08088 ast_unlock_contexts(); 08089 08090 /* 08091 * Notify watchers of all removed hints with the same lock 08092 * environment as handle_statechange(). 08093 */ 08094 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 08095 /* this hint has been removed, notify the watchers */ 08096 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 08097 thiscb->change_cb(saved_hint->context, saved_hint->exten, 08098 AST_EXTENSION_REMOVED, thiscb->data); 08099 /* Ref that we added when putting into saved_hint->callbacks */ 08100 ao2_ref(thiscb, -1); 08101 } 08102 ast_free(saved_hint); 08103 } 08104 08105 ast_mutex_unlock(&context_merge_lock); 08106 endlocktime = ast_tvnow(); 08107 08108 /* 08109 * The old list and hashtab no longer are relevant, delete them 08110 * while the rest of asterisk is now freely using the new stuff 08111 * instead. 08112 */ 08113 08114 ast_hashtab_destroy(oldtable, NULL); 08115 08116 for (tmp = oldcontextslist; tmp; ) { 08117 struct ast_context *next; /* next starting point */ 08118 08119 next = tmp->next; 08120 __ast_internal_context_destroy(tmp); 08121 tmp = next; 08122 } 08123 enddeltime = ast_tvnow(); 08124 08125 ft = ast_tvdiff_us(writelocktime, begintime); 08126 ft /= 1000000.0; 08127 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 08128 08129 ft = ast_tvdiff_us(endlocktime, writelocktime); 08130 ft /= 1000000.0; 08131 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 08132 08133 ft = ast_tvdiff_us(enddeltime, endlocktime); 08134 ft /= 1000000.0; 08135 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 08136 08137 ft = ast_tvdiff_us(enddeltime, begintime); 08138 ft /= 1000000.0; 08139 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 08140 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 11236 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().
11237 { 11238 return pbx_parseable_goto(chan, goto_string, 0); 11239 }
int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 11317 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().
11318 { 11319 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 11320 statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); 11321 11322 ast_register_atexit(pbx_shutdown); 11323 11324 return (hints && statecbs) ? 0 : -1; 11325 }
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 9549 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().
09550 { 09551 struct ast_channel *chan; 09552 struct app_tmp *tmp; 09553 int res = -1, cdr_res = -1; 09554 struct outgoing_helper oh; 09555 09556 memset(&oh, 0, sizeof(oh)); 09557 oh.vars = vars; 09558 oh.account = account; 09559 09560 if (locked_channel) 09561 *locked_channel = NULL; 09562 if (ast_strlen_zero(app)) { 09563 res = -1; 09564 goto outgoing_app_cleanup; 09565 } 09566 if (synchronous) { 09567 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09568 if (chan) { 09569 ast_set_variables(chan, vars); 09570 if (account) 09571 ast_cdr_setaccount(chan, account); 09572 if (chan->_state == AST_STATE_UP) { 09573 res = 0; 09574 ast_verb(4, "Channel %s was answered.\n", chan->name); 09575 tmp = ast_calloc(1, sizeof(*tmp)); 09576 if (!tmp || ast_string_field_init(tmp, 252)) { 09577 if (tmp) { 09578 ast_free(tmp); 09579 } 09580 res = -1; 09581 } else { 09582 ast_string_field_set(tmp, app, app); 09583 ast_string_field_set(tmp, data, appdata); 09584 tmp->chan = chan; 09585 if (synchronous > 1) { 09586 if (locked_channel) 09587 ast_channel_unlock(chan); 09588 ast_pbx_run_app(tmp); 09589 } else { 09590 if (locked_channel) 09591 ast_channel_lock(chan); 09592 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09593 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09594 ast_string_field_free_memory(tmp); 09595 ast_free(tmp); 09596 if (locked_channel) 09597 ast_channel_unlock(chan); 09598 ast_hangup(chan); 09599 res = -1; 09600 } else { 09601 if (locked_channel) 09602 *locked_channel = chan; 09603 } 09604 } 09605 } 09606 } else { 09607 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09608 if (chan->cdr) { /* update the cdr */ 09609 /* here we update the status of the call, which sould be busy. 09610 * if that fails then we set the status to failed */ 09611 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09612 ast_cdr_failed(chan->cdr); 09613 } 09614 ast_hangup(chan); 09615 } 09616 } 09617 09618 if (res < 0) { /* the call failed for some reason */ 09619 if (*reason == 0) { /* if the call failed (not busy or no answer) 09620 * update the cdr with the failed message */ 09621 cdr_res = ast_pbx_outgoing_cdr_failed(); 09622 if (cdr_res != 0) { 09623 res = cdr_res; 09624 goto outgoing_app_cleanup; 09625 } 09626 } 09627 } 09628 09629 } else { 09630 struct async_stat *as; 09631 if (!(as = ast_calloc(1, sizeof(*as)))) { 09632 res = -1; 09633 goto outgoing_app_cleanup; 09634 } 09635 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09636 if (!chan) { 09637 ast_free(as); 09638 res = -1; 09639 goto outgoing_app_cleanup; 09640 } 09641 as->chan = chan; 09642 ast_copy_string(as->app, app, sizeof(as->app)); 09643 if (appdata) 09644 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09645 as->timeout = timeout; 09646 ast_set_variables(chan, vars); 09647 if (account) 09648 ast_cdr_setaccount(chan, account); 09649 /* Start a new thread, and get something handling this channel. */ 09650 if (locked_channel) 09651 ast_channel_lock(chan); 09652 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09653 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09654 ast_free(as); 09655 if (locked_channel) 09656 ast_channel_unlock(chan); 09657 ast_hangup(chan); 09658 res = -1; 09659 goto outgoing_app_cleanup; 09660 } else { 09661 if (locked_channel) 09662 *locked_channel = chan; 09663 } 09664 res = 0; 09665 } 09666 outgoing_app_cleanup: 09667 ast_variables_destroy(vars); 09668 return res; 09669 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 9353 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().
09354 { 09355 /* allocate a channel */ 09356 struct ast_channel *chan = ast_dummy_channel_alloc(); 09357 09358 if (!chan) 09359 return -1; /* failure */ 09360 09361 chan->cdr = ast_cdr_alloc(); 09362 if (!chan->cdr) { 09363 /* allocation of the cdr failed */ 09364 chan = ast_channel_unref(chan); /* free the channel */ 09365 return -1; /* return failure */ 09366 } 09367 09368 /* allocation of the cdr was successful */ 09369 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 09370 ast_cdr_start(chan->cdr); /* record the start and stop time */ 09371 ast_cdr_end(chan->cdr); 09372 ast_cdr_failed(chan->cdr); /* set the status to failed */ 09373 ast_cdr_detach(chan->cdr); /* post and free the record */ 09374 chan->cdr = NULL; 09375 chan = ast_channel_unref(chan); /* free the channel */ 09376 09377 return 0; /* success */ 09378 }
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 9380 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().
09381 { 09382 struct ast_channel *chan; 09383 struct async_stat *as; 09384 int res = -1, cdr_res = -1; 09385 struct outgoing_helper oh; 09386 09387 if (synchronous) { 09388 oh.context = context; 09389 oh.exten = exten; 09390 oh.priority = priority; 09391 oh.cid_num = cid_num; 09392 oh.cid_name = cid_name; 09393 oh.account = account; 09394 oh.vars = vars; 09395 oh.parent_channel = NULL; 09396 09397 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09398 if (channel) { 09399 *channel = chan; 09400 if (chan) 09401 ast_channel_lock(chan); 09402 } 09403 if (chan) { 09404 if (chan->_state == AST_STATE_UP) { 09405 res = 0; 09406 ast_verb(4, "Channel %s was answered.\n", chan->name); 09407 09408 if (synchronous > 1) { 09409 if (channel) 09410 ast_channel_unlock(chan); 09411 if (ast_pbx_run(chan)) { 09412 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09413 if (channel) 09414 *channel = NULL; 09415 ast_hangup(chan); 09416 chan = NULL; 09417 res = -1; 09418 } 09419 } else { 09420 if (ast_pbx_start(chan)) { 09421 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09422 if (channel) { 09423 *channel = NULL; 09424 ast_channel_unlock(chan); 09425 } 09426 ast_hangup(chan); 09427 res = -1; 09428 } 09429 chan = NULL; 09430 } 09431 } else { 09432 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09433 09434 if (chan->cdr) { /* update the cdr */ 09435 /* here we update the status of the call, which sould be busy. 09436 * if that fails then we set the status to failed */ 09437 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09438 ast_cdr_failed(chan->cdr); 09439 } 09440 09441 if (channel) { 09442 *channel = NULL; 09443 ast_channel_unlock(chan); 09444 } 09445 ast_hangup(chan); 09446 chan = NULL; 09447 } 09448 } 09449 09450 if (res < 0) { /* the call failed for some reason */ 09451 if (*reason == 0) { /* if the call failed (not busy or no answer) 09452 * update the cdr with the failed message */ 09453 cdr_res = ast_pbx_outgoing_cdr_failed(); 09454 if (cdr_res != 0) { 09455 res = cdr_res; 09456 goto outgoing_exten_cleanup; 09457 } 09458 } 09459 09460 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09461 /* check if "failed" exists */ 09462 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09463 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09464 if (chan) { 09465 char failed_reason[4] = ""; 09466 if (!ast_strlen_zero(context)) 09467 ast_copy_string(chan->context, context, sizeof(chan->context)); 09468 set_ext_pri(chan, "failed", 1); 09469 ast_set_variables(chan, vars); 09470 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09471 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09472 if (account) 09473 ast_cdr_setaccount(chan, account); 09474 if (ast_pbx_run(chan)) { 09475 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09476 ast_hangup(chan); 09477 } 09478 chan = NULL; 09479 } 09480 } 09481 } 09482 } else { 09483 if (!(as = ast_calloc(1, sizeof(*as)))) { 09484 res = -1; 09485 goto outgoing_exten_cleanup; 09486 } 09487 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09488 if (channel) { 09489 *channel = chan; 09490 if (chan) 09491 ast_channel_lock(chan); 09492 } 09493 if (!chan) { 09494 ast_free(as); 09495 res = -1; 09496 goto outgoing_exten_cleanup; 09497 } 09498 as->chan = chan; 09499 ast_copy_string(as->context, context, sizeof(as->context)); 09500 set_ext_pri(as->chan, exten, priority); 09501 as->timeout = timeout; 09502 ast_set_variables(chan, vars); 09503 if (account) 09504 ast_cdr_setaccount(chan, account); 09505 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09506 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09507 ast_free(as); 09508 if (channel) { 09509 *channel = NULL; 09510 ast_channel_unlock(chan); 09511 } 09512 ast_hangup(chan); 09513 res = -1; 09514 goto outgoing_exten_cleanup; 09515 } 09516 res = 0; 09517 } 09518 outgoing_exten_cleanup: 09519 ast_variables_destroy(vars); 09520 return res; 09521 }
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 5931 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().
05932 { 05933 return ast_pbx_run_args(c, NULL); 05934 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 9533 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().
09534 { 09535 struct app_tmp *tmp = data; 09536 struct ast_app *app; 09537 app = pbx_findapp(tmp->app); 09538 if (app) { 09539 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 09540 pbx_exec(tmp->chan, app, tmp->data); 09541 } else 09542 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 09543 ast_hangup(tmp->chan); 09544 ast_string_field_free_memory(tmp); 09545 ast_free(tmp); 09546 return NULL; 09547 }
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 5911 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().
05912 { 05913 enum ast_pbx_result res = AST_PBX_SUCCESS; 05914 05915 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05916 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05917 return AST_PBX_FAILED; 05918 } 05919 05920 if (increase_call_count(c)) { 05921 return AST_PBX_CALL_LIMIT; 05922 } 05923 05924 res = __ast_pbx_run(c, args); 05925 05926 decrease_call_count(); 05927 05928 return res; 05929 }
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 5884 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().
05885 { 05886 pthread_t t; 05887 05888 if (!c) { 05889 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05890 return AST_PBX_FAILED; 05891 } 05892 05893 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05894 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05895 return AST_PBX_FAILED; 05896 } 05897 05898 if (increase_call_count(c)) 05899 return AST_PBX_CALL_LIMIT; 05900 05901 /* Start a new thread, and get something handling this channel. */ 05902 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05903 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05904 decrease_call_count(); 05905 return AST_PBX_FAILED; 05906 } 05907 05908 return AST_PBX_SUCCESS; 05909 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5941 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05942 { 05943 return totalcalls; 05944 }
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 10970 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().
10971 { 10972 return ast_rwlock_rdlock(&con->lock); 10973 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10952 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().
10953 { 10954 return ast_mutex_lock(&conlock); 10955 }
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 6349 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().
06350 { 06351 struct ast_app *tmp, *cur = NULL; 06352 char tmps[80]; 06353 int length, res; 06354 #ifdef AST_XML_DOCS 06355 char *tmpxml; 06356 #endif 06357 06358 AST_RWLIST_WRLOCK(&apps); 06359 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 06360 if (!(res = strcasecmp(app, tmp->name))) { 06361 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 06362 AST_RWLIST_UNLOCK(&apps); 06363 return -1; 06364 } else if (res < 0) 06365 break; 06366 } 06367 06368 length = sizeof(*tmp) + strlen(app) + 1; 06369 06370 if (!(tmp = ast_calloc(1, length))) { 06371 AST_RWLIST_UNLOCK(&apps); 06372 return -1; 06373 } 06374 06375 if (ast_string_field_init(tmp, 128)) { 06376 AST_RWLIST_UNLOCK(&apps); 06377 ast_free(tmp); 06378 return -1; 06379 } 06380 06381 strcpy(tmp->name, app); 06382 tmp->execute = execute; 06383 tmp->module = mod; 06384 06385 #ifdef AST_XML_DOCS 06386 /* Try to lookup the docs in our XML documentation database */ 06387 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 06388 /* load synopsis */ 06389 tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module)); 06390 ast_string_field_set(tmp, synopsis, tmpxml); 06391 ast_free(tmpxml); 06392 06393 /* load description */ 06394 tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); 06395 ast_string_field_set(tmp, description, tmpxml); 06396 ast_free(tmpxml); 06397 06398 /* load syntax */ 06399 tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module)); 06400 ast_string_field_set(tmp, syntax, tmpxml); 06401 ast_free(tmpxml); 06402 06403 /* load arguments */ 06404 tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module)); 06405 ast_string_field_set(tmp, arguments, tmpxml); 06406 ast_free(tmpxml); 06407 06408 /* load seealso */ 06409 tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module)); 06410 ast_string_field_set(tmp, seealso, tmpxml); 06411 ast_free(tmpxml); 06412 tmp->docsrc = AST_XML_DOC; 06413 } else { 06414 #endif 06415 ast_string_field_set(tmp, synopsis, synopsis); 06416 ast_string_field_set(tmp, description, description); 06417 #ifdef AST_XML_DOCS 06418 tmp->docsrc = AST_STATIC_DOC; 06419 } 06420 #endif 06421 06422 /* Store in alphabetical order */ 06423 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 06424 if (strcasecmp(tmp->name, cur->name) < 0) { 06425 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 06426 break; 06427 } 06428 } 06429 AST_RWLIST_TRAVERSE_SAFE_END; 06430 if (!cur) 06431 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 06432 06433 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 06434 06435 AST_RWLIST_UNLOCK(&apps); 06436 06437 return 0; 06438 }
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 6444 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().
06445 { 06446 struct ast_switch *tmp; 06447 06448 AST_RWLIST_WRLOCK(&switches); 06449 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06450 if (!strcasecmp(tmp->name, sw->name)) { 06451 AST_RWLIST_UNLOCK(&switches); 06452 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06453 return -1; 06454 } 06455 } 06456 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06457 AST_RWLIST_UNLOCK(&switches); 06458 06459 return 0; 06460 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 5242 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().
05243 { 05244 /* Cleanup the Notifys if hint is removed */ 05245 struct ast_hint *hint; 05246 05247 if (!e) { 05248 return -1; 05249 } 05250 05251 hint = ao2_find(hints, e, OBJ_UNLINK); 05252 if (!hint) { 05253 return -1; 05254 } 05255 05256 /* 05257 * The extension is being destroyed so we must save some 05258 * information to notify that the extension is deactivated. 05259 */ 05260 ao2_lock(hint); 05261 ast_copy_string(hint->context_name, 05262 ast_get_context_name(ast_get_extension_context(hint->exten)), 05263 sizeof(hint->context_name)); 05264 ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten), 05265 sizeof(hint->exten_name)); 05266 hint->exten = NULL; 05267 ao2_unlock(hint); 05268 05269 ao2_ref(hint, -1); 05270 05271 return 0; 05272 }
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 5430 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().
05431 { 05432 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05433 }
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 5385 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().
05386 { 05387 struct ast_exten *e = ast_hint_extension(c, context, exten); 05388 05389 if (!e) { 05390 return 0; 05391 } 05392 05393 if (hint) { 05394 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05395 } 05396 if (name) { 05397 const char *tmp = ast_get_extension_app_data(e); 05398 if (tmp) { 05399 ast_str_set(name, namesize, "%s", tmp); 05400 } 05401 } 05402 return -1; 05403 }
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 3402 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().
03403 { 03404 const char not_found = '\0'; 03405 char *tmpvar; 03406 const char *ret; 03407 const char *s; /* the result */ 03408 int offset, length; 03409 int i, need_substring; 03410 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03411 char workspace[20]; 03412 03413 if (c) { 03414 ast_channel_lock(c); 03415 places[0] = &c->varshead; 03416 } 03417 /* 03418 * Make a copy of var because parse_variable_name() modifies the string. 03419 * Then if called directly, we might need to run substring() on the result; 03420 * remember this for later in 'need_substring', 'offset' and 'length' 03421 */ 03422 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03423 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03424 03425 /* 03426 * Look first into predefined variables, then into variable lists. 03427 * Variable 's' points to the result, according to the following rules: 03428 * s == ¬_found (set at the beginning) means that we did not find a 03429 * matching variable and need to look into more places. 03430 * If s != ¬_found, s is a valid result string as follows: 03431 * s = NULL if the variable does not have a value; 03432 * you typically do this when looking for an unset predefined variable. 03433 * s = workspace if the result has been assembled there; 03434 * typically done when the result is built e.g. with an snprintf(), 03435 * so we don't need to do an additional copy. 03436 * s != workspace in case we have a string, that needs to be copied 03437 * (the ast_copy_string is done once for all at the end). 03438 * Typically done when the result is already available in some string. 03439 */ 03440 s = ¬_found; /* default value */ 03441 if (c) { /* This group requires a valid channel */ 03442 /* Names with common parts are looked up a piece at a time using strncmp. */ 03443 if (!strncmp(var, "CALL", 4)) { 03444 if (!strncmp(var + 4, "ING", 3)) { 03445 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03446 ast_str_set(str, maxlen, "%d", 03447 ast_party_id_presentation(&c->caller.id)); 03448 s = ast_str_buffer(*str); 03449 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03450 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03451 s = ast_str_buffer(*str); 03452 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03453 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03454 s = ast_str_buffer(*str); 03455 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03456 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03457 s = ast_str_buffer(*str); 03458 } 03459 } 03460 } else if (!strcmp(var, "HINT")) { 03461 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03462 } else if (!strcmp(var, "HINTNAME")) { 03463 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03464 } else if (!strcmp(var, "EXTEN")) { 03465 s = c->exten; 03466 } else if (!strcmp(var, "CONTEXT")) { 03467 s = c->context; 03468 } else if (!strcmp(var, "PRIORITY")) { 03469 ast_str_set(str, maxlen, "%d", c->priority); 03470 s = ast_str_buffer(*str); 03471 } else if (!strcmp(var, "CHANNEL")) { 03472 s = c->name; 03473 } else if (!strcmp(var, "UNIQUEID")) { 03474 s = c->uniqueid; 03475 } else if (!strcmp(var, "HANGUPCAUSE")) { 03476 ast_str_set(str, maxlen, "%d", c->hangupcause); 03477 s = ast_str_buffer(*str); 03478 } 03479 } 03480 if (s == ¬_found) { /* look for more */ 03481 if (!strcmp(var, "EPOCH")) { 03482 ast_str_set(str, maxlen, "%d", (int) time(NULL)); 03483 s = ast_str_buffer(*str); 03484 } else if (!strcmp(var, "SYSTEMNAME")) { 03485 s = ast_config_AST_SYSTEM_NAME; 03486 } else if (!strcmp(var, "ENTITYID")) { 03487 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03488 s = workspace; 03489 } 03490 } 03491 /* if not found, look into chanvars or global vars */ 03492 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03493 struct ast_var_t *variables; 03494 if (!places[i]) 03495 continue; 03496 if (places[i] == &globals) 03497 ast_rwlock_rdlock(&globalslock); 03498 AST_LIST_TRAVERSE(places[i], variables, entries) { 03499 if (!strcasecmp(ast_var_name(variables), var)) { 03500 s = ast_var_value(variables); 03501 break; 03502 } 03503 } 03504 if (places[i] == &globals) 03505 ast_rwlock_unlock(&globalslock); 03506 } 03507 if (s == ¬_found || s == NULL) { 03508 ast_debug(5, "Result of '%s' is NULL\n", var); 03509 ret = NULL; 03510 } else { 03511 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03512 if (s != ast_str_buffer(*str)) { 03513 ast_str_set(str, maxlen, "%s", s); 03514 } 03515 ret = ast_str_buffer(*str); 03516 if (need_substring) { 03517 ret = ast_str_substring(*str, offset, length); 03518 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03519 } 03520 } 03521 03522 if (c) { 03523 ast_channel_unlock(c); 03524 } 03525 return ret; 03526 }
void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
templ | Variable template to expand. |
Definition at line 4425 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().
04426 { 04427 size_t used; 04428 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04429 }
void ast_str_substitute_variables_full | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | c, | |||
struct varshead * | headp, | |||
const char * | templ, | |||
size_t * | used | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
c | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. | |
used | Number of bytes read from the template. |
Definition at line 4246 of file pbx.c.
References ast_channel_unref, ast_debug, ast_dummy_channel_alloc, ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().
04247 { 04248 /* Substitutes variables into buf, based on string templ */ 04249 char *cp4 = NULL; 04250 const char *tmp, *whereweare; 04251 int orig_size = 0; 04252 int offset, offset2, isfunction; 04253 const char *nextvar, *nextexp, *nextthing; 04254 const char *vars, *vare; 04255 char *finalvars; 04256 int pos, brackets, needsub, len; 04257 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04258 04259 ast_str_reset(*buf); 04260 whereweare = tmp = templ; 04261 while (!ast_strlen_zero(whereweare)) { 04262 /* reset our buffer */ 04263 ast_str_reset(substr3); 04264 04265 /* Assume we're copying the whole remaining string */ 04266 pos = strlen(whereweare); 04267 nextvar = NULL; 04268 nextexp = NULL; 04269 nextthing = strchr(whereweare, '$'); 04270 if (nextthing) { 04271 switch (nextthing[1]) { 04272 case '{': 04273 nextvar = nextthing; 04274 pos = nextvar - whereweare; 04275 break; 04276 case '[': 04277 nextexp = nextthing; 04278 pos = nextexp - whereweare; 04279 break; 04280 default: 04281 pos = 1; 04282 } 04283 } 04284 04285 if (pos) { 04286 /* Copy that many bytes */ 04287 ast_str_append_substr(buf, maxlen, whereweare, pos); 04288 04289 templ += pos; 04290 whereweare += pos; 04291 } 04292 04293 if (nextvar) { 04294 /* We have a variable. Find the start and end, and determine 04295 if we are going to have to recursively call ourselves on the 04296 contents */ 04297 vars = vare = nextvar + 2; 04298 brackets = 1; 04299 needsub = 0; 04300 04301 /* Find the end of it */ 04302 while (brackets && *vare) { 04303 if ((vare[0] == '$') && (vare[1] == '{')) { 04304 needsub++; 04305 } else if (vare[0] == '{') { 04306 brackets++; 04307 } else if (vare[0] == '}') { 04308 brackets--; 04309 } else if ((vare[0] == '$') && (vare[1] == '[')) 04310 needsub++; 04311 vare++; 04312 } 04313 if (brackets) 04314 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04315 len = vare - vars - 1; 04316 04317 /* Skip totally over variable string */ 04318 whereweare += (len + 3); 04319 04320 /* Store variable name (and truncate) */ 04321 ast_str_set_substr(&substr1, 0, vars, len); 04322 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04323 04324 /* Substitute if necessary */ 04325 if (needsub) { 04326 size_t used; 04327 if (!substr2) { 04328 substr2 = ast_str_create(16); 04329 } 04330 04331 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04332 finalvars = ast_str_buffer(substr2); 04333 } else { 04334 finalvars = ast_str_buffer(substr1); 04335 } 04336 04337 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04338 if (isfunction) { 04339 /* Evaluate function */ 04340 if (c || !headp) { 04341 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04342 } else { 04343 struct varshead old; 04344 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04345 if (bogus) { 04346 memcpy(&old, &bogus->varshead, sizeof(old)); 04347 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04348 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04349 /* Don't deallocate the varshead that was passed in */ 04350 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04351 ast_channel_unref(bogus); 04352 } else { 04353 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04354 } 04355 } 04356 ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)"); 04357 } else { 04358 /* Retrieve variable value */ 04359 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04360 cp4 = ast_str_buffer(substr3); 04361 } 04362 if (cp4) { 04363 ast_str_substring(substr3, offset, offset2); 04364 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04365 } 04366 } else if (nextexp) { 04367 /* We have an expression. Find the start and end, and determine 04368 if we are going to have to recursively call ourselves on the 04369 contents */ 04370 vars = vare = nextexp + 2; 04371 brackets = 1; 04372 needsub = 0; 04373 04374 /* Find the end of it */ 04375 while (brackets && *vare) { 04376 if ((vare[0] == '$') && (vare[1] == '[')) { 04377 needsub++; 04378 brackets++; 04379 vare++; 04380 } else if (vare[0] == '[') { 04381 brackets++; 04382 } else if (vare[0] == ']') { 04383 brackets--; 04384 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04385 needsub++; 04386 vare++; 04387 } 04388 vare++; 04389 } 04390 if (brackets) 04391 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04392 len = vare - vars - 1; 04393 04394 /* Skip totally over expression */ 04395 whereweare += (len + 3); 04396 04397 /* Store variable name (and truncate) */ 04398 ast_str_set_substr(&substr1, 0, vars, len); 04399 04400 /* Substitute if necessary */ 04401 if (needsub) { 04402 size_t used; 04403 if (!substr2) { 04404 substr2 = ast_str_create(16); 04405 } 04406 04407 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04408 finalvars = ast_str_buffer(substr2); 04409 } else { 04410 finalvars = ast_str_buffer(substr1); 04411 } 04412 04413 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04414 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04415 } 04416 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04417 } 04418 } 04419 *used = ast_str_strlen(*buf) - orig_size; 04420 ast_free(substr1); 04421 ast_free(substr2); 04422 ast_free(substr3); 04423 }
void ast_str_substitute_variables_varshead | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct varshead * | headp, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. |
Definition at line 4431 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().
04432 { 04433 size_t used; 04434 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04435 }
static const char* ast_str_substring | ( | struct ast_str * | value, | |
int | offset, | |||
int | length | |||
) | [static] |
Definition at line 3337 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().
03338 { 03339 int lr; /* length of the input string after the copy */ 03340 03341 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 03342 03343 /* Quick check if no need to do anything */ 03344 if (offset == 0 && length >= lr) /* take the whole string */ 03345 return ast_str_buffer(value); 03346 03347 if (offset < 0) { /* translate negative offset into positive ones */ 03348 offset = lr + offset; 03349 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03350 offset = 0; 03351 } 03352 03353 /* too large offset result in empty string so we know what to return */ 03354 if (offset >= lr) { 03355 ast_str_reset(value); 03356 return ast_str_buffer(value); 03357 } 03358 03359 if (offset > 0) { 03360 /* Go ahead and chop off the beginning */ 03361 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 03362 lr -= offset; 03363 } 03364 03365 if (length >= 0 && length < lr) { /* truncate if necessary */ 03366 char *tmp = ast_str_buffer(value); 03367 tmp[length] = '\0'; 03368 ast_str_update(value); 03369 } else if (length < 0) { 03370 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 03371 char *tmp = ast_str_buffer(value); 03372 tmp[lr + length] = '\0'; 03373 ast_str_update(value); 03374 } else { 03375 ast_str_reset(value); 03376 } 03377 } else { 03378 /* Nothing to do, but update the buffer length */ 03379 ast_str_update(value); 03380 } 03381 03382 return ast_str_buffer(value); 03383 }
int ast_thread_inhibit_escalations | ( | void | ) |
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.
Definition at line 4029 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by handle_tcptls_connection().
04030 { 04031 int *thread_inhibit_escalations; 04032 04033 thread_inhibit_escalations = ast_threadstorage_get( 04034 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04035 04036 if (thread_inhibit_escalations == NULL) { 04037 ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n"); 04038 return -1; 04039 } 04040 04041 *thread_inhibit_escalations = 1; 04042 return 0; 04043 }
int ast_unlock_context | ( | struct ast_context * | con | ) |
Unlocks | the given context |
con | context to unlock |
0 | on success | |
-1 | on failure |
Definition at line 10975 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().
10976 { 10977 return ast_rwlock_unlock(&con->lock); 10978 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10957 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().
10958 { 10959 return ast_mutex_unlock(&conlock); 10960 }
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 7710 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().
07711 { 07712 struct ast_app *tmp; 07713 07714 AST_RWLIST_WRLOCK(&apps); 07715 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 07716 if (!strcasecmp(app, tmp->name)) { 07717 unreference_cached_app(tmp); 07718 AST_RWLIST_REMOVE_CURRENT(list); 07719 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 07720 ast_string_field_free_memory(tmp); 07721 ast_free(tmp); 07722 break; 07723 } 07724 } 07725 AST_RWLIST_TRAVERSE_SAFE_END; 07726 AST_RWLIST_UNLOCK(&apps); 07727 07728 return tmp ? 0 : -1; 07729 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6462 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06463 { 06464 AST_RWLIST_WRLOCK(&switches); 06465 AST_RWLIST_REMOVE(&switches, sw, list); 06466 AST_RWLIST_UNLOCK(&switches); 06467 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) | [read] |
Definition at line 11089 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 11122 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().
11124 { 11125 if (!ip) 11126 return con ? con->ignorepats : NULL; 11127 else 11128 return ip->next; 11129 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 11113 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 11098 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().
11100 { 11101 if (!sw) 11102 return con ? AST_LIST_FIRST(&con->alts) : NULL; 11103 else 11104 return AST_LIST_NEXT(sw, list); 11105 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 11084 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 11107 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().
11109 { 11110 return priority ? priority->peer : exten; 11111 }
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 10965 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().
10966 { 10967 return ast_rwlock_wrlock(&con->lock); 10968 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10947 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().
10948 { 10949 return ast_mutex_lock(&conlock); 10950 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 9290 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().
09291 { 09292 struct async_stat *as = data; 09293 struct ast_channel *chan = as->chan; 09294 int timeout = as->timeout; 09295 int res; 09296 struct ast_frame *f; 09297 struct ast_app *app; 09298 struct timeval start = ast_tvnow(); 09299 int ms; 09300 09301 while ((ms = ast_remaining_ms(start, timeout)) && 09302 chan->_state != AST_STATE_UP) { 09303 res = ast_waitfor(chan, ms); 09304 if (res < 1) 09305 break; 09306 09307 f = ast_read(chan); 09308 if (!f) 09309 break; 09310 if (f->frametype == AST_FRAME_CONTROL) { 09311 if ((f->subclass.integer == AST_CONTROL_BUSY) || 09312 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 09313 ast_frfree(f); 09314 break; 09315 } 09316 } 09317 ast_frfree(f); 09318 } 09319 if (chan->_state == AST_STATE_UP) { 09320 if (!ast_strlen_zero(as->app)) { 09321 app = pbx_findapp(as->app); 09322 if (app) { 09323 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 09324 pbx_exec(chan, app, as->appdata); 09325 } else 09326 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 09327 } else { 09328 if (!ast_strlen_zero(as->context)) 09329 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 09330 if (!ast_strlen_zero(as->exten)) 09331 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 09332 if (as->priority > 0) 09333 chan->priority = as->priority; 09334 /* Run the PBX */ 09335 if (ast_pbx_run(chan)) { 09336 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 09337 } else { 09338 /* PBX will have taken care of this */ 09339 chan = NULL; 09340 } 09341 } 09342 } 09343 ast_free(as); 09344 if (chan) 09345 ast_hangup(chan); 09346 return NULL; 09347 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1656 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().
01657 { 01658 char extenstr[40]; 01659 struct ast_str *my_prefix = ast_str_alloca(1024); 01660 01661 extenstr[0] = '\0'; 01662 01663 if (node->exten) { 01664 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01665 } 01666 01667 if (strlen(node->x) > 1) { 01668 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01669 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01670 node->exten ? node->exten->exten : "", extenstr); 01671 } else { 01672 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01673 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01674 node->exten ? node->exten->exten : "", extenstr); 01675 } 01676 01677 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01678 01679 if (node->next_char) 01680 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01681 01682 if (node->alt_char) 01683 cli_match_char_tree(node->alt_char, prefix, fd); 01684 }
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 5451 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().
05452 { 05453 int digit; 05454 05455 buf[pos] = '\0'; /* make sure it is properly terminated */ 05456 while (ast_matchmore_extension(c, c->context, buf, 1, 05457 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05458 /* As long as we're willing to wait, and as long as it's not defined, 05459 keep reading digits until we can't possibly get a right answer anymore. */ 05460 digit = ast_waitfordigit(c, waittime); 05461 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05462 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05463 } else { 05464 if (!digit) /* No entry */ 05465 break; 05466 if (digit < 0) /* Error, maybe a hangup */ 05467 return -1; 05468 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 05469 buf[pos++] = digit; 05470 buf[pos] = '\0'; 05471 } 05472 waittime = c->pbx->dtimeoutms; 05473 } 05474 } 05475 return 0; 05476 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 1083 of file pbx.c.
Referenced by get_pattern_node().
static char* complete_core_show_hint | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
autocomplete for CLI command 'core show hint'
Definition at line 6654 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().
06655 { 06656 struct ast_hint *hint; 06657 char *ret = NULL; 06658 int which = 0; 06659 int wordlen; 06660 struct ao2_iterator i; 06661 06662 if (pos != 3) 06663 return NULL; 06664 06665 wordlen = strlen(word); 06666 06667 /* walk through all hints */ 06668 i = ao2_iterator_init(hints, 0); 06669 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06670 ao2_lock(hint); 06671 if (!hint->exten) { 06672 /* The extension has already been destroyed */ 06673 ao2_unlock(hint); 06674 continue; 06675 } 06676 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 06677 ret = ast_strdup(ast_get_extension_name(hint->exten)); 06678 ao2_unlock(hint); 06679 ao2_ref(hint, -1); 06680 break; 06681 } 06682 ao2_unlock(hint); 06683 } 06684 ao2_iterator_destroy(&i); 06685 06686 return ret; 06687 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 6870 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().
06872 { 06873 struct ast_context *c = NULL; 06874 char *ret = NULL; 06875 int which = 0; 06876 int wordlen; 06877 06878 /* we are do completion of [exten@]context on second position only */ 06879 if (pos != 2) 06880 return NULL; 06881 06882 ast_rdlock_contexts(); 06883 06884 wordlen = strlen(word); 06885 06886 /* walk through all contexts and return the n-th match */ 06887 while ( (c = ast_walk_contexts(c)) ) { 06888 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06889 ret = ast_strdup(ast_get_context_name(c)); 06890 break; 06891 } 06892 } 06893 06894 ast_unlock_contexts(); 06895 06896 return ret; 06897 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7851 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().
07852 { 07853 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 07854 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 07855 struct ast_hashtab_iter *exten_iter; 07856 struct ast_hashtab_iter *prio_iter; 07857 int insert_count = 0; 07858 int first = 1; 07859 07860 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 07861 the current registrar, and copy them to the new context. If the new context does not 07862 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 07863 only create the empty matching context if the old one meets the criteria */ 07864 07865 if (context->root_table) { 07866 exten_iter = ast_hashtab_start_traversal(context->root_table); 07867 while ((exten_item=ast_hashtab_next(exten_iter))) { 07868 if (new) { 07869 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 07870 } else { 07871 new_exten_item = NULL; 07872 } 07873 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07874 while ((prio_item=ast_hashtab_next(prio_iter))) { 07875 int res1; 07876 char *dupdstr; 07877 07878 if (new_exten_item) { 07879 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 07880 } else { 07881 new_prio_item = NULL; 07882 } 07883 if (strcmp(prio_item->registrar,registrar) == 0) { 07884 continue; 07885 } 07886 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 07887 if (!new) { 07888 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 */ 07889 } 07890 07891 /* copy in the includes, switches, and ignorepats */ 07892 if (first) { /* but, only need to do this once */ 07893 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07894 first = 0; 07895 } 07896 07897 if (!new) { 07898 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07899 ast_hashtab_end_traversal(prio_iter); 07900 ast_hashtab_end_traversal(exten_iter); 07901 return; /* no sense continuing. */ 07902 } 07903 /* we will not replace existing entries in the new context with stuff from the old context. 07904 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07905 07906 dupdstr = ast_strdup(prio_item->data); 07907 07908 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07909 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07910 if (!res1 && new_exten_item && new_prio_item){ 07911 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07912 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07913 } else { 07914 /* 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, 07915 and no double frees take place, either! */ 07916 insert_count++; 07917 } 07918 } 07919 ast_hashtab_end_traversal(prio_iter); 07920 } 07921 ast_hashtab_end_traversal(exten_iter); 07922 } else if (new) { 07923 /* If the context existed but had no extensions, we still want to merge 07924 * the includes, switches and ignore patterns. 07925 */ 07926 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07927 } 07928 07929 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07930 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07931 /* we could have given it the registrar of the other module who incremented the refcount, 07932 but that's not available, so we give it the registrar we know about */ 07933 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07934 07935 /* copy in the includes, switches, and ignorepats */ 07936 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07937 } 07938 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7818 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().
07819 { 07820 struct ast_include *i; 07821 struct ast_ignorepat *ip; 07822 struct ast_sw *sw; 07823 07824 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); 07825 /* copy in the includes, switches, and ignorepats */ 07826 /* walk through includes */ 07827 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 07828 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 07829 continue; /* not mine */ 07830 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 07831 } 07832 07833 /* walk through switches */ 07834 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 07835 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 07836 continue; /* not mine */ 07837 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)); 07838 } 07839 07840 /* walk thru ignorepats ... */ 07841 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 07842 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 07843 continue; /* not mine */ 07844 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 07845 } 07846 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2278 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().
02279 { 02280 struct ast_hashtab_iter *t1; 02281 struct ast_exten *e1; 02282 #ifdef NEED_DEBUG 02283 int biggest_bucket, resizes, numobjs, numbucks; 02284 02285 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02286 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02287 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02288 numobjs, numbucks, biggest_bucket, resizes); 02289 #endif 02290 t1 = ast_hashtab_start_traversal(con->root_table); 02291 while ((e1 = ast_hashtab_next(t1))) { 02292 if (e1->exten) { 02293 add_exten_to_pattern_tree(con, e1, 0); 02294 } else { 02295 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02296 } 02297 } 02298 ast_hashtab_end_traversal(t1); 02299 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 5842 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().
05843 { 05844 ast_mutex_lock(&maxcalllock); 05845 if (countcalls > 0) 05846 countcalls--; 05847 ast_mutex_unlock(&maxcalllock); 05848 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 5850 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().
05851 { 05852 if (e->priority == PRIORITY_HINT) 05853 ast_remove_hint(e); 05854 05855 if (e->peer_table) 05856 ast_hashtab_destroy(e->peer_table,0); 05857 if (e->peer_label_table) 05858 ast_hashtab_destroy(e->peer_label_table, 0); 05859 if (e->datad) 05860 e->datad(e->data); 05861 ast_free(e); 05862 }
static void destroy_hint | ( | void * | obj | ) | [static] |
Definition at line 5212 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().
05213 { 05214 struct ast_hint *hint = obj; 05215 05216 if (hint->callbacks) { 05217 struct ast_state_cb *state_cb; 05218 const char *context_name; 05219 const char *exten_name; 05220 05221 if (hint->exten) { 05222 context_name = ast_get_context_name(ast_get_extension_context(hint->exten)); 05223 exten_name = ast_get_extension_name(hint->exten); 05224 hint->exten = NULL; 05225 } else { 05226 /* The extension has already been destroyed */ 05227 context_name = hint->context_name; 05228 exten_name = hint->exten_name; 05229 } 05230 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 05231 /* Notify with -1 and remove all callbacks */ 05232 /* NOTE: The casts will not be needed for v1.10 and later */ 05233 state_cb->change_cb((char *) context_name, (char *) exten_name, 05234 AST_EXTENSION_DEACTIVATED, state_cb->data); 05235 ao2_ref(state_cb, -1); 05236 } 05237 ao2_ref(hint->callbacks, -1); 05238 } 05239 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2301 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().
02302 { 02303 /* destroy all the alternates */ 02304 if (pattern_tree->alt_char) { 02305 destroy_pattern_tree(pattern_tree->alt_char); 02306 pattern_tree->alt_char = 0; 02307 } 02308 /* destroy all the nexts */ 02309 if (pattern_tree->next_char) { 02310 destroy_pattern_tree(pattern_tree->next_char); 02311 pattern_tree->next_char = 0; 02312 } 02313 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02314 ast_free(pattern_tree); 02315 }
static void destroy_state_cb | ( | void * | doomed | ) | [static] |
Definition at line 5043 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().
05044 { 05045 struct ast_state_cb *state_cb = doomed; 05046 05047 if (state_cb->destroy_cb) { 05048 state_cb->destroy_cb(state_cb->id, state_cb->data); 05049 } 05050 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 10815 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().
10816 { 10817 const char *device; 10818 struct statechange *sc; 10819 10820 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 10821 if (ast_strlen_zero(device)) { 10822 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 10823 return; 10824 } 10825 10826 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 10827 return; 10828 strcpy(sc->dev, device); 10829 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 10830 ast_free(sc); 10831 } 10832 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3528 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03529 { 03530 struct pbx_exception *exception = data; 03531 ast_string_field_free_memory(exception); 03532 ast_free(exception); 03533 }
static int ext_cmp | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2648 of file pbx.c.
References ext_cmp_exten(), and ext_cmp_pattern().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02649 { 02650 /* Make sure non-pattern extens come first. */ 02651 if (left[0] != '_') { 02652 if (right[0] == '_') { 02653 return -1; 02654 } 02655 /* Compare two non-pattern extens. */ 02656 return ext_cmp_exten(left, right); 02657 } 02658 if (right[0] != '_') { 02659 return 1; 02660 } 02661 02662 /* 02663 * OK, we need full pattern sorting routine. 02664 * 02665 * Skip past the underscores 02666 */ 02667 return ext_cmp_pattern(left + 1, right + 1); 02668 }
static int ext_cmp_exten | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2398 of file pbx.c.
Referenced by _extension_match_core(), and ext_cmp().
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 cmp = *left - *right; 02412 if (cmp) { 02413 break; 02414 } 02415 if (!*left) { 02416 /* 02417 * Get here only if both strings ended at the same time. cmp 02418 * would be non-zero if only one string ended. 02419 */ 02420 break; 02421 } 02422 ++left; 02423 ++right; 02424 } 02425 return cmp; 02426 }
static int ext_cmp_exten_partial | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2355 of file pbx.c.
Referenced by _extension_match_core().
02356 { 02357 int cmp; 02358 02359 for (;;) { 02360 /* Ignore '-' chars as eye candy fluff. */ 02361 while (*left == '-') { 02362 ++left; 02363 } 02364 while (*right == '-') { 02365 ++right; 02366 } 02367 02368 if (!*right) { 02369 /* 02370 * Right ended first for partial match or both ended at the same 02371 * time for a match. 02372 */ 02373 cmp = 0; 02374 break; 02375 } 02376 02377 cmp = *left - *right; 02378 if (cmp) { 02379 break; 02380 } 02381 ++left; 02382 ++right; 02383 } 02384 return cmp; 02385 }
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 2600 of file pbx.c.
References ARRAY_LEN, and ext_cmp_pattern_pos().
Referenced by _extension_match_core(), and ext_cmp().
02601 { 02602 int cmp; 02603 int left_pos; 02604 int right_pos; 02605 02606 for (;;) { 02607 unsigned char left_bitwise[32] = { 0, }; 02608 unsigned char right_bitwise[32] = { 0, }; 02609 02610 left_pos = ext_cmp_pattern_pos(&left, left_bitwise); 02611 right_pos = ext_cmp_pattern_pos(&right, right_bitwise); 02612 cmp = left_pos - right_pos; 02613 if (!cmp) { 02614 /* 02615 * Are the character sets different, even though they score the same? 02616 * 02617 * Note: Must swap left and right to get the sense of the 02618 * comparison correct. Otherwise, we would need to multiply by 02619 * -1 instead. 02620 */ 02621 cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise)); 02622 } 02623 if (cmp) { 02624 break; 02625 } 02626 if (!left) { 02627 /* 02628 * Get here only if both patterns ended at the same time. cmp 02629 * would be non-zero if only one pattern ended. 02630 */ 02631 break; 02632 } 02633 } 02634 return cmp; 02635 }
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 2485 of file pbx.c.
References ast_log(), BITS_PER, and LOG_WARNING.
Referenced by ext_cmp_pattern().
02486 { 02487 #define BITS_PER 8 /* Number of bits per unit (byte). */ 02488 unsigned char c; 02489 unsigned char cmin; 02490 int count; 02491 const char *end; 02492 02493 do { 02494 /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */ 02495 do { 02496 c = *(*p)++; 02497 } while (c == '-'); 02498 02499 /* always return unless we have a set of chars */ 02500 switch (c) { 02501 default: 02502 /* ordinary character */ 02503 bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER)); 02504 return 0x0100 | c; 02505 02506 case 'n': 02507 case 'N': 02508 /* 2..9 */ 02509 bitwise[6] = 0x3f; 02510 bitwise[7] = 0xc0; 02511 return 0x0800 | '2'; 02512 02513 case 'x': 02514 case 'X': 02515 /* 0..9 */ 02516 bitwise[6] = 0xff; 02517 bitwise[7] = 0xc0; 02518 return 0x0A00 | '0'; 02519 02520 case 'z': 02521 case 'Z': 02522 /* 1..9 */ 02523 bitwise[6] = 0x7f; 02524 bitwise[7] = 0xc0; 02525 return 0x0900 | '1'; 02526 02527 case '.': 02528 /* wildcard */ 02529 return 0x18000; 02530 02531 case '!': 02532 /* earlymatch */ 02533 return 0x28000; /* less specific than '.' */ 02534 02535 case '\0': 02536 /* empty string */ 02537 *p = NULL; 02538 return 0x30000; 02539 02540 case '[': 02541 /* char set */ 02542 break; 02543 } 02544 /* locate end of set */ 02545 end = strchr(*p, ']'); 02546 02547 if (!end) { 02548 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02549 return 0x40000; /* XXX make this entry go last... */ 02550 } 02551 02552 count = 0; 02553 cmin = 0xFF; 02554 for (; *p < end; ++*p) { 02555 unsigned char c1; /* first char in range */ 02556 unsigned char c2; /* last char in range */ 02557 02558 c1 = (*p)[0]; 02559 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02560 c2 = (*p)[2]; 02561 *p += 2; /* skip a total of 3 chars */ 02562 } else { /* individual character */ 02563 c2 = c1; 02564 } 02565 if (c1 < cmin) { 02566 cmin = c1; 02567 } 02568 for (; c1 <= c2; ++c1) { 02569 unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER)); 02570 02571 /* 02572 * Note: If two character sets score the same, the one with the 02573 * lowest ASCII values will compare as coming first. Must fill 02574 * in most significant bits for lower ASCII values to accomplish 02575 * the desired sort order. 02576 */ 02577 if (!(bitwise[c1 / BITS_PER] & mask)) { 02578 /* Add the character to the set. */ 02579 bitwise[c1 / BITS_PER] |= mask; 02580 count += 0x100; 02581 } 02582 } 02583 } 02584 ++*p; 02585 } while (!count);/* While the char set was empty. */ 02586 return count | cmin; 02587 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 8832 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
08833 { 08834 int count = 0; 08835 int insquares = 0; 08836 08837 while (*src && (count < len - 1)) { 08838 if (*src == '[') { 08839 insquares = 1; 08840 } else if (*src == ']') { 08841 insquares = 0; 08842 } else if (*src == ' ' && !insquares) { 08843 src++; 08844 continue; 08845 } 08846 *dst = *src; 08847 dst++; 08848 src++; 08849 count++; 08850 } 08851 *dst = '\0'; 08852 08853 return count; 08854 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2887 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().
02888 { 02889 int i; 02890 static int prof_id = -2; /* marker for 'unallocated' id */ 02891 if (prof_id == -2) { 02892 prof_id = ast_add_profile("ext_match", 0); 02893 } 02894 ast_mark(prof_id, 1); 02895 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode); 02896 ast_mark(prof_id, 0); 02897 return i; 02898 }
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 5976 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05977 { 05978 struct fake_context item; 05979 05980 ast_copy_string(item.name, context, sizeof(item.name)); 05981 05982 return ast_hashtab_lookup(contexts_table, &item); 05983 }
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 5990 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().
05991 { 05992 struct ast_context *c; 05993 struct fake_context item; 05994 05995 ast_copy_string(item.name, context, sizeof(item.name)); 05996 05997 ast_rdlock_contexts(); 05998 c = ast_hashtab_lookup(contexts_table, &item); 05999 if (!c) { 06000 ast_unlock_contexts(); 06001 } 06002 06003 return c; 06004 }
static int find_hint_by_cb_id | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Remove a watcher from the callback list.
Definition at line 5147 of file pbx.c.
References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.
Referenced by ast_extension_state_del().
static char* func_args | ( | char * | function | ) | [static] |
return a pointer to the arguments of the function, and terminates the function name with '\0'
Definition at line 3998 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03999 { 04000 char *args = strchr(function, '('); 04001 04002 if (!args) { 04003 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 04004 } else { 04005 char *p; 04006 *args++ = '\0'; 04007 if ((p = strrchr(args, ')'))) { 04008 *p = '\0'; 04009 } else { 04010 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 04011 } 04012 } 04013 return args; 04014 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1686 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.
01687 { 01688 /* find the exten at the end of the rope */ 01689 struct match_char *node2 = node; 01690 01691 for (node2 = node; node2; node2 = node2->next_char) { 01692 if (node2->exten) { 01693 #ifdef NEED_DEBUG_HERE 01694 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01695 #endif 01696 return node2->exten; 01697 } 01698 } 01699 #ifdef NEED_DEBUG_HERE 01700 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01701 #endif 01702 return 0; 01703 }
static const char* get_pattern_node | ( | struct pattern_node * | node, | |
const char * | src, | |||
int | pattern, | |||
const char * | extenbuf | |||
) | [static] |
Definition at line 2035 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().
02036 { 02037 #define INC_DST_OVERFLOW_CHECK \ 02038 do { \ 02039 if (dst - node->buf < sizeof(node->buf) - 1) { \ 02040 ++dst; \ 02041 } else { \ 02042 overflow = 1; \ 02043 } \ 02044 } while (0) 02045 02046 node->specif = 0; 02047 node->buf[0] = '\0'; 02048 while (*src) { 02049 if (*src == '[' && pattern) { 02050 char *dst = node->buf; 02051 const char *src_next; 02052 int length; 02053 int overflow = 0; 02054 02055 /* get past the '[' */ 02056 ++src; 02057 for (;;) { 02058 if (*src == '\\') { 02059 /* Escaped character. */ 02060 ++src; 02061 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') { 02062 *dst = *src++; 02063 INC_DST_OVERFLOW_CHECK; 02064 } 02065 } else if (*src == '-') { 02066 unsigned char first; 02067 unsigned char last; 02068 02069 src_next = src; 02070 first = *(src_next - 1); 02071 last = *++src_next; 02072 02073 if (last == '\\') { 02074 /* Escaped character. */ 02075 last = *++src_next; 02076 } 02077 02078 /* Possible char range. */ 02079 if (node->buf[0] && last) { 02080 /* Expand the char range. */ 02081 while (++first <= last) { 02082 *dst = first; 02083 INC_DST_OVERFLOW_CHECK; 02084 } 02085 src = src_next + 1; 02086 } else { 02087 /* 02088 * There was no left or right char for the range. 02089 * It is just a '-'. 02090 */ 02091 *dst = *src++; 02092 INC_DST_OVERFLOW_CHECK; 02093 } 02094 } else if (*src == '\0') { 02095 ast_log(LOG_WARNING, 02096 "A matching ']' was not found for '[' in exten pattern '%s'\n", 02097 extenbuf); 02098 break; 02099 } else if (*src == ']') { 02100 ++src; 02101 break; 02102 } else { 02103 *dst = *src++; 02104 INC_DST_OVERFLOW_CHECK; 02105 } 02106 } 02107 /* null terminate the exploded range */ 02108 *dst = '\0'; 02109 02110 if (overflow) { 02111 ast_log(LOG_ERROR, 02112 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n", 02113 extenbuf); 02114 node->buf[0] = '\0'; 02115 continue; 02116 } 02117 02118 /* Sort the characters in character set. */ 02119 length = strlen(node->buf); 02120 if (!length) { 02121 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n", 02122 extenbuf); 02123 node->buf[0] = '\0'; 02124 continue; 02125 } 02126 qsort(node->buf, length, 1, compare_char); 02127 02128 /* Remove duplicate characters from character set. */ 02129 dst = node->buf; 02130 src_next = node->buf; 02131 while (*src_next++) { 02132 if (*dst != *src_next) { 02133 *++dst = *src_next; 02134 } 02135 } 02136 02137 length = strlen(node->buf); 02138 length <<= 8; 02139 node->specif = length | (unsigned char) node->buf[0]; 02140 break; 02141 } else if (*src == '-') { 02142 /* Skip dashes in all extensions. */ 02143 ++src; 02144 } else { 02145 if (*src == '\\') { 02146 /* 02147 * XXX The escape character here does not remove any special 02148 * meaning to characters except the '[', '\\', and '-' 02149 * characters since they are special only in this function. 02150 */ 02151 node->buf[0] = *++src; 02152 if (!node->buf[0]) { 02153 break; 02154 } 02155 } else { 02156 node->buf[0] = *src; 02157 if (pattern) { 02158 /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02159 if (node->buf[0] == 'n') { 02160 node->buf[0] = 'N'; 02161 } else if (node->buf[0] == 'x') { 02162 node->buf[0] = 'X'; 02163 } else if (node->buf[0] == 'z') { 02164 node->buf[0] = 'Z'; 02165 } 02166 } 02167 } 02168 node->buf[1] = '\0'; 02169 node->specif = 1; 02170 ++src; 02171 break; 02172 } 02173 } 02174 return src; 02175 02176 #undef INC_DST_OVERFLOW_CHECK 02177 }
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 8187 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and lookup_name().
Referenced by ast_build_timing().
08188 { 08189 int start, end; /* start and ending position */ 08190 unsigned int mask = 0; 08191 char *part; 08192 08193 /* Check for whole range */ 08194 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 08195 return (1 << max) - 1; 08196 } 08197 08198 while ((part = strsep(&src, "&"))) { 08199 /* Get start and ending position */ 08200 char *endpart = strchr(part, '-'); 08201 if (endpart) { 08202 *endpart++ = '\0'; 08203 } 08204 /* Find the start */ 08205 if ((start = lookup_name(part, names, max)) < 0) { 08206 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 08207 continue; 08208 } 08209 if (endpart) { /* find end of range */ 08210 if ((end = lookup_name(endpart, names, max)) < 0) { 08211 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 08212 continue; 08213 } 08214 } else { 08215 end = start; 08216 } 08217 /* Fill the mask. Remember that ranges are cyclic */ 08218 mask |= (1 << end); /* initialize with last element */ 08219 while (start != end) { 08220 mask |= (1 << start); 08221 if (++start >= max) { 08222 start = 0; 08223 } 08224 } 08225 } 08226 return mask; 08227 }
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 8230 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
08231 { 08232 char *endpart, *part; 08233 int x; 08234 int st_h, st_m; 08235 int endh, endm; 08236 int minute_start, minute_end; 08237 08238 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 08239 memset(i->minmask, 0, sizeof(i->minmask)); 08240 08241 /* 1-minute per bit */ 08242 /* Star is all times */ 08243 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 08244 /* 48, because each hour takes 2 integers; 30 bits each */ 08245 for (x = 0; x < 48; x++) { 08246 i->minmask[x] = 0x3fffffff; /* 30 bits */ 08247 } 08248 return; 08249 } 08250 /* Otherwise expect a range */ 08251 while ((part = strsep(×, "&"))) { 08252 if (!(endpart = strchr(part, '-'))) { 08253 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 08254 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 08255 continue; 08256 } 08257 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 08258 continue; 08259 } 08260 *endpart++ = '\0'; 08261 /* why skip non digits? Mostly to skip spaces */ 08262 while (*endpart && !isdigit(*endpart)) { 08263 endpart++; 08264 } 08265 if (!*endpart) { 08266 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 08267 continue; 08268 } 08269 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 08270 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 08271 continue; 08272 } 08273 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 08274 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 08275 continue; 08276 } 08277 minute_start = st_h * 60 + st_m; 08278 minute_end = endh * 60 + endm; 08279 /* Go through the time and enable each appropriate bit */ 08280 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 08281 i->minmask[x / 30] |= (1 << (x % 30)); 08282 } 08283 /* Do the last one */ 08284 i->minmask[x / 30] |= (1 << (x % 30)); 08285 } 08286 /* All done */ 08287 return; 08288 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 7201 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.
07202 { 07203 char *exten = NULL, *context = NULL; 07204 /* Variables used for different counters */ 07205 struct dialplan_counters counters; 07206 const char *incstack[AST_PBX_MAX_STACK]; 07207 07208 switch (cmd) { 07209 case CLI_INIT: 07210 e->command = "dialplan debug"; 07211 e->usage = 07212 "Usage: dialplan debug [context]\n" 07213 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 07214 return NULL; 07215 case CLI_GENERATE: 07216 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 07217 } 07218 07219 memset(&counters, 0, sizeof(counters)); 07220 07221 if (a->argc != 2 && a->argc != 3) 07222 return CLI_SHOWUSAGE; 07223 07224 /* we obtain [exten@]context? if yes, split them ... */ 07225 /* note: we ignore the exten totally here .... */ 07226 if (a->argc == 3) { 07227 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 07228 context = ast_strdupa(a->argv[2]); 07229 exten = strsep(&context, "@"); 07230 /* change empty strings to NULL */ 07231 if (ast_strlen_zero(exten)) 07232 exten = NULL; 07233 } else { /* no '@' char, only context given */ 07234 context = ast_strdupa(a->argv[2]); 07235 } 07236 if (ast_strlen_zero(context)) 07237 context = NULL; 07238 } 07239 /* else Show complete dial plan, context and exten are NULL */ 07240 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 07241 07242 /* check for input failure and throw some error messages */ 07243 if (context && !counters.context_existence) { 07244 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 07245 return CLI_FAILURE; 07246 } 07247 07248 07249 ast_cli(a->fd,"-= %d %s. =-\n", 07250 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 07251 07252 /* everything ok */ 07253 return CLI_SUCCESS; 07254 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7574 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.
07575 { 07576 struct ast_channel *chan; 07577 const char *chan_name, *var_name, *var_value; 07578 07579 switch (cmd) { 07580 case CLI_INIT: 07581 e->command = "dialplan set chanvar"; 07582 e->usage = 07583 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 07584 " Set channel variable <varname> to <value>\n"; 07585 return NULL; 07586 case CLI_GENERATE: 07587 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07588 } 07589 07590 if (a->argc != e->args + 3) 07591 return CLI_SHOWUSAGE; 07592 07593 chan_name = a->argv[e->args]; 07594 var_name = a->argv[e->args + 1]; 07595 var_value = a->argv[e->args + 2]; 07596 07597 if (!(chan = ast_channel_get_by_name(chan_name))) { 07598 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 07599 return CLI_FAILURE; 07600 } 07601 07602 pbx_builtin_setvar_helper(chan, var_name, var_value); 07603 07604 chan = ast_channel_unref(chan); 07605 07606 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 07607 07608 return CLI_SUCCESS; 07609 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7611 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.
07612 { 07613 int oldval = 0; 07614 07615 switch (cmd) { 07616 case CLI_INIT: 07617 e->command = "dialplan set extenpatternmatchnew true"; 07618 e->usage = 07619 "Usage: dialplan set extenpatternmatchnew true|false\n" 07620 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07621 return NULL; 07622 case CLI_GENERATE: 07623 return NULL; 07624 } 07625 07626 if (a->argc != 4) 07627 return CLI_SHOWUSAGE; 07628 07629 oldval = pbx_set_extenpatternmatchnew(1); 07630 07631 if (oldval) 07632 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07633 else 07634 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07635 07636 return CLI_SUCCESS; 07637 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7552 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.
07553 { 07554 switch (cmd) { 07555 case CLI_INIT: 07556 e->command = "dialplan set global"; 07557 e->usage = 07558 "Usage: dialplan set global <name> <value>\n" 07559 " Set global dialplan variable <name> to <value>\n"; 07560 return NULL; 07561 case CLI_GENERATE: 07562 return NULL; 07563 } 07564 07565 if (a->argc != e->args + 2) 07566 return CLI_SHOWUSAGE; 07567 07568 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 07569 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 07570 07571 return CLI_SUCCESS; 07572 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6548 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.
06549 { 06550 struct ast_app *aa; 06551 int app, no_registered_app = 1; 06552 06553 switch (cmd) { 06554 case CLI_INIT: 06555 e->command = "core show application"; 06556 e->usage = 06557 "Usage: core show application <application> [<application> [<application> [...]]]\n" 06558 " Describes a particular application.\n"; 06559 return NULL; 06560 case CLI_GENERATE: 06561 /* 06562 * There is a possibility to show informations about more than one 06563 * application at one time. You can type 'show application Dial Echo' and 06564 * you will see informations about these two applications ... 06565 */ 06566 return ast_complete_applications(a->line, a->word, a->n); 06567 } 06568 06569 if (a->argc < 4) { 06570 return CLI_SHOWUSAGE; 06571 } 06572 06573 AST_RWLIST_RDLOCK(&apps); 06574 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06575 /* Check for each app that was supplied as an argument */ 06576 for (app = 3; app < a->argc; app++) { 06577 if (strcasecmp(aa->name, a->argv[app])) { 06578 continue; 06579 } 06580 06581 /* We found it! */ 06582 no_registered_app = 0; 06583 06584 print_app_docs(aa, a->fd); 06585 } 06586 } 06587 AST_RWLIST_UNLOCK(&apps); 06588 06589 /* we found at least one app? no? */ 06590 if (no_registered_app) { 06591 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 06592 return CLI_FAILURE; 06593 } 06594 06595 return CLI_SUCCESS; 06596 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6784 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.
06785 { 06786 struct ast_app *aa; 06787 int like = 0, describing = 0; 06788 int total_match = 0; /* Number of matches in like clause */ 06789 int total_apps = 0; /* Number of apps registered */ 06790 static const char * const choices[] = { "like", "describing", NULL }; 06791 06792 switch (cmd) { 06793 case CLI_INIT: 06794 e->command = "core show applications [like|describing]"; 06795 e->usage = 06796 "Usage: core show applications [{like|describing} <text>]\n" 06797 " List applications which are currently available.\n" 06798 " If 'like', <text> will be a substring of the app name\n" 06799 " If 'describing', <text> will be a substring of the description\n"; 06800 return NULL; 06801 case CLI_GENERATE: 06802 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 06803 } 06804 06805 AST_RWLIST_RDLOCK(&apps); 06806 06807 if (AST_RWLIST_EMPTY(&apps)) { 06808 ast_cli(a->fd, "There are no registered applications\n"); 06809 AST_RWLIST_UNLOCK(&apps); 06810 return CLI_SUCCESS; 06811 } 06812 06813 /* core list applications like <keyword> */ 06814 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 06815 like = 1; 06816 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 06817 describing = 1; 06818 } 06819 06820 /* core list applications describing <keyword1> [<keyword2>] [...] */ 06821 if ((!like) && (!describing)) { 06822 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 06823 } else { 06824 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 06825 } 06826 06827 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06828 int printapp = 0; 06829 total_apps++; 06830 if (like) { 06831 if (strcasestr(aa->name, a->argv[4])) { 06832 printapp = 1; 06833 total_match++; 06834 } 06835 } else if (describing) { 06836 if (aa->description) { 06837 /* Match all words on command line */ 06838 int i; 06839 printapp = 1; 06840 for (i = 4; i < a->argc; i++) { 06841 if (!strcasestr(aa->description, a->argv[i])) { 06842 printapp = 0; 06843 } else { 06844 total_match++; 06845 } 06846 } 06847 } 06848 } else { 06849 printapp = 1; 06850 } 06851 06852 if (printapp) { 06853 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 06854 } 06855 } 06856 if ((!like) && (!describing)) { 06857 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 06858 } else { 06859 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 06860 } 06861 06862 AST_RWLIST_UNLOCK(&apps); 06863 06864 return CLI_SUCCESS; 06865 }
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 7517 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.
07518 { 07519 struct ast_channel *chan = NULL; 07520 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 07521 07522 switch (cmd) { 07523 case CLI_INIT: 07524 e->command = "dialplan show chanvar"; 07525 e->usage = 07526 "Usage: dialplan show chanvar <channel>\n" 07527 " List current channel variables and their values\n"; 07528 return NULL; 07529 case CLI_GENERATE: 07530 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07531 } 07532 07533 if (a->argc != e->args + 1) 07534 return CLI_SHOWUSAGE; 07535 07536 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 07537 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 07538 return CLI_FAILURE; 07539 } 07540 07541 pbx_builtin_serialize_variables(chan, &vars); 07542 07543 if (ast_str_strlen(vars)) { 07544 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 07545 } 07546 07547 chan = ast_channel_unref(chan); 07548 07549 return CLI_SUCCESS; 07550 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7134 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, 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.
07135 { 07136 char *exten = NULL, *context = NULL; 07137 /* Variables used for different counters */ 07138 struct dialplan_counters counters; 07139 const char *incstack[AST_PBX_MAX_STACK]; 07140 07141 switch (cmd) { 07142 case CLI_INIT: 07143 e->command = "dialplan show"; 07144 e->usage = 07145 "Usage: dialplan show [[exten@]context]\n" 07146 " Show dialplan\n"; 07147 return NULL; 07148 case CLI_GENERATE: 07149 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 07150 } 07151 07152 memset(&counters, 0, sizeof(counters)); 07153 07154 if (a->argc != 2 && a->argc != 3) 07155 return CLI_SHOWUSAGE; 07156 07157 /* we obtain [exten@]context? if yes, split them ... */ 07158 if (a->argc == 3) { 07159 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 07160 context = ast_strdupa(a->argv[2]); 07161 exten = strsep(&context, "@"); 07162 /* change empty strings to NULL */ 07163 if (ast_strlen_zero(exten)) 07164 exten = NULL; 07165 } else { /* no '@' char, only context given */ 07166 context = ast_strdupa(a->argv[2]); 07167 } 07168 if (ast_strlen_zero(context)) 07169 context = NULL; 07170 } 07171 /* else Show complete dial plan, context and exten are NULL */ 07172 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 07173 07174 /* check for input failure and throw some error messages */ 07175 if (context && !counters.context_existence) { 07176 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 07177 return CLI_FAILURE; 07178 } 07179 07180 if (exten && !counters.extension_existence) { 07181 if (context) 07182 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 07183 exten, context); 07184 else 07185 ast_cli(a->fd, 07186 "There is no existence of '%s' extension in all contexts\n", 07187 exten); 07188 return CLI_FAILURE; 07189 } 07190 07191 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 07192 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 07193 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 07194 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 07195 07196 /* everything ok */ 07197 return CLI_SUCCESS; 07198 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3650 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.
03651 { 03652 struct ast_custom_function *acf; 03653 /* Maximum number of characters added by terminal coloring is 22 */ 03654 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03655 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03656 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03657 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03658 char *ret = NULL; 03659 int which = 0; 03660 int wordlen; 03661 03662 switch (cmd) { 03663 case CLI_INIT: 03664 e->command = "core show function"; 03665 e->usage = 03666 "Usage: core show function <function>\n" 03667 " Describe a particular dialplan function.\n"; 03668 return NULL; 03669 case CLI_GENERATE: 03670 wordlen = strlen(a->word); 03671 /* case-insensitive for convenience in this 'complete' function */ 03672 AST_RWLIST_RDLOCK(&acf_root); 03673 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03674 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03675 ret = ast_strdup(acf->name); 03676 break; 03677 } 03678 } 03679 AST_RWLIST_UNLOCK(&acf_root); 03680 03681 return ret; 03682 } 03683 03684 if (a->argc < 4) { 03685 return CLI_SHOWUSAGE; 03686 } 03687 03688 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03689 ast_cli(a->fd, "No function by that name registered.\n"); 03690 return CLI_FAILURE; 03691 } 03692 03693 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03694 if (!(syntax = ast_malloc(syntax_size))) { 03695 ast_cli(a->fd, "Memory allocation failure!\n"); 03696 return CLI_FAILURE; 03697 } 03698 03699 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03700 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03701 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03702 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03703 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03704 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03705 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03706 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03707 #ifdef AST_XML_DOCS 03708 if (acf->docsrc == AST_XML_DOC) { 03709 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03710 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03711 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03712 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03713 } else 03714 #endif 03715 { 03716 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03717 synopsis = ast_malloc(synopsis_size); 03718 03719 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03720 description = ast_malloc(description_size); 03721 03722 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03723 arguments = ast_malloc(arguments_size); 03724 03725 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03726 seealso = ast_malloc(seealso_size); 03727 03728 /* check allocated memory. */ 03729 if (!synopsis || !description || !arguments || !seealso) { 03730 ast_free(synopsis); 03731 ast_free(description); 03732 ast_free(arguments); 03733 ast_free(seealso); 03734 ast_free(syntax); 03735 return CLI_FAILURE; 03736 } 03737 03738 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03739 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03740 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03741 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03742 } 03743 03744 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03745 infotitle, syntitle, synopsis, destitle, description, 03746 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03747 03748 ast_free(arguments); 03749 ast_free(synopsis); 03750 ast_free(description); 03751 ast_free(seealso); 03752 ast_free(syntax); 03753 03754 return CLI_SUCCESS; 03755 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3608 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.
03609 { 03610 struct ast_custom_function *acf; 03611 int count_acf = 0; 03612 int like = 0; 03613 03614 switch (cmd) { 03615 case CLI_INIT: 03616 e->command = "core show functions [like]"; 03617 e->usage = 03618 "Usage: core show functions [like <text>]\n" 03619 " List builtin functions, optionally only those matching a given string\n"; 03620 return NULL; 03621 case CLI_GENERATE: 03622 return NULL; 03623 } 03624 03625 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03626 like = 1; 03627 } else if (a->argc != 3) { 03628 return CLI_SHOWUSAGE; 03629 } 03630 03631 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03632 03633 AST_RWLIST_RDLOCK(&acf_root); 03634 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03635 if (!like || strstr(acf->name, a->argv[4])) { 03636 count_acf++; 03637 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03638 S_OR(acf->name, ""), 03639 S_OR(acf->syntax, ""), 03640 S_OR(acf->synopsis, "")); 03641 } 03642 } 03643 AST_RWLIST_UNLOCK(&acf_root); 03644 03645 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03646 03647 return CLI_SUCCESS; 03648 }
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 7459 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.
07460 { 07461 int i = 0; 07462 struct ast_var_t *newvariable; 07463 07464 switch (cmd) { 07465 case CLI_INIT: 07466 e->command = "dialplan show globals"; 07467 e->usage = 07468 "Usage: dialplan show globals\n" 07469 " List current global dialplan variables and their values\n"; 07470 return NULL; 07471 case CLI_GENERATE: 07472 return NULL; 07473 } 07474 07475 ast_rwlock_rdlock(&globalslock); 07476 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 07477 i++; 07478 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 07479 } 07480 ast_rwlock_unlock(&globalslock); 07481 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 07482 07483 return CLI_SUCCESS; 07484 }
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 6690 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.
06691 { 06692 struct ast_hint *hint; 06693 int watchers; 06694 int num = 0, extenlen; 06695 struct ao2_iterator i; 06696 06697 switch (cmd) { 06698 case CLI_INIT: 06699 e->command = "core show hint"; 06700 e->usage = 06701 "Usage: core show hint <exten>\n" 06702 " List registered hint.\n" 06703 " Hint details are shown in four columns. In order from left to right, they are:\n" 06704 " 1. Hint extension URI.\n" 06705 " 2. Mapped device state identifiers.\n" 06706 " 3. Current extension state. The aggregate of mapped device states.\n" 06707 " 4. Watchers - number of subscriptions and other entities watching this hint.\n"; 06708 06709 return NULL; 06710 case CLI_GENERATE: 06711 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 06712 } 06713 06714 if (a->argc < 4) 06715 return CLI_SHOWUSAGE; 06716 06717 if (ao2_container_count(hints) == 0) { 06718 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06719 return CLI_SUCCESS; 06720 } 06721 06722 extenlen = strlen(a->argv[3]); 06723 i = ao2_iterator_init(hints, 0); 06724 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06725 ao2_lock(hint); 06726 if (!hint->exten) { 06727 /* The extension has already been destroyed */ 06728 ao2_unlock(hint); 06729 continue; 06730 } 06731 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 06732 watchers = ao2_container_count(hint->callbacks); 06733 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06734 ast_get_extension_name(hint->exten), 06735 ast_get_context_name(ast_get_extension_context(hint->exten)), 06736 ast_get_extension_app(hint->exten), 06737 ast_extension_state2str(hint->laststate), watchers); 06738 num++; 06739 } 06740 ao2_unlock(hint); 06741 } 06742 ao2_iterator_destroy(&i); 06743 if (!num) 06744 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 06745 else 06746 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 06747 return CLI_SUCCESS; 06748 }
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 6599 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.
06600 { 06601 struct ast_hint *hint; 06602 int num = 0; 06603 int watchers; 06604 struct ao2_iterator i; 06605 06606 switch (cmd) { 06607 case CLI_INIT: 06608 e->command = "core show hints"; 06609 e->usage = 06610 "Usage: core show hints\n" 06611 " List registered hints.\n" 06612 " Hint details are shown in four columns. In order from left to right, they are:\n" 06613 " 1. Hint extension URI.\n" 06614 " 2. Mapped device state identifiers.\n" 06615 " 3. Current extension state. The aggregate of mapped device states.\n" 06616 " 4. Watchers - number of subscriptions and other entities watching this hint.\n"; 06617 return NULL; 06618 case CLI_GENERATE: 06619 return NULL; 06620 } 06621 06622 if (ao2_container_count(hints) == 0) { 06623 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06624 return CLI_SUCCESS; 06625 } 06626 /* ... we have hints ... */ 06627 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 06628 06629 i = ao2_iterator_init(hints, 0); 06630 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06631 ao2_lock(hint); 06632 if (!hint->exten) { 06633 /* The extension has already been destroyed */ 06634 ao2_unlock(hint); 06635 continue; 06636 } 06637 watchers = ao2_container_count(hint->callbacks); 06638 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06639 ast_get_extension_name(hint->exten), 06640 ast_get_context_name(ast_get_extension_context(hint->exten)), 06641 ast_get_extension_app(hint->exten), 06642 ast_extension_state2str(hint->laststate), watchers); 06643 ao2_unlock(hint); 06644 num++; 06645 } 06646 ao2_iterator_destroy(&i); 06647 06648 ast_cli(a->fd, "----------------\n"); 06649 ast_cli(a->fd, "- %d hints registered\n", num); 06650 return CLI_SUCCESS; 06651 }
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 6752 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.
06753 { 06754 struct ast_switch *sw; 06755 06756 switch (cmd) { 06757 case CLI_INIT: 06758 e->command = "core show switches"; 06759 e->usage = 06760 "Usage: core show switches\n" 06761 " List registered switches\n"; 06762 return NULL; 06763 case CLI_GENERATE: 06764 return NULL; 06765 } 06766 06767 AST_RWLIST_RDLOCK(&switches); 06768 06769 if (AST_RWLIST_EMPTY(&switches)) { 06770 AST_RWLIST_UNLOCK(&switches); 06771 ast_cli(a->fd, "There are no registered alternative switches\n"); 06772 return CLI_SUCCESS; 06773 } 06774 06775 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 06776 AST_RWLIST_TRAVERSE(&switches, sw, list) 06777 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 06778 06779 AST_RWLIST_UNLOCK(&switches); 06780 06781 return CLI_SUCCESS; 06782 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4941 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().
04942 { 04943 struct ast_hint *hint; 04944 struct ast_str *hint_app; 04945 struct statechange *sc = datap; 04946 struct ao2_iterator i; 04947 struct ao2_iterator cb_iter; 04948 char context_name[AST_MAX_CONTEXT]; 04949 char exten_name[AST_MAX_EXTENSION]; 04950 04951 hint_app = ast_str_create(1024); 04952 if (!hint_app) { 04953 ast_free(sc); 04954 return -1; 04955 } 04956 04957 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ 04958 i = ao2_iterator_init(hints, 0); 04959 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 04960 struct ast_state_cb *state_cb; 04961 char *cur, *parse; 04962 int state; 04963 04964 ao2_lock(hint); 04965 if (!hint->exten) { 04966 /* The extension has already been destroyed */ 04967 ao2_unlock(hint); 04968 continue; 04969 } 04970 04971 /* Does this hint monitor the device that changed state? */ 04972 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04973 parse = ast_str_buffer(hint_app); 04974 while ((cur = strsep(&parse, "&"))) { 04975 if (!strcasecmp(cur, sc->dev)) { 04976 /* The hint monitors the device. */ 04977 break; 04978 } 04979 } 04980 if (!cur) { 04981 /* The hint does not monitor the device. */ 04982 ao2_unlock(hint); 04983 continue; 04984 } 04985 04986 /* 04987 * Save off strings in case the hint extension gets destroyed 04988 * while we are notifying the watchers. 04989 */ 04990 ast_copy_string(context_name, 04991 ast_get_context_name(ast_get_extension_context(hint->exten)), 04992 sizeof(context_name)); 04993 ast_copy_string(exten_name, ast_get_extension_name(hint->exten), 04994 sizeof(exten_name)); 04995 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04996 ao2_unlock(hint); 04997 04998 /* 04999 * Get device state for this hint. 05000 * 05001 * NOTE: We cannot hold any locks while determining the hint 05002 * device state or notifying the watchers without causing a 05003 * deadlock. (conlock, hints, and hint) 05004 */ 05005 state = ast_extension_state3(hint_app); 05006 if (state == hint->laststate) { 05007 continue; 05008 } 05009 05010 /* Device state changed since last check - notify the watchers. */ 05011 hint->laststate = state; /* record we saw the change */ 05012 05013 /* For general callbacks */ 05014 cb_iter = ao2_iterator_init(statecbs, 0); 05015 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 05016 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 05017 } 05018 ao2_iterator_destroy(&cb_iter); 05019 05020 /* For extension callbacks */ 05021 cb_iter = ao2_iterator_init(hint->callbacks, 0); 05022 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 05023 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 05024 } 05025 ao2_iterator_destroy(&cb_iter); 05026 } 05027 ao2_iterator_destroy(&i); 05028 ast_mutex_unlock(&context_merge_lock); 05029 05030 ast_free(hint_app); 05031 ast_free(sc); 05032 return 0; 05033 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7639 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.
07640 { 07641 int oldval = 0; 07642 07643 switch (cmd) { 07644 case CLI_INIT: 07645 e->command = "dialplan set extenpatternmatchnew false"; 07646 e->usage = 07647 "Usage: dialplan set extenpatternmatchnew true|false\n" 07648 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07649 return NULL; 07650 case CLI_GENERATE: 07651 return NULL; 07652 } 07653 07654 if (a->argc != 4) 07655 return CLI_SHOWUSAGE; 07656 07657 oldval = pbx_set_extenpatternmatchnew(0); 07658 07659 if (!oldval) 07660 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07661 else 07662 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07663 07664 return CLI_SUCCESS; 07665 }
static int hashtab_compare_exten_labels | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
static int hashtab_compare_exten_numbers | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1130 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1102 of file pbx.c.
References AST_EXT_MATCHCID_ANY, AST_EXT_MATCHCID_OFF, ast_strlen_zero(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01103 { 01104 const struct ast_exten *ac = ah_a; 01105 const struct ast_exten *bc = ah_b; 01106 int x = strcmp(ac->exten, bc->exten); 01107 if (x) { /* if exten names are diff, then return */ 01108 return x; 01109 } 01110 01111 /* but if they are the same, do the cidmatch values match? */ 01112 /* not sure which side may be using ast_ext_matchcid_types, so check both */ 01113 if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) { 01114 return 0; 01115 } 01116 if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) { 01117 return 0; 01118 } 01119 if (ac->matchcid != bc->matchcid) { 01120 return 1; 01121 } 01122 /* all other cases already disposed of, match now required on callerid string (cidmatch) */ 01123 /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */ 01124 if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) { 01125 return 0; 01126 } 01127 return strcmp(ac->cidmatch, bc->cidmatch); 01128 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1150 of file pbx.c.
References AST_EXT_MATCHCID_ON, ast_hashtab_hash_string(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01151 { 01152 const struct ast_exten *ac = obj; 01153 unsigned int x = ast_hashtab_hash_string(ac->exten); 01154 unsigned int y = 0; 01155 if (ac->matchcid == AST_EXT_MATCHCID_ON) 01156 y = ast_hashtab_hash_string(ac->cidmatch); 01157 return x+y; 01158 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1166 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01167 { 01168 const struct ast_exten *ac = obj; 01169 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01170 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1160 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01161 { 01162 const struct ast_exten *ac = obj; 01163 return ast_hashtab_hash_int(ac->priority); 01164 }
static int hint_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
static int hint_hash | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 11265 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().
11266 { 11267 const struct ast_hint *hint = obj; 11268 const char *exten_name; 11269 int res; 11270 11271 exten_name = ast_get_extension_name(hint->exten); 11272 if (ast_strlen_zero(exten_name)) { 11273 /* 11274 * If the exten or extension name isn't set, return 0 so that 11275 * the ao2_find() search will start in the first bucket. 11276 */ 11277 res = 0; 11278 } else { 11279 res = ast_str_case_hash(exten_name); 11280 } 11281 11282 return res; 11283 }
static int hint_id_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 5196 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
05197 { 05198 const struct ast_state_cb *cb = obj; 05199 int *id = arg; 05200 05201 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 05202 }
static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 10838 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.
10840 { 10841 struct ast_data *data_hint; 10842 struct ast_hint *hint; 10843 int watchers; 10844 struct ao2_iterator i; 10845 10846 if (ao2_container_count(hints) == 0) { 10847 return 0; 10848 } 10849 10850 i = ao2_iterator_init(hints, 0); 10851 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 10852 watchers = ao2_container_count(hint->callbacks); 10853 data_hint = ast_data_add_node(data_root, "hint"); 10854 if (!data_hint) { 10855 continue; 10856 } 10857 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 10858 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 10859 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 10860 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 10861 ast_data_add_int(data_hint, "watchers", watchers); 10862 10863 if (!ast_data_search_match(search, data_hint)) { 10864 ast_data_remove_node(data_root, data_hint); 10865 } 10866 } 10867 ao2_iterator_destroy(&i); 10868 10869 return 0; 10870 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1522 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01523 { 01524 if (!i->hastime) 01525 return 1; 01526 01527 return ast_check_timing(&(i->timing)); 01528 }
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 5795 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().
05796 { 05797 int failed = 0; 05798 double curloadavg; 05799 #if defined(HAVE_SYSINFO) 05800 long curfreemem; 05801 struct sysinfo sys_info; 05802 #endif 05803 05804 ast_mutex_lock(&maxcalllock); 05805 if (option_maxcalls) { 05806 if (countcalls >= option_maxcalls) { 05807 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 05808 failed = -1; 05809 } 05810 } 05811 if (option_maxload) { 05812 getloadavg(&curloadavg, 1); 05813 if (curloadavg >= option_maxload) { 05814 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 05815 failed = -1; 05816 } 05817 } 05818 #if defined(HAVE_SYSINFO) 05819 if (option_minmemfree) { 05820 if (!sysinfo(&sys_info)) { 05821 /* make sure that the free system memory is above the configured low watermark 05822 * convert the amount of freeram from mem_units to MB */ 05823 curfreemem = sys_info.freeram * sys_info.mem_unit; 05824 curfreemem /= 1024 * 1024; 05825 if (curfreemem < option_minmemfree) { 05826 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 05827 failed = -1; 05828 } 05829 } 05830 } 05831 #endif 05832 05833 if (!failed) { 05834 countcalls++; 05835 totalcalls++; 05836 } 05837 ast_mutex_unlock(&maxcalllock); 05838 05839 return failed; 05840 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1940 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01941 { 01942 struct match_char *curr, *lcurr; 01943 01944 /* insert node into the tree at "current", so the alt_char list from current is 01945 sorted in increasing value as you go to the leaves */ 01946 if (!(*parent_ptr)) { 01947 *parent_ptr = node; 01948 return; 01949 } 01950 01951 if ((*parent_ptr)->specificity > node->specificity) { 01952 /* insert at head */ 01953 node->alt_char = (*parent_ptr); 01954 *parent_ptr = node; 01955 return; 01956 } 01957 01958 lcurr = *parent_ptr; 01959 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01960 if (curr->specificity > node->specificity) { 01961 node->alt_char = curr; 01962 lcurr->alt_char = node; 01963 break; 01964 } 01965 lcurr = curr; 01966 } 01967 01968 if (!curr) { 01969 lcurr->alt_char = node; 01970 } 01971 01972 }
static int is_read_allowed | ( | struct ast_custom_function * | acfptr | ) | [static] |
Determines whether execution of a custom function's read function is allowed.
acfptr | Custom function to check |
Definition at line 4076 of file pbx.c.
References ast_debug, ast_custom_function::name, read_escalates(), and thread_inhibits_escalations().
Referenced by ast_func_read(), and ast_func_read2().
04077 { 04078 if (!acfptr) { 04079 return 1; 04080 } 04081 04082 if (!read_escalates(acfptr)) { 04083 return 1; 04084 } 04085 04086 if (!thread_inhibits_escalations()) { 04087 return 1; 04088 } 04089 04090 if (live_dangerously) { 04091 /* Global setting overrides the thread's preference */ 04092 ast_debug(2, "Reading %s from a dangerous context\n", 04093 acfptr->name); 04094 return 1; 04095 } 04096 04097 /* We have no reason to allow this function to execute */ 04098 return 0; 04099 }
static int is_write_allowed | ( | struct ast_custom_function * | acfptr | ) | [static] |
Determines whether execution of a custom function's write function is allowed.
acfptr | Custom function to check |
Definition at line 4109 of file pbx.c.
References ast_debug, ast_custom_function::name, thread_inhibits_escalations(), and write_escalates().
Referenced by ast_func_write().
04110 { 04111 if (!acfptr) { 04112 return 1; 04113 } 04114 04115 if (!write_escalates(acfptr)) { 04116 return 1; 04117 } 04118 04119 if (!thread_inhibits_escalations()) { 04120 return 1; 04121 } 04122 04123 if (live_dangerously) { 04124 /* Global setting overrides the thread's preference */ 04125 ast_debug(2, "Writing %s from a dangerous context\n", 04126 acfptr->name); 04127 return 1; 04128 } 04129 04130 /* We have no reason to allow this function to execute */ 04131 return 0; 04132 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 10906 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().
10907 { 10908 int x; 10909 10910 ast_register_atexit(unload_pbx); 10911 10912 /* Initialize the PBX */ 10913 ast_verb(1, "Asterisk PBX Core Initializing\n"); 10914 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 10915 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 10916 } 10917 10918 ast_verb(1, "Registering builtin applications:\n"); 10919 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10920 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 10921 __ast_custom_function_register(&exception_function, NULL); 10922 __ast_custom_function_register(&testtime_function, NULL); 10923 10924 /* Register builtin applications */ 10925 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10926 ast_verb(1, "[%s]\n", builtins[x].name); 10927 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 10928 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 10929 return -1; 10930 } 10931 } 10932 10933 /* Register manager application */ 10934 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 10935 10936 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 10937 AST_EVENT_IE_END))) { 10938 return -1; 10939 } 10940 10941 return 0; 10942 }
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 8164 of file pbx.c.
Referenced by get_range().
08165 { 08166 int i; 08167 08168 if (names && *s > '9') { 08169 for (i = 0; names[i]; i++) { 08170 if (!strcasecmp(s, names[i])) { 08171 return i; 08172 } 08173 } 08174 } 08175 08176 /* Allow months and weekdays to be specified as numbers, as well */ 08177 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 08178 /* What the array offset would have been: "1" would be at offset 0 */ 08179 return i - 1; 08180 } 08181 return -1; /* error return */ 08182 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 7257 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().
07258 { 07259 astman_send_listack(s, m, "DialPlan list will follow", "start"); 07260 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 7402 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().
07403 { 07404 const char *exten, *context; 07405 const char *id = astman_get_header(m, "ActionID"); 07406 char idtext[256]; 07407 07408 /* Variables used for different counters */ 07409 struct dialplan_counters counters; 07410 07411 if (!ast_strlen_zero(id)) 07412 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 07413 else 07414 idtext[0] = '\0'; 07415 07416 memset(&counters, 0, sizeof(counters)); 07417 07418 exten = astman_get_header(m, "Extension"); 07419 context = astman_get_header(m, "Context"); 07420 07421 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 07422 07423 if (!ast_strlen_zero(context) && !counters.context_existence) { 07424 char errorbuf[BUFSIZ]; 07425 07426 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 07427 astman_send_error(s, m, errorbuf); 07428 return 0; 07429 } 07430 if (!ast_strlen_zero(exten) && !counters.extension_existence) { 07431 char errorbuf[BUFSIZ]; 07432 07433 if (!ast_strlen_zero(context)) 07434 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 07435 else 07436 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 07437 astman_send_error(s, m, errorbuf); 07438 return 0; 07439 } 07440 07441 if (!counters.total_items) { 07442 manager_dpsendack(s, m); 07443 } 07444 07445 astman_append(s, "Event: ShowDialPlanComplete\r\n" 07446 "EventList: Complete\r\n" 07447 "ListItems: %d\r\n" 07448 "ListExtensions: %d\r\n" 07449 "ListPriorities: %d\r\n" 07450 "ListContexts: %d\r\n" 07451 "%s" 07452 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 07453 07454 /* everything ok */ 07455 return 0; 07456 }
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 7266 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().
07270 { 07271 struct ast_context *c; 07272 int res = 0, old_total_exten = dpc->total_exten; 07273 07274 if (ast_strlen_zero(exten)) 07275 exten = NULL; 07276 if (ast_strlen_zero(context)) 07277 context = NULL; 07278 07279 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 07280 07281 /* try to lock contexts */ 07282 if (ast_rdlock_contexts()) { 07283 astman_send_error(s, m, "Failed to lock contexts"); 07284 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 07285 return -1; 07286 } 07287 07288 c = NULL; /* walk all contexts ... */ 07289 while ( (c = ast_walk_contexts(c)) ) { 07290 struct ast_exten *e; 07291 struct ast_include *i; 07292 struct ast_ignorepat *ip; 07293 07294 if (context && strcmp(ast_get_context_name(c), context) != 0) 07295 continue; /* not the name we want */ 07296 07297 dpc->context_existence = 1; 07298 dpc->total_context++; 07299 07300 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 07301 07302 if (ast_rdlock_context(c)) { /* failed to lock */ 07303 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 07304 continue; 07305 } 07306 07307 /* XXX note- an empty context is not printed */ 07308 e = NULL; /* walk extensions in context */ 07309 while ( (e = ast_walk_context_extensions(c, e)) ) { 07310 struct ast_exten *p; 07311 07312 /* looking for extension? is this our extension? */ 07313 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 07314 /* not the one we are looking for, continue */ 07315 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 07316 continue; 07317 } 07318 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 07319 07320 dpc->extension_existence = 1; 07321 07322 dpc->total_exten++; 07323 07324 p = NULL; /* walk next extension peers */ 07325 while ( (p = ast_walk_extension_priorities(e, p)) ) { 07326 int prio = ast_get_extension_priority(p); 07327 07328 dpc->total_prio++; 07329 if (!dpc->total_items++) 07330 manager_dpsendack(s, m); 07331 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07332 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 07333 07334 /* XXX maybe make this conditional, if p != e ? */ 07335 if (ast_get_extension_label(p)) 07336 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 07337 07338 if (prio == PRIORITY_HINT) { 07339 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 07340 } else { 07341 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)); 07342 } 07343 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 07344 } 07345 } 07346 07347 i = NULL; /* walk included and write info ... */ 07348 while ( (i = ast_walk_context_includes(c, i)) ) { 07349 if (exten) { 07350 /* Check all includes for the requested extension */ 07351 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 07352 } else { 07353 if (!dpc->total_items++) 07354 manager_dpsendack(s, m); 07355 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07356 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)); 07357 astman_append(s, "\r\n"); 07358 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 07359 } 07360 } 07361 07362 ip = NULL; /* walk ignore patterns and write info ... */ 07363 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 07364 const char *ipname = ast_get_ignorepat_name(ip); 07365 char ignorepat[AST_MAX_EXTENSION]; 07366 07367 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 07368 if (!exten || ast_extension_match(ignorepat, exten)) { 07369 if (!dpc->total_items++) 07370 manager_dpsendack(s, m); 07371 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07372 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 07373 astman_append(s, "\r\n"); 07374 } 07375 } 07376 if (!rinclude) { 07377 struct ast_sw *sw = NULL; 07378 while ( (sw = ast_walk_context_switches(c, sw)) ) { 07379 if (!dpc->total_items++) 07380 manager_dpsendack(s, m); 07381 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07382 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)); 07383 astman_append(s, "\r\n"); 07384 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 07385 } 07386 } 07387 07388 ast_unlock_context(c); 07389 } 07390 ast_unlock_contexts(); 07391 07392 if (dpc->total_exten == old_total_exten) { 07393 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 07394 /* Nothing new under the sun */ 07395 return -1; 07396 } else { 07397 return res; 07398 } 07399 }
void mask_string | ( | char * | , | |
int | , | |||
int | , | |||
int | ||||
) |
Provided by pbx.c
Definition at line 4650 of file pbx.c.
References ast_strlen_zero().
Referenced by AST_LIST_HEAD(), handle_verbose(), pbx_extension_helper(), and run_agi().
04650 { 04651 char *val; 04652 int i; 04653 04654 if (!findeq) { 04655 val = str; 04656 } else { 04657 val = strchr(str, '='); 04658 val++; 04659 } 04660 if (!ast_strlen_zero(val)) { 04661 if (strlen(val) >= ini) { 04662 for (i=0; i<strlen(val); i++) { 04663 if ((i>=ini-1) && (i<end)) 04664 val[i] = 'X'; 04665 } 04666 } 04667 } 04668 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2958 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02959 { 02960 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02961 failing to get a number should count as a match, otherwise not */ 02962 02963 if (ast_strlen_zero(callerid)) { 02964 return ast_strlen_zero(cidpattern) ? 1 : 0; 02965 } 02966 02967 return ast_extension_match(cidpattern, callerid); 02968 }
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 1764 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().
01765 { 01766 struct match_char *p; /* note minimal stack storage requirements */ 01767 struct ast_exten pattern = { .label = label }; 01768 #ifdef DEBUG_THIS 01769 if (tree) 01770 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01771 else 01772 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01773 #endif 01774 for (p = tree; p; p = p->alt_char) { 01775 if (p->is_pattern) { 01776 if (p->x[0] == 'N') { 01777 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01778 #define NEW_MATCHER_CHK_MATCH \ 01779 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01780 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01781 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01782 if (!p->deleted) { \ 01783 if (action == E_FINDLABEL) { \ 01784 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01785 ast_debug(4, "Found label in preferred extension\n"); \ 01786 return; \ 01787 } \ 01788 } else { \ 01789 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01790 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01791 } \ 01792 } \ 01793 } \ 01794 } 01795 01796 #define NEW_MATCHER_RECURSE \ 01797 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01798 || p->next_char->x[0] == '!')) { \ 01799 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01800 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01801 if (score->exten) { \ 01802 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01803 return; /* the first match is all we need */ \ 01804 } \ 01805 } else { \ 01806 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01807 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01808 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01809 "NULL"); \ 01810 return; /* the first match is all we need */ \ 01811 } \ 01812 } \ 01813 } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \ 01814 score->canmatch = 1; \ 01815 score->canmatch_exten = get_canmatch_exten(p); \ 01816 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01817 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01818 return; \ 01819 } \ 01820 } 01821 01822 NEW_MATCHER_CHK_MATCH; 01823 NEW_MATCHER_RECURSE; 01824 } 01825 } else if (p->x[0] == 'Z') { 01826 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01827 NEW_MATCHER_CHK_MATCH; 01828 NEW_MATCHER_RECURSE; 01829 } 01830 } else if (p->x[0] == 'X') { 01831 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01832 NEW_MATCHER_CHK_MATCH; 01833 NEW_MATCHER_RECURSE; 01834 } 01835 } else if (p->x[0] == '.' && p->x[1] == 0) { 01836 /* how many chars will the . match against? */ 01837 int i = 0; 01838 const char *str2 = str; 01839 while (*str2 && *str2 != '/') { 01840 str2++; 01841 i++; 01842 } 01843 if (p->exten && *str2 != '/') { 01844 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01845 if (score->exten) { 01846 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01847 return; /* the first match is all we need */ 01848 } 01849 } 01850 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01851 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01852 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01853 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01854 return; /* the first match is all we need */ 01855 } 01856 } 01857 } else if (p->x[0] == '!' && p->x[1] == 0) { 01858 /* how many chars will the . match against? */ 01859 int i = 1; 01860 const char *str2 = str; 01861 while (*str2 && *str2 != '/') { 01862 str2++; 01863 i++; 01864 } 01865 if (p->exten && *str2 != '/') { 01866 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01867 if (score->exten) { 01868 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01869 return; /* the first match is all we need */ 01870 } 01871 } 01872 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01873 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01874 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01875 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01876 return; /* the first match is all we need */ 01877 } 01878 } 01879 } else if (p->x[0] == '/' && p->x[1] == 0) { 01880 /* the pattern in the tree includes the cid match! */ 01881 if (p->next_char && callerid && *callerid) { 01882 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01883 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01884 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01885 return; /* the first match is all we need */ 01886 } 01887 } 01888 } else if (strchr(p->x, *str)) { 01889 ast_debug(4, "Nothing strange about this match\n"); 01890 NEW_MATCHER_CHK_MATCH; 01891 NEW_MATCHER_RECURSE; 01892 } 01893 } else if (strchr(p->x, *str)) { 01894 ast_debug(4, "Nothing strange about this match\n"); 01895 NEW_MATCHER_CHK_MATCH; 01896 NEW_MATCHER_RECURSE; 01897 } 01898 } 01899 ast_debug(4, "return at end of func\n"); 01900 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 3268 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
03269 { 03270 int parens = 0; 03271 03272 *offset = 0; 03273 *length = INT_MAX; 03274 *isfunc = 0; 03275 for (; *var; var++) { 03276 if (*var == '(') { 03277 (*isfunc)++; 03278 parens++; 03279 } else if (*var == ')') { 03280 parens--; 03281 } else if (*var == ':' && parens == 0) { 03282 *var++ = '\0'; 03283 sscanf(var, "%30d:%30d", offset, length); 03284 return 1; /* offset:length valid */ 03285 } 03286 } 03287 return 0; 03288 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10714 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().
10715 { 10716 struct ast_var_t *vardata; 10717 10718 ast_rwlock_wrlock(&globalslock); 10719 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10720 ast_var_delete(vardata); 10721 ast_rwlock_unlock(&globalslock); 10722 }
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 10480 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().
10481 { 10482 struct ast_var_t *variables; 10483 const char *ret = NULL; 10484 int i; 10485 struct varshead *places[2] = { NULL, &globals }; 10486 10487 if (!name) 10488 return NULL; 10489 10490 if (chan) { 10491 ast_channel_lock(chan); 10492 places[0] = &chan->varshead; 10493 } 10494 10495 for (i = 0; i < 2; i++) { 10496 if (!places[i]) 10497 continue; 10498 if (places[i] == &globals) 10499 ast_rwlock_rdlock(&globalslock); 10500 AST_LIST_TRAVERSE(places[i], variables, entries) { 10501 if (!strcmp(name, ast_var_name(variables))) { 10502 ret = ast_var_value(variables); 10503 break; 10504 } 10505 } 10506 if (places[i] == &globals) 10507 ast_rwlock_unlock(&globalslock); 10508 if (ret) 10509 break; 10510 } 10511 10512 if (chan) 10513 ast_channel_unlock(chan); 10514 10515 return ret; 10516 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10736 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), and pbx_checkcondition().
10737 { 10738 char *condition, *branch1, *branch2, *branch; 10739 char *stringp; 10740 10741 if (ast_strlen_zero(data)) { 10742 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 10743 return 0; 10744 } 10745 10746 stringp = ast_strdupa(data); 10747 condition = strsep(&stringp,"?"); 10748 branch1 = strsep(&stringp,":"); 10749 branch2 = strsep(&stringp,""); 10750 branch = pbx_checkcondition(condition) ? branch1 : branch2; 10751 10752 if (ast_strlen_zero(branch)) { 10753 ast_debug(1, "Not taking any branch\n"); 10754 return 0; 10755 } 10756 10757 return pbx_builtin_goto(chan, branch); 10758 }
int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10674 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.
10675 { 10676 char *name; 10677 char *value; 10678 char *channel; 10679 char tmp[VAR_BUF_SIZE]; 10680 static int deprecation_warning = 0; 10681 10682 if (ast_strlen_zero(data)) { 10683 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 10684 return 0; 10685 } 10686 tmp[0] = 0; 10687 if (!deprecation_warning) { 10688 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 10689 deprecation_warning = 1; 10690 } 10691 10692 value = ast_strdupa(data); 10693 name = strsep(&value,"="); 10694 channel = strsep(&value,","); 10695 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 10696 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 10697 if (chan2) { 10698 char *s = ast_alloca(strlen(value) + 4); 10699 sprintf(s, "${%s}", value); 10700 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 10701 chan2 = ast_channel_unref(chan2); 10702 } 10703 pbx_builtin_setvar_helper(chan, name, tmp); 10704 } 10705 10706 return(0); 10707 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10001 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().
10002 { 10003 const char *options = data; 10004 int answer = 1; 10005 10006 /* Some channels can receive DTMF in unanswered state; some cannot */ 10007 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 10008 answer = 0; 10009 } 10010 10011 /* If the channel is hungup, stop waiting */ 10012 if (ast_check_hangup(chan)) { 10013 return -1; 10014 } else if (chan->_state != AST_STATE_UP && answer) { 10015 __ast_answer(chan, 0, 1); 10016 } 10017 10018 ast_indicate(chan, AST_CONTROL_INCOMPLETE); 10019 10020 return AST_PBX_INCOMPLETE; 10021 }
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 10518 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().
10519 { 10520 struct ast_var_t *newvariable; 10521 struct varshead *headp; 10522 10523 if (name[strlen(name)-1] == ')') { 10524 char *function = ast_strdupa(name); 10525 10526 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10527 ast_func_write(chan, function, value); 10528 return; 10529 } 10530 10531 if (chan) { 10532 ast_channel_lock(chan); 10533 headp = &chan->varshead; 10534 } else { 10535 ast_rwlock_wrlock(&globalslock); 10536 headp = &globals; 10537 } 10538 10539 if (value && (newvariable = ast_var_assign(name, value))) { 10540 if (headp == &globals) 10541 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10542 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10543 } 10544 10545 if (chan) 10546 ast_channel_unlock(chan); 10547 else 10548 ast_rwlock_unlock(&globalslock); 10549 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason | |||
) |
Definition at line 3577 of file pbx.c.
References raise_exception().
03578 { 03579 /* Priority will become 1, next time through the AUTOLOOP */ 03580 return raise_exception(chan, reason, 0); 03581 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10797 of file pbx.c.
References ast_say_character_str().
10798 { 10799 int res = 0; 10800 10801 if (data) 10802 res = ast_say_character_str(chan, data, "", chan->language); 10803 return res; 10804 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10788 of file pbx.c.
References ast_say_digit_str().
10789 { 10790 int res = 0; 10791 10792 if (data) 10793 res = ast_say_digit_str(chan, data, "", chan->language); 10794 return res; 10795 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10760 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), and LOG_WARNING.
10761 { 10762 char tmp[256]; 10763 char *number = tmp; 10764 char *options; 10765 10766 if (ast_strlen_zero(data)) { 10767 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 10768 return -1; 10769 } 10770 ast_copy_string(tmp, data, sizeof(tmp)); 10771 strsep(&number, ","); 10772 options = strsep(&number, ","); 10773 if (options) { 10774 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 10775 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 10776 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 10777 return -1; 10778 } 10779 } 10780 10781 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 10782 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 10783 } 10784 10785 return 0; 10786 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10806 of file pbx.c.
References ast_say_phonetic_str().
10807 { 10808 int res = 0; 10809 10810 if (data) 10811 res = ast_say_phonetic_str(chan, data, "", chan->language); 10812 return res; 10813 }
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 10449 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().
10450 { 10451 struct ast_var_t *variables; 10452 const char *var, *val; 10453 int total = 0; 10454 10455 if (!chan) 10456 return 0; 10457 10458 ast_str_reset(*buf); 10459 10460 ast_channel_lock(chan); 10461 10462 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10463 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10464 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10465 ) { 10466 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10467 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10468 break; 10469 } else 10470 total++; 10471 } else 10472 break; 10473 } 10474 10475 ast_channel_unlock(chan); 10476 10477 return total; 10478 }
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 10608 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().
10609 { 10610 char *name, *value, *mydata; 10611 10612 if (ast_compat_app_set) { 10613 return pbx_builtin_setvar_multiple(chan, data); 10614 } 10615 10616 if (ast_strlen_zero(data)) { 10617 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10618 return 0; 10619 } 10620 10621 mydata = ast_strdupa(data); 10622 name = strsep(&mydata, "="); 10623 value = mydata; 10624 if (!value) { 10625 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10626 return 0; 10627 } 10628 10629 if (strchr(name, ' ')) { 10630 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10631 } 10632 10633 pbx_builtin_setvar_helper(chan, name, value); 10634 10635 return 0; 10636 }
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 10551 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_LIST_HEAD(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), gosub_run(), handle_gosub(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_call_full(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), 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().
10552 { 10553 struct ast_var_t *newvariable; 10554 struct varshead *headp; 10555 const char *nametail = name; 10556 10557 if (name[strlen(name) - 1] == ')') { 10558 char *function = ast_strdupa(name); 10559 10560 return ast_func_write(chan, function, value); 10561 } 10562 10563 if (chan) { 10564 ast_channel_lock(chan); 10565 headp = &chan->varshead; 10566 } else { 10567 ast_rwlock_wrlock(&globalslock); 10568 headp = &globals; 10569 } 10570 10571 /* For comparison purposes, we have to strip leading underscores */ 10572 if (*nametail == '_') { 10573 nametail++; 10574 if (*nametail == '_') 10575 nametail++; 10576 } 10577 10578 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10579 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10580 /* there is already such a variable, delete it */ 10581 AST_LIST_REMOVE_CURRENT(entries); 10582 ast_var_delete(newvariable); 10583 break; 10584 } 10585 } 10586 AST_LIST_TRAVERSE_SAFE_END; 10587 10588 if (value && (newvariable = ast_var_assign(name, value))) { 10589 if (headp == &globals) 10590 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10591 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10592 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10593 "Channel: %s\r\n" 10594 "Variable: %s\r\n" 10595 "Value: %s\r\n" 10596 "Uniqueid: %s\r\n", 10597 chan ? chan->name : "none", name, value, 10598 chan ? chan->uniqueid : "none"); 10599 } 10600 10601 if (chan) 10602 ast_channel_unlock(chan); 10603 else 10604 ast_rwlock_unlock(&globalslock); 10605 return 0; 10606 }
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 10638 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().
10639 { 10640 char *data; 10641 int x; 10642 AST_DECLARE_APP_ARGS(args, 10643 AST_APP_ARG(pair)[24]; 10644 ); 10645 AST_DECLARE_APP_ARGS(pair, 10646 AST_APP_ARG(name); 10647 AST_APP_ARG(value); 10648 ); 10649 10650 if (ast_strlen_zero(vdata)) { 10651 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10652 return 0; 10653 } 10654 10655 data = ast_strdupa(vdata); 10656 AST_STANDARD_APP_ARGS(args, data); 10657 10658 for (x = 0; x < args.argc; x++) { 10659 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10660 if (pair.argc == 2) { 10661 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10662 if (strchr(pair.name, ' ')) 10663 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); 10664 } else if (!chan) { 10665 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10666 } else { 10667 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10668 } 10669 } 10670 10671 return 0; 10672 }
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 10724 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().
10725 { 10726 int res; 10727 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10728 return 0; 10729 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10730 return res; 10731 } else { /* Strings are true */ 10732 return 1; 10733 } 10734 }
static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 1530 of file pbx.c.
References ast_free.
Referenced by __ast_pbx_run().
01531 { 01532 ast_free(p); 01533 }
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 1454 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().
01457 { 01458 int res; 01459 struct ast_module_user *u = NULL; 01460 const char *saved_c_appl; 01461 const char *saved_c_data; 01462 01463 if (c->cdr && !ast_check_hangup(c)) 01464 ast_cdr_setapp(c->cdr, app->name, data); 01465 01466 /* save channel values */ 01467 saved_c_appl= c->appl; 01468 saved_c_data= c->data; 01469 01470 c->appl = app->name; 01471 c->data = data; 01472 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01473 01474 if (app->module) 01475 u = __ast_module_user_add(app->module, c); 01476 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01477 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01478 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01479 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01480 app->name, (char *) data); 01481 } 01482 res = app->execute(c, S_OR(data, "")); 01483 if (app->module && u) 01484 __ast_module_user_remove(app->module, u); 01485 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01486 /* restore channel values */ 01487 c->appl = saved_c_appl; 01488 c->data = saved_c_data; 01489 return res; 01490 }
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 4688 of file pbx.c.
References agimaskvar, agimaskvarend, agimaskvarini, ast_exten::app, app, ast_copy_string(), ast_debug, AST_LIST_TRAVERSE, 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, mask_string(), 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, setmaskvar, setmaskvarend, setmaskvarini, 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(), var, ast_variable_list::variable, and VERBOSITY_ATLEAST.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
04691 { 04692 struct ast_exten *e; 04693 struct ast_app *app; 04694 char *substitute = NULL; 04695 int res; 04696 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04697 char passdata[EXT_DATA_SIZE]; 04698 char *tmpdata, *var; 04699 struct ast_variable_list *cur; 04700 04701 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04702 04703 ast_rdlock_contexts(); 04704 if (found) 04705 *found = 0; 04706 04707 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04708 if (e) { 04709 if (found) 04710 *found = 1; 04711 if (matching_action) { 04712 ast_unlock_contexts(); 04713 return -1; /* success, we found it */ 04714 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04715 res = e->priority; 04716 ast_unlock_contexts(); 04717 return res; /* the priority we were looking for */ 04718 } else { /* spawn */ 04719 if (!e->cached_app) 04720 e->cached_app = pbx_findapp(e->app); 04721 app = e->cached_app; 04722 if (ast_strlen_zero(e->data)) { 04723 *passdata = '\0'; 04724 } else { 04725 const char *tmp; 04726 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 04727 /* no variables to substitute, copy on through */ 04728 ast_copy_string(passdata, e->data, sizeof(passdata)); 04729 } else { 04730 /* save e->data on stack for later processing after lock released */ 04731 substitute = ast_strdupa(e->data); 04732 } 04733 } 04734 ast_unlock_contexts(); 04735 if (!app) { 04736 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04737 return -1; 04738 } 04739 if (c->context != context) 04740 ast_copy_string(c->context, context, sizeof(c->context)); 04741 if (c->exten != exten) 04742 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04743 c->priority = priority; 04744 if (substitute) { 04745 pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1); 04746 } 04747 #ifdef CHANNEL_TRACE 04748 ast_channel_trace_update(c); 04749 #endif 04750 ast_debug(1, "Launching '%s'\n", app->name); 04751 tmpdata = ast_strdupa(passdata); /* do not modify string */ 04752 if (VERBOSITY_ATLEAST(3)) { 04753 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04754 char findstr[128]; 04755 if ((!strcmp(app->name, "Set") || !strcmp(app->name, "MSet")) 04756 && !ast_strlen_zero(setmaskvar)) { 04757 AST_LIST_TRAVERSE(&setmaskvars, cur, list) { 04758 ast_copy_string(findstr, cur->variable, sizeof(findstr)); 04759 strncat(findstr, "=", sizeof(findstr)); 04760 if (!strncmp(tmpdata, findstr, strlen(findstr))) { 04761 mask_string(tmpdata, setmaskvarini, setmaskvarend, 1); 04762 break; 04763 } 04764 } 04765 } else if (!strcmp(app->name, "AGI") && !ast_strlen_zero(agimaskvar)) { 04766 AST_LIST_TRAVERSE(&agimaskvars, cur, list) { 04767 ast_copy_string(findstr, cur->variable, sizeof(findstr)); 04768 strncat(findstr, "=", sizeof(findstr)); 04769 var = strstr(tmpdata, findstr); 04770 if (var) 04771 mask_string(var, agimaskvarini, agimaskvarend, 1); 04772 } 04773 } 04774 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04775 exten, context, priority, 04776 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04777 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04778 term_color(tmp3, tmpdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04779 "in new stack"); 04780 } 04781 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04782 "Channel: %s\r\n" 04783 "Context: %s\r\n" 04784 "Extension: %s\r\n" 04785 "Priority: %d\r\n" 04786 "Application: %s\r\n" 04787 "AppData: %s\r\n" 04788 "Uniqueid: %s\r\n", 04789 c->name, c->context, c->exten, c->priority, app->name, tmpdata, c->uniqueid); 04790 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04791 } 04792 } else if (q.swo) { /* not found here, but in another switch */ 04793 if (found) 04794 *found = 1; 04795 ast_unlock_contexts(); 04796 if (matching_action) { 04797 return -1; 04798 } else { 04799 if (!q.swo->exec) { 04800 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04801 res = -1; 04802 } 04803 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04804 } 04805 } else { /* not found anywhere, see what happened */ 04806 ast_unlock_contexts(); 04807 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04808 switch (q.status) { 04809 case STATUS_NO_CONTEXT: 04810 if (!matching_action && !combined_find_spawn) 04811 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04812 break; 04813 case STATUS_NO_EXTENSION: 04814 if (!matching_action && !combined_find_spawn) 04815 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04816 break; 04817 case STATUS_NO_PRIORITY: 04818 if (!matching_action && !combined_find_spawn) 04819 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04820 break; 04821 case STATUS_NO_LABEL: 04822 if (context && !combined_find_spawn) 04823 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04824 break; 04825 default: 04826 ast_debug(1, "Shouldn't happen!\n"); 04827 } 04828 04829 return (matching_action) ? 0 : -1; 04830 } 04831 }
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 2970 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().
02974 { 02975 int x, res; 02976 struct ast_context *tmp = NULL; 02977 struct ast_exten *e = NULL, *eroot = NULL; 02978 struct ast_include *i = NULL; 02979 struct ast_sw *sw = NULL; 02980 struct ast_exten pattern = {NULL, }; 02981 struct scoreboard score = {0, }; 02982 struct ast_str *tmpdata = NULL; 02983 02984 pattern.label = label; 02985 pattern.priority = priority; 02986 #ifdef NEED_DEBUG_HERE 02987 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02988 #endif 02989 02990 /* Initialize status if appropriate */ 02991 if (q->stacklen == 0) { 02992 q->status = STATUS_NO_CONTEXT; 02993 q->swo = NULL; 02994 q->data = NULL; 02995 q->foundcontext = NULL; 02996 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02997 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02998 return NULL; 02999 } 03000 03001 /* Check first to see if we've already been checked */ 03002 for (x = 0; x < q->stacklen; x++) { 03003 if (!strcasecmp(q->incstack[x], context)) 03004 return NULL; 03005 } 03006 03007 if (bypass) { /* bypass means we only look there */ 03008 tmp = bypass; 03009 } else { /* look in contexts */ 03010 tmp = find_context(context); 03011 if (!tmp) { 03012 return NULL; 03013 } 03014 } 03015 03016 if (q->status < STATUS_NO_EXTENSION) 03017 q->status = STATUS_NO_EXTENSION; 03018 03019 /* Do a search for matching extension */ 03020 03021 eroot = NULL; 03022 score.total_specificity = 0; 03023 score.exten = 0; 03024 score.total_length = 0; 03025 if (!tmp->pattern_tree && tmp->root_table) { 03026 create_match_char_tree(tmp); 03027 #ifdef NEED_DEBUG 03028 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 03029 log_match_char_tree(tmp->pattern_tree," "); 03030 #endif 03031 } 03032 #ifdef NEED_DEBUG 03033 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03034 log_match_char_tree(tmp->pattern_tree, ":: "); 03035 #endif 03036 03037 do { 03038 if (!ast_strlen_zero(overrideswitch)) { 03039 char *osw = ast_strdupa(overrideswitch), *name; 03040 struct ast_switch *asw; 03041 ast_switch_f *aswf = NULL; 03042 char *datap; 03043 int eval = 0; 03044 03045 name = strsep(&osw, "/"); 03046 asw = pbx_findswitch(name); 03047 03048 if (!asw) { 03049 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03050 break; 03051 } 03052 03053 if (osw && strchr(osw, '$')) { 03054 eval = 1; 03055 } 03056 03057 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03058 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03059 break; 03060 } else if (eval) { 03061 /* Substitute variables now */ 03062 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03063 datap = ast_str_buffer(tmpdata); 03064 } else { 03065 datap = osw; 03066 } 03067 03068 /* equivalent of extension_match_core() at the switch level */ 03069 if (action == E_CANMATCH) 03070 aswf = asw->canmatch; 03071 else if (action == E_MATCHMORE) 03072 aswf = asw->matchmore; 03073 else /* action == E_MATCH */ 03074 aswf = asw->exists; 03075 if (!aswf) { 03076 res = 0; 03077 } else { 03078 if (chan) { 03079 ast_autoservice_start(chan); 03080 } 03081 res = aswf(chan, context, exten, priority, callerid, datap); 03082 if (chan) { 03083 ast_autoservice_stop(chan); 03084 } 03085 } 03086 if (res) { /* Got a match */ 03087 q->swo = asw; 03088 q->data = datap; 03089 q->foundcontext = context; 03090 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03091 return NULL; 03092 } 03093 } 03094 } while (0); 03095 03096 if (extenpatternmatchnew) { 03097 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03098 eroot = score.exten; 03099 03100 if (score.last_char == '!' && action == E_MATCHMORE) { 03101 /* We match an extension ending in '!'. 03102 * The decision in this case is final and is NULL (no match). 03103 */ 03104 #ifdef NEED_DEBUG_HERE 03105 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03106 #endif 03107 return NULL; 03108 } 03109 03110 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03111 q->status = STATUS_SUCCESS; 03112 #ifdef NEED_DEBUG_HERE 03113 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03114 #endif 03115 return score.canmatch_exten; 03116 } 03117 03118 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03119 if (score.node) { 03120 struct ast_exten *z = trie_find_next_match(score.node); 03121 if (z) { 03122 #ifdef NEED_DEBUG_HERE 03123 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03124 #endif 03125 } else { 03126 if (score.canmatch_exten) { 03127 #ifdef NEED_DEBUG_HERE 03128 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03129 #endif 03130 return score.canmatch_exten; 03131 } else { 03132 #ifdef NEED_DEBUG_HERE 03133 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03134 #endif 03135 } 03136 } 03137 return z; 03138 } 03139 #ifdef NEED_DEBUG_HERE 03140 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03141 #endif 03142 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03143 } 03144 03145 if (eroot) { 03146 /* found entry, now look for the right priority */ 03147 if (q->status < STATUS_NO_PRIORITY) 03148 q->status = STATUS_NO_PRIORITY; 03149 e = NULL; 03150 if (action == E_FINDLABEL && label ) { 03151 if (q->status < STATUS_NO_LABEL) 03152 q->status = STATUS_NO_LABEL; 03153 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03154 } else { 03155 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03156 } 03157 if (e) { /* found a valid match */ 03158 q->status = STATUS_SUCCESS; 03159 q->foundcontext = context; 03160 #ifdef NEED_DEBUG_HERE 03161 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03162 #endif 03163 return e; 03164 } 03165 } 03166 } else { /* the old/current default exten pattern match algorithm */ 03167 03168 /* scan the list trying to match extension and CID */ 03169 eroot = NULL; 03170 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03171 int match = extension_match_core(eroot->exten, exten, action); 03172 /* 0 on fail, 1 on match, 2 on earlymatch */ 03173 03174 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03175 continue; /* keep trying */ 03176 if (match == 2 && action == E_MATCHMORE) { 03177 /* We match an extension ending in '!'. 03178 * The decision in this case is final and is NULL (no match). 03179 */ 03180 return NULL; 03181 } 03182 /* found entry, now look for the right priority */ 03183 if (q->status < STATUS_NO_PRIORITY) 03184 q->status = STATUS_NO_PRIORITY; 03185 e = NULL; 03186 if (action == E_FINDLABEL && label ) { 03187 if (q->status < STATUS_NO_LABEL) 03188 q->status = STATUS_NO_LABEL; 03189 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03190 } else { 03191 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03192 } 03193 if (e) { /* found a valid match */ 03194 q->status = STATUS_SUCCESS; 03195 q->foundcontext = context; 03196 return e; 03197 } 03198 } 03199 } 03200 03201 /* Check alternative switches */ 03202 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03203 struct ast_switch *asw = pbx_findswitch(sw->name); 03204 ast_switch_f *aswf = NULL; 03205 char *datap; 03206 03207 if (!asw) { 03208 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03209 continue; 03210 } 03211 03212 /* Substitute variables now */ 03213 if (sw->eval) { 03214 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03215 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03216 continue; 03217 } 03218 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03219 } 03220 03221 /* equivalent of extension_match_core() at the switch level */ 03222 if (action == E_CANMATCH) 03223 aswf = asw->canmatch; 03224 else if (action == E_MATCHMORE) 03225 aswf = asw->matchmore; 03226 else /* action == E_MATCH */ 03227 aswf = asw->exists; 03228 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03229 if (!aswf) 03230 res = 0; 03231 else { 03232 if (chan) 03233 ast_autoservice_start(chan); 03234 res = aswf(chan, context, exten, priority, callerid, datap); 03235 if (chan) 03236 ast_autoservice_stop(chan); 03237 } 03238 if (res) { /* Got a match */ 03239 q->swo = asw; 03240 q->data = datap; 03241 q->foundcontext = context; 03242 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03243 return NULL; 03244 } 03245 } 03246 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03247 /* Now try any includes we have in this context */ 03248 for (i = tmp->includes; i; i = i->next) { 03249 if (include_valid(i)) { 03250 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03251 #ifdef NEED_DEBUG_HERE 03252 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03253 #endif 03254 return e; 03255 } 03256 if (q->swo) 03257 return NULL; 03258 } 03259 } 03260 return NULL; 03261 }
struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 1494 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().
01495 { 01496 struct ast_app *tmp; 01497 01498 AST_RWLIST_RDLOCK(&apps); 01499 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01500 if (!strcasecmp(tmp->name, app)) 01501 break; 01502 } 01503 AST_RWLIST_UNLOCK(&apps); 01504 01505 return tmp; 01506 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 1508 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
01509 { 01510 struct ast_switch *asw; 01511 01512 AST_RWLIST_RDLOCK(&switches); 01513 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01514 if (!strcasecmp(asw->name, sw)) 01515 break; 01516 } 01517 AST_RWLIST_UNLOCK(&switches); 01518 01519 return asw; 01520 }
void pbx_live_dangerously | ( | int | new_live_dangerously | ) |
Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).
These dialplan functions (such as SHELL
) provide an opportunity for privilege escalation. They are okay to invoke from the dialplan, but external protocols with permission controls should not normally invoke them.
This function can globally enable/disable the execution of dangerous functions from external protocols.
new_live_dangerously | If true, enable the execution of escalating functions from external protocols. |
Definition at line 4016 of file pbx.c.
References ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by ast_readconfig().
04017 { 04018 if (new_live_dangerously && !live_dangerously) { 04019 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n" 04020 "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n"); 04021 } 04022 04023 if (!new_live_dangerously && live_dangerously) { 04024 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n"); 04025 } 04026 live_dangerously = new_live_dangerously; 04027 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 11181 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().
11182 { 11183 char *exten, *pri, *context; 11184 char *stringp; 11185 int ipri; 11186 int mode = 0; 11187 11188 if (ast_strlen_zero(goto_string)) { 11189 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 11190 return -1; 11191 } 11192 stringp = ast_strdupa(goto_string); 11193 context = strsep(&stringp, ","); /* guaranteed non-null */ 11194 exten = strsep(&stringp, ","); 11195 pri = strsep(&stringp, ","); 11196 if (!exten) { /* Only a priority in this one */ 11197 pri = context; 11198 exten = NULL; 11199 context = NULL; 11200 } else if (!pri) { /* Only an extension and priority in this one */ 11201 pri = exten; 11202 exten = context; 11203 context = NULL; 11204 } 11205 if (*pri == '+') { 11206 mode = 1; 11207 pri++; 11208 } else if (*pri == '-') { 11209 mode = -1; 11210 pri++; 11211 } 11212 if (sscanf(pri, "%30d", &ipri) != 1) { 11213 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 11214 exten ? exten : chan->exten, pri, 11215 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 11216 if (ipri < 1) { 11217 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 11218 return -1; 11219 } else 11220 mode = 0; 11221 } 11222 /* At this point we have a priority and maybe an extension and a context */ 11223 11224 if (mode) 11225 ipri = chan->priority + (ipri * mode); 11226 11227 if (async) 11228 ast_async_goto(chan, context, exten, ipri); 11229 else 11230 ast_explicit_goto(chan, context, exten, ipri); 11231 11232 return 0; 11233 11234 }
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 3391 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().
03392 { 03393 struct ast_str *str = ast_str_create(16); 03394 const char *cret; 03395 03396 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03397 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03398 *ret = cret ? workspace : NULL; 03399 ast_free(str); 03400 }
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 5946 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05947 { 05948 int oldval = autofallthrough; 05949 autofallthrough = newval; 05950 return oldval; 05951 }
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 5953 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05954 { 05955 int oldval = extenpatternmatchnew; 05956 extenpatternmatchnew = newval; 05957 return oldval; 05958 }
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 5960 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05961 { 05962 if (overrideswitch) { 05963 ast_free(overrideswitch); 05964 } 05965 if (!ast_strlen_zero(newval)) { 05966 overrideswitch = ast_strdup(newval); 05967 } else { 05968 overrideswitch = NULL; 05969 } 05970 }
static void pbx_shutdown | ( | void | ) | [static] |
Definition at line 11301 of file pbx.c.
References ao2_ref, ast_hashtab_destroy(), contexts_table, hints, pbx_builtin_clear_globals(), and statecbs.
Referenced by ast_pbx_init().
11302 { 11303 if (hints) { 11304 ao2_ref(hints, -1); 11305 hints = NULL; 11306 } 11307 if (statecbs) { 11308 ao2_ref(statecbs, -1); 11309 statecbs = NULL; 11310 } 11311 if (contexts_table) { 11312 ast_hashtab_destroy(contexts_table, NULL); 11313 } 11314 pbx_builtin_clear_globals(); 11315 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4633 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_extension_helper(), pbx_find_extension(), pbx_load_config(), realtime_exec(), rotate_file(), substituted(), try_calling(), and write_cdr().
04634 { 04635 size_t used; 04636 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04637 }
void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
struct varshead * | headp, | |||
const char * | cp1, | |||
char * | cp2, | |||
int | count, | |||
size_t * | used | |||
) |
Definition at line 4437 of file pbx.c.
References ast_alloca, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
04438 { 04439 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04440 char *cp4 = NULL; 04441 const char *tmp, *whereweare, *orig_cp2 = cp2; 04442 int length, offset, offset2, isfunction; 04443 char *workspace = NULL; 04444 char *ltmp = NULL, *var = NULL; 04445 char *nextvar, *nextexp, *nextthing; 04446 char *vars, *vare; 04447 int pos, brackets, needsub, len; 04448 04449 *cp2 = 0; /* just in case nothing ends up there */ 04450 whereweare=tmp=cp1; 04451 while (!ast_strlen_zero(whereweare) && count) { 04452 /* Assume we're copying the whole remaining string */ 04453 pos = strlen(whereweare); 04454 nextvar = NULL; 04455 nextexp = NULL; 04456 nextthing = strchr(whereweare, '$'); 04457 if (nextthing) { 04458 switch (nextthing[1]) { 04459 case '{': 04460 nextvar = nextthing; 04461 pos = nextvar - whereweare; 04462 break; 04463 case '[': 04464 nextexp = nextthing; 04465 pos = nextexp - whereweare; 04466 break; 04467 default: 04468 pos = 1; 04469 } 04470 } 04471 04472 if (pos) { 04473 /* Can't copy more than 'count' bytes */ 04474 if (pos > count) 04475 pos = count; 04476 04477 /* Copy that many bytes */ 04478 memcpy(cp2, whereweare, pos); 04479 04480 count -= pos; 04481 cp2 += pos; 04482 whereweare += pos; 04483 *cp2 = 0; 04484 } 04485 04486 if (nextvar) { 04487 /* We have a variable. Find the start and end, and determine 04488 if we are going to have to recursively call ourselves on the 04489 contents */ 04490 vars = vare = nextvar + 2; 04491 brackets = 1; 04492 needsub = 0; 04493 04494 /* Find the end of it */ 04495 while (brackets && *vare) { 04496 if ((vare[0] == '$') && (vare[1] == '{')) { 04497 needsub++; 04498 } else if (vare[0] == '{') { 04499 brackets++; 04500 } else if (vare[0] == '}') { 04501 brackets--; 04502 } else if ((vare[0] == '$') && (vare[1] == '[')) 04503 needsub++; 04504 vare++; 04505 } 04506 if (brackets) 04507 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04508 len = vare - vars - 1; 04509 04510 /* Skip totally over variable string */ 04511 whereweare += (len + 3); 04512 04513 if (!var) 04514 var = ast_alloca(VAR_BUF_SIZE); 04515 04516 /* Store variable name (and truncate) */ 04517 ast_copy_string(var, vars, len + 1); 04518 04519 /* Substitute if necessary */ 04520 if (needsub) { 04521 size_t used; 04522 if (!ltmp) 04523 ltmp = ast_alloca(VAR_BUF_SIZE); 04524 04525 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04526 vars = ltmp; 04527 } else { 04528 vars = var; 04529 } 04530 04531 if (!workspace) 04532 workspace = ast_alloca(VAR_BUF_SIZE); 04533 04534 workspace[0] = '\0'; 04535 04536 parse_variable_name(vars, &offset, &offset2, &isfunction); 04537 if (isfunction) { 04538 /* Evaluate function */ 04539 if (c || !headp) 04540 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04541 else { 04542 struct varshead old; 04543 struct ast_channel *c = ast_dummy_channel_alloc(); 04544 if (c) { 04545 memcpy(&old, &c->varshead, sizeof(old)); 04546 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04547 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04548 /* Don't deallocate the varshead that was passed in */ 04549 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04550 c = ast_channel_unref(c); 04551 } else { 04552 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04553 } 04554 } 04555 ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)"); 04556 } else { 04557 /* Retrieve variable value */ 04558 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04559 } 04560 if (cp4) { 04561 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04562 04563 length = strlen(cp4); 04564 if (length > count) 04565 length = count; 04566 memcpy(cp2, cp4, length); 04567 count -= length; 04568 cp2 += length; 04569 *cp2 = 0; 04570 } 04571 } else if (nextexp) { 04572 /* We have an expression. Find the start and end, and determine 04573 if we are going to have to recursively call ourselves on the 04574 contents */ 04575 vars = vare = nextexp + 2; 04576 brackets = 1; 04577 needsub = 0; 04578 04579 /* Find the end of it */ 04580 while (brackets && *vare) { 04581 if ((vare[0] == '$') && (vare[1] == '[')) { 04582 needsub++; 04583 brackets++; 04584 vare++; 04585 } else if (vare[0] == '[') { 04586 brackets++; 04587 } else if (vare[0] == ']') { 04588 brackets--; 04589 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04590 needsub++; 04591 vare++; 04592 } 04593 vare++; 04594 } 04595 if (brackets) 04596 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04597 len = vare - vars - 1; 04598 04599 /* Skip totally over expression */ 04600 whereweare += (len + 3); 04601 04602 if (!var) 04603 var = ast_alloca(VAR_BUF_SIZE); 04604 04605 /* Store variable name (and truncate) */ 04606 ast_copy_string(var, vars, len + 1); 04607 04608 /* Substitute if necessary */ 04609 if (needsub) { 04610 size_t used; 04611 if (!ltmp) 04612 ltmp = ast_alloca(VAR_BUF_SIZE); 04613 04614 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04615 vars = ltmp; 04616 } else { 04617 vars = var; 04618 } 04619 04620 length = ast_expr(vars, cp2, count, c); 04621 04622 if (length) { 04623 ast_debug(1, "Expression result is '%s'\n", cp2); 04624 count -= length; 04625 cp2 += length; 04626 *cp2 = 0; 04627 } 04628 } 04629 } 04630 *used = cp2 - orig_cp2; 04631 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4639 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04640 { 04641 size_t used; 04642 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04643 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5864 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05865 { 05866 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05867 answer this channel and get it going. 05868 */ 05869 /* NOTE: 05870 The launcher of this function _MUST_ increment 'countcalls' 05871 before invoking the function; it will be decremented when the 05872 PBX has finished running on the channel 05873 */ 05874 struct ast_channel *c = data; 05875 05876 __ast_pbx_run(c, NULL); 05877 decrease_call_count(); 05878 05879 pthread_exit(NULL); 05880 05881 return NULL; 05882 }
static void print_app_docs | ( | struct ast_app * | aa, | |
int | fd | |||
) | [static] |
Definition at line 6473 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().
06474 { 06475 /* Maximum number of characters added by terminal coloring is 22 */ 06476 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 06477 char seealsotitle[40]; 06478 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 06479 char *seealso = NULL; 06480 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 06481 06482 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 06483 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 06484 06485 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 06486 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 06487 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 06488 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 06489 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 06490 06491 #ifdef AST_XML_DOCS 06492 if (aa->docsrc == AST_XML_DOC) { 06493 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 06494 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 06495 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 06496 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 06497 06498 if (!synopsis || !description || !arguments || !seealso) { 06499 goto return_cleanup; 06500 } 06501 } else 06502 #endif 06503 { 06504 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06505 synopsis = ast_malloc(synopsis_size); 06506 06507 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06508 description = ast_malloc(description_size); 06509 06510 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06511 arguments = ast_malloc(arguments_size); 06512 06513 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06514 seealso = ast_malloc(seealso_size); 06515 06516 if (!synopsis || !description || !arguments || !seealso) { 06517 goto return_cleanup; 06518 } 06519 06520 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 06521 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 06522 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 06523 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 06524 } 06525 06526 /* Handle the syntax the same for both XML and raw docs */ 06527 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06528 if (!(syntax = ast_malloc(syntax_size))) { 06529 goto return_cleanup; 06530 } 06531 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 06532 06533 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 06534 infotitle, syntitle, synopsis, destitle, description, 06535 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 06536 06537 return_cleanup: 06538 ast_free(description); 06539 ast_free(arguments); 06540 ast_free(synopsis); 06541 ast_free(seealso); 06542 ast_free(syntax); 06543 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 6910 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().
06911 { 06912 int prio = ast_get_extension_priority(e); 06913 if (prio == PRIORITY_HINT) { 06914 snprintf(buf, buflen, "hint: %s", 06915 ast_get_extension_app(e)); 06916 } else { 06917 snprintf(buf, buflen, "%d. %s(%s)", 06918 prio, ast_get_extension_app(e), 06919 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06920 } 06921 }
static int raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason, | |||
int | priority | |||
) | [static] |
Definition at line 3551 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().
03552 { 03553 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03554 struct pbx_exception *exception = NULL; 03555 03556 if (!ds) { 03557 ds = ast_datastore_alloc(&exception_store_info, NULL); 03558 if (!ds) 03559 return -1; 03560 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03561 ast_datastore_free(ds); 03562 return -1; 03563 } 03564 ds->data = exception; 03565 ast_channel_datastore_add(chan, ds); 03566 } else 03567 exception = ds->data; 03568 03569 ast_string_field_set(exception, reason, reason); 03570 ast_string_field_set(exception, context, chan->context); 03571 ast_string_field_set(exception, exten, chan->exten); 03572 exception->priority = chan->priority; 03573 set_ext_pri(chan, "e", priority); 03574 return 0; 03575 }
static int read_escalates | ( | const struct ast_custom_function * | acf | ) | [static] |
Returns true if given custom function escalates privileges on read.
acf | Custom function to query. |
Definition at line 3813 of file pbx.c.
References ast_custom_escalating_function::acf, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_escalating_function::read_escalates.
Referenced by is_read_allowed().
03813 { 03814 int res = 0; 03815 struct ast_custom_escalating_function *cur_escalation; 03816 03817 AST_RWLIST_RDLOCK(&escalation_root); 03818 AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) { 03819 if (cur_escalation->acf == acf) { 03820 res = cur_escalation->read_escalates; 03821 break; 03822 } 03823 } 03824 AST_RWLIST_UNLOCK(&escalation_root); 03825 return res; 03826 }
static void set_ext_pri | ( | struct ast_channel * | c, | |
const char * | exten, | |||
int | pri | |||
) | [static] |
helper function to set extension and priority
Definition at line 5436 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().
05437 { 05438 ast_channel_lock(c); 05439 ast_copy_string(c->exten, exten, sizeof(c->exten)); 05440 c->priority = pri; 05441 ast_channel_unlock(c); 05442 }
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 7079 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().
07080 { 07081 struct ast_context *c = NULL; 07082 int res = 0, old_total_exten = dpc->total_exten; 07083 07084 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 07085 07086 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 07087 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 07088 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 07089 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 07090 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 07091 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 07092 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 07093 ast_rdlock_contexts(); 07094 07095 /* walk all contexts ... */ 07096 while ( (c = ast_walk_contexts(c)) ) { 07097 int context_info_printed = 0; 07098 07099 if (context && strcmp(ast_get_context_name(c), context)) 07100 continue; /* skip this one, name doesn't match */ 07101 07102 dpc->context_existence = 1; 07103 07104 if (!c->pattern_tree) { 07105 /* Ignore check_return warning from Coverity for ast_exists_extension below */ 07106 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 07107 } 07108 07109 ast_rdlock_context(c); 07110 07111 dpc->total_context++; 07112 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 07113 ast_get_context_name(c), ast_get_context_registrar(c)); 07114 context_info_printed = 1; 07115 07116 if (c->pattern_tree) 07117 { 07118 cli_match_char_tree(c->pattern_tree, " ", fd); 07119 } else { 07120 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 07121 } 07122 07123 ast_unlock_context(c); 07124 07125 /* if we print something in context, make an empty line */ 07126 if (context_info_printed) 07127 ast_cli(fd, "\n"); 07128 } 07129 ast_unlock_contexts(); 07130 07131 return (dpc->total_exten == old_total_exten) ? -1 : res; 07132 }
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 6924 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().
06925 { 06926 struct ast_context *c = NULL; 06927 int res = 0, old_total_exten = dpc->total_exten; 06928 06929 ast_rdlock_contexts(); 06930 06931 /* walk all contexts ... */ 06932 while ( (c = ast_walk_contexts(c)) ) { 06933 struct ast_exten *e; 06934 struct ast_include *i; 06935 struct ast_ignorepat *ip; 06936 #ifndef LOW_MEMORY 06937 char buf[1024], buf2[1024]; 06938 #else 06939 char buf[256], buf2[256]; 06940 #endif 06941 int context_info_printed = 0; 06942 06943 if (context && strcmp(ast_get_context_name(c), context)) 06944 continue; /* skip this one, name doesn't match */ 06945 06946 dpc->context_existence = 1; 06947 06948 ast_rdlock_context(c); 06949 06950 /* are we looking for exten too? if yes, we print context 06951 * only if we find our extension. 06952 * Otherwise print context even if empty ? 06953 * XXX i am not sure how the rinclude is handled. 06954 * I think it ought to go inside. 06955 */ 06956 if (!exten) { 06957 dpc->total_context++; 06958 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06959 ast_get_context_name(c), ast_get_context_registrar(c)); 06960 context_info_printed = 1; 06961 } 06962 06963 /* walk extensions ... */ 06964 e = NULL; 06965 while ( (e = ast_walk_context_extensions(c, e)) ) { 06966 struct ast_exten *p; 06967 06968 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06969 continue; /* skip, extension match failed */ 06970 06971 dpc->extension_existence = 1; 06972 06973 /* may we print context info? */ 06974 if (!context_info_printed) { 06975 dpc->total_context++; 06976 if (rinclude) { /* TODO Print more info about rinclude */ 06977 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06978 ast_get_context_name(c), ast_get_context_registrar(c)); 06979 } else { 06980 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06981 ast_get_context_name(c), ast_get_context_registrar(c)); 06982 } 06983 context_info_printed = 1; 06984 } 06985 dpc->total_prio++; 06986 06987 /* write extension name and first peer */ 06988 if (e->matchcid == AST_EXT_MATCHCID_ON) 06989 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06990 else 06991 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06992 06993 print_ext(e, buf2, sizeof(buf2)); 06994 06995 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06996 ast_get_extension_registrar(e)); 06997 06998 dpc->total_exten++; 06999 /* walk next extension peers */ 07000 p = e; /* skip the first one, we already got it */ 07001 while ( (p = ast_walk_extension_priorities(e, p)) ) { 07002 const char *el = ast_get_extension_label(p); 07003 dpc->total_prio++; 07004 if (el) 07005 snprintf(buf, sizeof(buf), " [%s]", el); 07006 else 07007 buf[0] = '\0'; 07008 print_ext(p, buf2, sizeof(buf2)); 07009 07010 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 07011 ast_get_extension_registrar(p)); 07012 } 07013 } 07014 07015 /* walk included and write info ... */ 07016 i = NULL; 07017 while ( (i = ast_walk_context_includes(c, i)) ) { 07018 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 07019 if (exten) { 07020 /* Check all includes for the requested extension */ 07021 if (includecount >= AST_PBX_MAX_STACK) { 07022 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 07023 } else { 07024 int dupe = 0; 07025 int x; 07026 for (x = 0; x < includecount; x++) { 07027 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 07028 dupe++; 07029 break; 07030 } 07031 } 07032 if (!dupe) { 07033 includes[includecount] = ast_get_include_name(i); 07034 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 07035 } else { 07036 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 07037 } 07038 } 07039 } else { 07040 ast_cli(fd, " Include => %-45s [%s]\n", 07041 buf, ast_get_include_registrar(i)); 07042 } 07043 } 07044 07045 /* walk ignore patterns and write info ... */ 07046 ip = NULL; 07047 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 07048 const char *ipname = ast_get_ignorepat_name(ip); 07049 char ignorepat[AST_MAX_EXTENSION]; 07050 snprintf(buf, sizeof(buf), "'%s'", ipname); 07051 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 07052 if (!exten || ast_extension_match(ignorepat, exten)) { 07053 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 07054 buf, ast_get_ignorepat_registrar(ip)); 07055 } 07056 } 07057 if (!rinclude) { 07058 struct ast_sw *sw = NULL; 07059 while ( (sw = ast_walk_context_switches(c, sw)) ) { 07060 snprintf(buf, sizeof(buf), "'%s/%s'", 07061 ast_get_switch_name(sw), 07062 ast_get_switch_data(sw)); 07063 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 07064 buf, ast_get_switch_registrar(sw)); 07065 } 07066 } 07067 07068 ast_unlock_context(c); 07069 07070 /* if we print something in context, make an empty line */ 07071 if (context_info_printed) 07072 ast_cli(fd, "\n"); 07073 } 07074 ast_unlock_contexts(); 07075 07076 return (dpc->total_exten == old_total_exten) ? -1 : res; 07077 }
static int statecbs_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11293 of file pbx.c.
References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
11294 { 11295 const struct ast_state_cb *state_cb = obj; 11296 ast_state_cb_type change_cb = arg; 11297 11298 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; 11299 }
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 3301 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
03302 { 03303 char *ret = workspace; 03304 int lr; /* length of the input string after the copy */ 03305 03306 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 03307 03308 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 03309 03310 /* Quick check if no need to do anything */ 03311 if (offset == 0 && length >= lr) /* take the whole string */ 03312 return ret; 03313 03314 if (offset < 0) { /* translate negative offset into positive ones */ 03315 offset = lr + offset; 03316 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03317 offset = 0; 03318 } 03319 03320 /* too large offset result in empty string so we know what to return */ 03321 if (offset >= lr) 03322 return ret + lr; /* the final '\0' */ 03323 03324 ret += offset; /* move to the start position */ 03325 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 03326 ret[length] = '\0'; 03327 else if (length < 0) { 03328 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 03329 ret[lr + length - offset] = '\0'; 03330 else 03331 ret[0] = '\0'; 03332 } 03333 03334 return ret; 03335 }
static int thread_inhibits_escalations | ( | void | ) | [static] |
Indicates whether the current thread inhibits the execution of dangerous functions.
Definition at line 4052 of file pbx.c.
References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.
Referenced by is_read_allowed(), and is_write_allowed().
04053 { 04054 int *thread_inhibit_escalations; 04055 04056 thread_inhibit_escalations = ast_threadstorage_get( 04057 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations)); 04058 04059 if (thread_inhibit_escalations == NULL) { 04060 ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n"); 04061 /* On error, assume that we are inhibiting */ 04062 return 1; 04063 } 04064 04065 return *thread_inhibit_escalations; 04066 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1705 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().
01706 { 01707 struct match_char *m3; 01708 struct match_char *m4; 01709 struct ast_exten *e3; 01710 01711 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01712 return node->exten; 01713 } 01714 01715 if (node && node->x[0] == '!' && !node->x[1]) { 01716 return node->exten; 01717 } 01718 01719 if (!node || !node->next_char) { 01720 return NULL; 01721 } 01722 01723 m3 = node->next_char; 01724 01725 if (m3->exten) { 01726 return m3->exten; 01727 } 01728 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01729 if (m4->exten) { 01730 return m4->exten; 01731 } 01732 } 01733 for (m4 = m3; m4; m4 = m4->alt_char) { 01734 e3 = trie_find_next_match(m3); 01735 if (e3) { 01736 return e3; 01737 } 01738 } 01739 01740 return NULL; 01741 }
static void unload_pbx | ( | void | ) | [static] |
Definition at line 10883 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().
10884 { 10885 int x; 10886 10887 if (device_state_sub) { 10888 device_state_sub = ast_event_unsubscribe(device_state_sub); 10889 } 10890 if (device_state_tps) { 10891 ast_taskprocessor_unreference(device_state_tps); 10892 device_state_tps = NULL; 10893 } 10894 10895 /* Unregister builtin applications */ 10896 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10897 ast_unregister_application(builtins[x].name); 10898 } 10899 ast_manager_unregister("ShowDialPlan"); 10900 ast_cli_unregister_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10901 ast_custom_function_unregister(&exception_function); 10902 ast_custom_function_unregister(&testtime_function); 10903 ast_data_unregister(NULL); 10904 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 7691 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().
07692 { 07693 struct ast_context *context = NULL; 07694 struct ast_exten *eroot = NULL, *e = NULL; 07695 07696 ast_rdlock_contexts(); 07697 while ((context = ast_walk_contexts(context))) { 07698 while ((eroot = ast_walk_context_extensions(context, eroot))) { 07699 while ((e = ast_walk_extension_priorities(eroot, e))) { 07700 if (e->cached_app == app) 07701 e->cached_app = NULL; 07702 } 07703 } 07704 } 07705 ast_unlock_contexts(); 07706 07707 return; 07708 }
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 1609 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().
01610 { 01611 /* if this extension is marked as deleted, then skip this -- if it never shows 01612 on the scoreboard, it will never be found, nor will halt the traversal. */ 01613 if (deleted) 01614 return; 01615 board->total_specificity = spec; 01616 board->total_length = length; 01617 board->exten = exten; 01618 board->last_char = last; 01619 board->node = node; 01620 #ifdef NEED_DEBUG_HERE 01621 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01622 #endif 01623 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
const void * | data | |||
) | [static] |
Definition at line 9887 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().
09888 { 09889 int res; 09890 struct ast_frame *f; 09891 double waitsec; 09892 int waittime; 09893 09894 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 09895 waitsec = -1; 09896 if (waitsec > -1) { 09897 waittime = waitsec * 1000.0; 09898 ast_safe_sleep(chan, waittime); 09899 } else do { 09900 res = ast_waitfor(chan, -1); 09901 if (res < 0) 09902 return; 09903 f = ast_read(chan); 09904 if (f) 09905 ast_frfree(f); 09906 } while(f); 09907 }
static int write_escalates | ( | const struct ast_custom_function * | acf | ) | [static] |
Returns true if given custom function escalates privileges on write.
acf | Custom function to query. |
Definition at line 3835 of file pbx.c.
References ast_custom_escalating_function::acf, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_escalating_function::write_escalates.
Referenced by is_write_allowed().
03835 { 03836 int res = 0; 03837 struct ast_custom_escalating_function *cur_escalation; 03838 03839 AST_RWLIST_RDLOCK(&escalation_root); 03840 AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) { 03841 if (cur_escalation->acf == acf) { 03842 res = cur_escalation->write_escalates; 03843 break; 03844 } 03845 } 03846 AST_RWLIST_UNLOCK(&escalation_root); 03847 return res; 03848 }
int autofallthrough = 1 [static] |
Definition at line 1176 of file pbx.c.
Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().
struct ast_app_option background_opts[128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} [static] |
Definition at line 807 of file pbx.c.
Referenced by pbx_builtin_background().
struct pbx_builtin builtins[] [static] |
Declaration of builtin applications.
Referenced by load_pbx(), and unload_pbx().
ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock for the ast_context list.
Definition at line 1251 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 1256 of file pbx.c.
Referenced by ast_merge_contexts_and_delete(), and handle_statechange().
struct ast_context* contexts [static] |
Definition at line 1242 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 1243 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), find_context(), find_context_locked(), and pbx_shutdown().
int countcalls [static] |
Definition at line 1184 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
const char* const days[] [static] |
Definition at line 8290 of file pbx.c.
Referenced by ast_build_timing().
struct ast_event_sub* device_state_sub [static] |
Subscription for device state change events.
Definition at line 1181 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
{ .name = "EXCEPTION", .read = acf_exception_read, }
Definition at line 3603 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 3535 of file pbx.c.
Referenced by acf_exception_read(), and raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1177 of file pbx.c.
Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } [static] |
Definition at line 823 of file pbx.c.
Referenced by ast_extension_state2().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
Definition at line 1174 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [static] |
Definition at line 1173 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
struct ao2_container* hints [static] |
Definition at line 1271 of file pbx.c.
Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add_destroy(), ast_extension_state_del(), ast_merge_contexts_and_delete(), ast_pbx_init(), ast_remove_hint(), complete_core_show_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), and pbx_shutdown().
struct ast_data_handler hints_data_provider [static] |
{ .version = AST_DATA_HANDLER_VERSION, .get = hints_data_provider_get }
int live_dangerously [static] |
Set to true (non-zero) to globally allow all dangerous dialplan functions to run.
Definition at line 828 of file pbx.c.
Referenced by ast_readconfig().
ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 1183 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
const char* const months[] [static] |
Definition at line 8302 of file pbx.c.
Referenced by ast_build_timing().
char* overrideswitch = NULL [static] |
Definition at line 1178 of file pbx.c.
Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().
struct ast_cli_entry pbx_cli[] [static] |
Definition at line 7670 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 10877 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 10028 of file pbx.c.
Referenced by pbx_builtin_resetcdr().
struct ao2_container* statecbs [static] |
Definition at line 1273 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 1262 of file pbx.c.
Referenced by ast_extension_state_add_destroy().
struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } [static] |
Definition at line 822 of file pbx.c.
Referenced by pbx_find_extension().
struct ast_custom_function testtime_function [static] |
{ .name = "TESTTIME", .write = testtime_write, }
Definition at line 10119 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_threadstorage thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , } [static] |
Definition at line 828 of file pbx.c.
Referenced by ast_thread_inhibit_escalations(), and thread_inhibits_escalations().
int totalcalls [static] |
Definition at line 1185 of file pbx.c.
Referenced by ast_processed_calls(), increase_call_count(), and timing_read().
struct ast_app_option waitexten_opts[128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} [static] |
Definition at line 815 of file pbx.c.
Referenced by pbx_builtin_waitexten().