#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <sys/sysinfo.h>
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/cel.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
struct | acf_root |
struct | app_tmp |
struct | apps |
struct | ast_app |
ast_app: A registered application More... | |
struct | ast_context |
ast_context: An extension context More... | |
struct | ast_exten |
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
struct | ast_hint |
Structure for dial plan hints. More... | |
struct | ast_ignorepat |
ast_ignorepat: Ignore patterns in dial plan More... | |
struct | ast_include |
ast_include: include= support in extensions.conf More... | |
struct | ast_state_cb |
ast_state_cb: An extension state notify register item More... | |
struct | ast_sw |
ast_sw: Switch statement in extensions.conf More... | |
struct | async_stat |
struct | cfextension_states |
struct | dialplan_counters |
Counters for the show dialplan manager command. More... | |
struct | fake_context |
struct | match_char |
match_char: forms a syntax tree for quick matching of extension patterns More... | |
struct | pattern_node |
struct | pbx_builtin |
Declaration of builtin applications. More... | |
struct | pbx_exception |
struct | scoreboard |
struct | statechange |
struct | store_hint |
struct | store_hints |
struct | switches |
Defines | |
#define | AST_PBX_MAX_STACK 128 |
#define | BACKGROUND_MATCHEXTEN (1 << 2) |
#define | BACKGROUND_NOANSWER (1 << 1) |
#define | BACKGROUND_PLAYBACK (1 << 3) |
#define | BACKGROUND_SKIP (1 << 0) |
#define | 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. | |
static int | __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async) |
static void | __ast_internal_context_destroy (struct ast_context *con) |
static enum ast_pbx_result | __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args) |
static void | __init_extensionstate_buf (void) |
static void | __init_switch_data (void) |
static int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static int | acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
static int | acf_retrieve_docs (struct ast_custom_function *acf) |
static struct match_char * | add_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly) |
static struct match_char * | add_pattern_node (struct ast_context *con, struct match_char *current, 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) |
Add an extension to an extension context, this time with an ast_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). | |
ast_context * | ast_context_find (const char *name) |
Find a context. | |
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 a context include. | |
int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
Removes an include by an ast_context structure. | |
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. | |
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) |
Uses hint and devicestate callback to get the state of an extension. | |
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 string representation of the state of an extension. | |
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) |
Registers a state change callback. | |
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) |
Registers a state change callback with destructor. | |
int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
Deletes a registered state change callback by ID. | |
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) |
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) |
If an extension hint exists, return non-zero. | |
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) |
Register an 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) |
If an extension hint exists, return non-zero. | |
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_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. | |
ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
ast_context * | ast_walk_contexts (struct ast_context *con) |
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 *a, const char *b) |
the full routine to compare extensions in rules. | |
static int | ext_cmp1 (const char **p, unsigned char *bitwise) |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first. | |
static int | ext_strncpy (char *dst, const char *src, int len) |
copy a string skipping whitespace | |
static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static struct ast_context * | find_context (const char *context) |
lookup for a context with a given name, | |
static struct ast_context * | find_context_locked (const char *context) |
lookup for a context with a given name, | |
static 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) |
int | load_pbx (void) |
static int | lookup_name (const char *s, const char *const names[], int max) |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
static void | manager_dpsendack (struct mansession *s, const struct message *m) |
Send ack once. | |
static int | manager_show_dialplan (struct mansession *s, const struct message *m) |
Manager listing of dial plan. | |
static int | manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude) |
Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not. | |
static int | matchcid (const char *cidpattern, const char *callerid) |
static void | new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action) |
static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
extract offset:length from variable name. | |
static int | pbx_builtin_answer (struct ast_channel *, const char *) |
static int | pbx_builtin_background (struct ast_channel *, const char *) |
static int | pbx_builtin_busy (struct ast_channel *, const char *) |
void | pbx_builtin_clear_globals (void) |
static int | pbx_builtin_congestion (struct ast_channel *, const char *) |
static int | pbx_builtin_execiftime (struct ast_channel *, const char *) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
Return a pointer to the value of the corresponding channel variable. | |
static int | pbx_builtin_goto (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoif (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoiftime (struct ast_channel *, const char *) |
static int | pbx_builtin_hangup (struct ast_channel *, const char *) |
static int | pbx_builtin_importvar (struct ast_channel *, const char *) |
static int | pbx_builtin_incomplete (struct ast_channel *, const char *) |
static int | pbx_builtin_noop (struct ast_channel *, const char *) |
static int | pbx_builtin_proceeding (struct ast_channel *, const char *) |
static int | pbx_builtin_progress (struct ast_channel *, const char *) |
void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, without removing any previously set value. | |
int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason) |
static int | pbx_builtin_resetcdr (struct ast_channel *, const char *) |
static int | pbx_builtin_ringing (struct ast_channel *, const char *) |
static int | pbx_builtin_saycharacters (struct ast_channel *, const char *) |
static int | pbx_builtin_saydigits (struct ast_channel *, const char *) |
static int | pbx_builtin_saynumber (struct ast_channel *, const char *) |
static int | pbx_builtin_sayphonetic (struct ast_channel *, const char *) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
Create a human-readable string, specifying all variables and their corresponding values. | |
static int | pbx_builtin_setamaflags (struct ast_channel *, const char *) |
int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
static int | pbx_builtin_wait (struct ast_channel *, const char *) |
static int | pbx_builtin_waitexten (struct ast_channel *, const char *) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
static void | pbx_destroy (struct ast_pbx *p) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
Execute an application. | |
static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn) |
The return value depends on the action:. | |
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) |
ast_app * | pbx_findapp (const char *app) |
Look up an application. | |
static struct ast_switch * | pbx_findswitch (const char *sw) |
static int | pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async) |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
Retrieve the value of a builtin variable or variable from the channel variable stack. | |
int | pbx_set_autofallthrough (int newval) |
int | pbx_set_extenpatternmatchnew (int newval) |
void | pbx_set_overrideswitch (const char *newval) |
static void | pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
static void * | pbx_thread (void *data) |
static void | print_app_docs (struct ast_app *aa, int fd) |
static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
helper function to print an extension | |
static int | raise_exception (struct ast_channel *chan, const char *reason, int priority) |
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 struct ast_exten * | trie_find_next_match (struct match_char *node) |
static void | unreference_cached_app (struct ast_app *app) |
static void | update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node) |
static void | wait_for_hangup (struct ast_channel *chan, const void *data) |
Variables | |
static int | autofallthrough = 1 |
static struct ast_app_option | background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} |
static struct pbx_builtin | builtins [] |
Declaration of builtin applications. | |
static ast_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 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 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 },} |
Definition in file pbx.c.
#define AST_PBX_MAX_STACK 128 |
#define BACKGROUND_MATCHEXTEN (1 << 2) |
#define BACKGROUND_NOANSWER (1 << 1) |
#define BACKGROUND_PLAYBACK (1 << 3) |
#define BACKGROUND_SKIP (1 << 0) |
#define EXT_DATA_SIZE 8192 |
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 770 of file pbx.c.
Referenced by pbx_extension_helper().
#define HASH_EXTENHINT_SIZE 563 |
#define INC_DST_OVERFLOW_CHECK |
Referenced by get_pattern_node().
#define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
#define NEW_MATCHER_RECURSE |
#define VAR_BUF_SIZE 4096 |
Definition at line 775 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) |
#define WAITEXTEN_MOH (1 << 0) |
void __ast_context_destroy | ( | struct ast_context * | list, | |
struct ast_hashtab * | contexttab, | |||
struct ast_context * | con, | |||
const char * | registrar | |||
) |
Definition at line 9121 of file pbx.c.
References __ast_internal_context_destroy(), 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_sw::list, ast_context::name, ast_sw::next, ast_include::next, ast_ignorepat::next, ast_context::next, ast_exten::next, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, and ast_context::root_table.
Referenced by ast_context_destroy().
09122 { 09123 struct ast_context *tmp, *tmpl=NULL; 09124 struct ast_exten *exten_item, *prio_item; 09125 09126 for (tmp = list; tmp; ) { 09127 struct ast_context *next = NULL; /* next starting point */ 09128 /* The following code used to skip forward to the next 09129 context with matching registrar, but this didn't 09130 make sense; individual priorities registrar'd to 09131 the matching registrar could occur in any context! */ 09132 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 09133 if (con) { 09134 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 09135 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 09136 if ( !strcasecmp(tmp->name, con->name) ) { 09137 break; /* found it */ 09138 } 09139 } 09140 } 09141 09142 if (!tmp) /* not found, we are done */ 09143 break; 09144 ast_wrlock_context(tmp); 09145 09146 if (registrar) { 09147 /* then search thru and remove any extens that match registrar. */ 09148 struct ast_hashtab_iter *exten_iter; 09149 struct ast_hashtab_iter *prio_iter; 09150 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 09151 struct ast_include *i, *pi = NULL, *ni = NULL; 09152 struct ast_sw *sw = NULL; 09153 09154 /* remove any ignorepats whose registrar matches */ 09155 for (ip = tmp->ignorepats; ip; ip = ipn) { 09156 ipn = ip->next; 09157 if (!strcmp(ip->registrar, registrar)) { 09158 if (ipl) { 09159 ipl->next = ip->next; 09160 ast_free(ip); 09161 continue; /* don't change ipl */ 09162 } else { 09163 tmp->ignorepats = ip->next; 09164 ast_free(ip); 09165 continue; /* don't change ipl */ 09166 } 09167 } 09168 ipl = ip; 09169 } 09170 /* remove any includes whose registrar matches */ 09171 for (i = tmp->includes; i; i = ni) { 09172 ni = i->next; 09173 if (strcmp(i->registrar, registrar) == 0) { 09174 /* remove from list */ 09175 if (pi) { 09176 pi->next = i->next; 09177 /* free include */ 09178 ast_free(i); 09179 continue; /* don't change pi */ 09180 } else { 09181 tmp->includes = i->next; 09182 /* free include */ 09183 ast_free(i); 09184 continue; /* don't change pi */ 09185 } 09186 } 09187 pi = i; 09188 } 09189 /* remove any switches whose registrar matches */ 09190 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 09191 if (strcmp(sw->registrar,registrar) == 0) { 09192 AST_LIST_REMOVE_CURRENT(list); 09193 ast_free(sw); 09194 } 09195 } 09196 AST_LIST_TRAVERSE_SAFE_END; 09197 09198 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 09199 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 09200 while ((exten_item=ast_hashtab_next(exten_iter))) { 09201 int end_traversal = 1; 09202 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 09203 while ((prio_item=ast_hashtab_next(prio_iter))) { 09204 char extension[AST_MAX_EXTENSION]; 09205 char cidmatch[AST_MAX_EXTENSION]; 09206 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 09207 continue; 09208 } 09209 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 09210 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 09211 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 09212 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 09213 if (prio_item->cidmatch) { 09214 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 09215 } 09216 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1); 09217 } 09218 /* Explanation: 09219 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 09220 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 09221 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 09222 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 09223 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 09224 * free the iterator 09225 */ 09226 if (end_traversal) { 09227 ast_hashtab_end_traversal(prio_iter); 09228 } else { 09229 ast_free(prio_iter); 09230 } 09231 } 09232 ast_hashtab_end_traversal(exten_iter); 09233 } 09234 09235 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 09236 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 09237 another registrar. It's not empty if there are any extensions */ 09238 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 09239 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09240 ast_hashtab_remove_this_object(contexttab, tmp); 09241 09242 next = tmp->next; 09243 if (tmpl) 09244 tmpl->next = next; 09245 else 09246 contexts = next; 09247 /* Okay, now we're safe to let it go -- in a sense, we were 09248 ready to let it go as soon as we locked it. */ 09249 ast_unlock_context(tmp); 09250 __ast_internal_context_destroy(tmp); 09251 } else { 09252 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 09253 tmp->refcount, tmp->root); 09254 ast_unlock_context(tmp); 09255 next = tmp->next; 09256 tmpl = tmp; 09257 } 09258 } else if (con) { 09259 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 09260 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09261 ast_hashtab_remove_this_object(contexttab, tmp); 09262 09263 next = tmp->next; 09264 if (tmpl) 09265 tmpl->next = next; 09266 else 09267 contexts = next; 09268 /* Okay, now we're safe to let it go -- in a sense, we were 09269 ready to let it go as soon as we locked it. */ 09270 ast_unlock_context(tmp); 09271 __ast_internal_context_destroy(tmp); 09272 } 09273 09274 /* if we have a specific match, we are done, otherwise continue */ 09275 tmp = con ? NULL : next; 09276 } 09277 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3574 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by load_pbx().
03575 { 03576 struct ast_custom_function *cur; 03577 char tmps[80]; 03578 03579 if (!acf) { 03580 return -1; 03581 } 03582 03583 acf->mod = mod; 03584 #ifdef AST_XML_DOCS 03585 acf->docsrc = AST_STATIC_DOC; 03586 #endif 03587 03588 if (acf_retrieve_docs(acf)) { 03589 return -1; 03590 } 03591 03592 AST_RWLIST_WRLOCK(&acf_root); 03593 03594 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03595 if (!strcmp(acf->name, cur->name)) { 03596 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03597 AST_RWLIST_UNLOCK(&acf_root); 03598 return -1; 03599 } 03600 } 03601 03602 /* Store in alphabetical order */ 03603 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03604 if (strcasecmp(acf->name, cur->name) < 0) { 03605 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03606 break; 03607 } 03608 } 03609 AST_RWLIST_TRAVERSE_SAFE_END; 03610 03611 if (!cur) { 03612 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03613 } 03614 03615 AST_RWLIST_UNLOCK(&acf_root); 03616 03617 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03618 03619 return 0; 03620 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 10521 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::context, ast_channel::exten, and S_COR.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
10522 { 10523 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 10524 10525 if (!chan) 10526 return -2; 10527 10528 if (context == NULL) 10529 context = chan->context; 10530 if (exten == NULL) 10531 exten = chan->exten; 10532 10533 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 10534 if (ast_exists_extension(chan, context, exten, priority, 10535 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 10536 return goto_func(chan, context, exten, priority); 10537 else { 10538 return AST_PBX_GOTO_FAILED; 10539 } 10540 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 9074 of file pbx.c.
References ast_context::alts, ast_free, ast_hashtab_destroy(), AST_LIST_REMOVE_HEAD, ast_rwlock_destroy, destroy_exten(), destroy_pattern_tree(), el, ast_context::ignorepats, ast_context::includes, ast_context::lock, ast_exten::next, ast_ignorepat::next, ast_include::next, ast_context::pattern_tree, ast_exten::peer, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().
09075 { 09076 struct ast_include *tmpi; 09077 struct ast_sw *sw; 09078 struct ast_exten *e, *el, *en; 09079 struct ast_ignorepat *ipi; 09080 struct ast_context *tmp = con; 09081 09082 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 09083 struct ast_include *tmpil = tmpi; 09084 tmpi = tmpi->next; 09085 ast_free(tmpil); 09086 } 09087 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 09088 struct ast_ignorepat *ipl = ipi; 09089 ipi = ipi->next; 09090 ast_free(ipl); 09091 } 09092 if (tmp->registrar) 09093 ast_free(tmp->registrar); 09094 09095 /* destroy the hash tabs */ 09096 if (tmp->root_table) { 09097 ast_hashtab_destroy(tmp->root_table, 0); 09098 } 09099 /* and destroy the pattern tree */ 09100 if (tmp->pattern_tree) 09101 destroy_pattern_tree(tmp->pattern_tree); 09102 09103 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 09104 ast_free(sw); 09105 for (e = tmp->root; e;) { 09106 for (en = e->peer; en;) { 09107 el = en; 09108 en = en->peer; 09109 destroy_exten(el); 09110 } 09111 el = e; 09112 e = e->next; 09113 destroy_exten(el); 09114 } 09115 tmp->root = NULL; 09116 ast_rwlock_destroy(&tmp->lock); 09117 ast_free(tmp); 09118 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 4933 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_update(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_copy_string(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_free, ast_log(), ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verb, ast_channel::caller, ast_channel::cdr, ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_channel::name, ast_party_id::number, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeoutms, S_COR, set_ext_pri(), ast_party_number::str, and ast_party_number::valid.
Referenced by ast_pbx_run_args(), and pbx_thread().
04935 { 04936 int found = 0; /* set if we find at least one match */ 04937 int res = 0; 04938 int autoloopflag; 04939 int error = 0; /* set an error conditions */ 04940 04941 /* A little initial setup here */ 04942 if (c->pbx) { 04943 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 04944 /* XXX and now what ? */ 04945 ast_free(c->pbx); 04946 } 04947 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 04948 return -1; 04949 /* Set reasonable defaults */ 04950 c->pbx->rtimeoutms = 10000; 04951 c->pbx->dtimeoutms = 5000; 04952 04953 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 04954 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 04955 04956 /* Start by trying whatever the channel is set to */ 04957 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 04958 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04959 /* If not successful fall back to 's' */ 04960 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); 04961 /* XXX the original code used the existing priority in the call to 04962 * ast_exists_extension(), and reset it to 1 afterwards. 04963 * I believe the correct thing is to set it to 1 immediately. 04964 */ 04965 set_ext_pri(c, "s", 1); 04966 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 04967 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04968 /* JK02: And finally back to default if everything else failed */ 04969 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); 04970 ast_copy_string(c->context, "default", sizeof(c->context)); 04971 } 04972 } 04973 ast_channel_lock(c); 04974 if (c->cdr) { 04975 /* allow CDR variables that have been collected after channel was created to be visible during call */ 04976 ast_cdr_update(c); 04977 } 04978 ast_channel_unlock(c); 04979 for (;;) { 04980 char dst_exten[256]; /* buffer to accumulate digits */ 04981 int pos = 0; /* XXX should check bounds */ 04982 int digit = 0; 04983 int invalid = 0; 04984 int timeout = 0; 04985 04986 /* loop on priorities in this context/exten */ 04987 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 04988 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 04989 &found, 1))) { 04990 if (!ast_check_hangup(c)) { 04991 ++c->priority; 04992 continue; 04993 } 04994 04995 /* Check softhangup flags. */ 04996 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04997 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 04998 continue; 04999 } 05000 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05001 if (ast_exists_extension(c, c->context, "T", 1, 05002 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05003 set_ext_pri(c, "T", 1); 05004 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05005 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05006 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05007 continue; 05008 } else if (ast_exists_extension(c, c->context, "e", 1, 05009 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05010 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05011 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05012 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05013 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05014 continue; 05015 } 05016 05017 /* Call timed out with no special extension to jump to. */ 05018 error = 1; 05019 break; 05020 } 05021 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 05022 c->exten, c->priority); 05023 error = 1; 05024 break; 05025 } /* end while - from here on we can use 'break' to go out */ 05026 if (found && res) { 05027 /* Something bad happened, or a hangup has been requested. */ 05028 if (strchr("0123456789ABCDEF*#", res)) { 05029 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 05030 pos = 0; 05031 dst_exten[pos++] = digit = res; 05032 dst_exten[pos] = '\0'; 05033 } else if (res == AST_PBX_INCOMPLETE) { 05034 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05035 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05036 05037 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 05038 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 05039 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05040 invalid = 1; 05041 } else { 05042 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 05043 digit = 1; 05044 pos = strlen(dst_exten); 05045 } 05046 } else { 05047 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05048 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05049 05050 if ((res == AST_PBX_ERROR) 05051 && ast_exists_extension(c, c->context, "e", 1, 05052 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05053 /* if we are already on the 'e' exten, don't jump to it again */ 05054 if (!strcmp(c->exten, "e")) { 05055 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); 05056 error = 1; 05057 } else { 05058 raise_exception(c, "ERROR", 1); 05059 continue; 05060 } 05061 } 05062 05063 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05064 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05065 continue; 05066 } 05067 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05068 if (ast_exists_extension(c, c->context, "T", 1, 05069 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05070 set_ext_pri(c, "T", 1); 05071 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05072 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05073 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05074 continue; 05075 } else if (ast_exists_extension(c, c->context, "e", 1, 05076 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05077 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05078 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05079 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05080 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05081 continue; 05082 } 05083 /* Call timed out with no special extension to jump to. */ 05084 } 05085 ast_channel_lock(c); 05086 if (c->cdr) { 05087 ast_cdr_update(c); 05088 } 05089 ast_channel_unlock(c); 05090 error = 1; 05091 break; 05092 } 05093 } 05094 if (error) 05095 break; 05096 05097 /*!\note 05098 * We get here on a failure of some kind: non-existing extension or 05099 * hangup. We have options, here. We can either catch the failure 05100 * and continue, or we can drop out entirely. */ 05101 05102 if (invalid 05103 || !ast_exists_extension(c, c->context, c->exten, 1, 05104 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05105 /*!\note 05106 * If there is no match at priority 1, it is not a valid extension anymore. 05107 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 05108 * neither exist. 05109 */ 05110 if (ast_exists_extension(c, c->context, "i", 1, 05111 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05112 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 05113 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 05114 set_ext_pri(c, "i", 1); 05115 } else if (ast_exists_extension(c, c->context, "e", 1, 05116 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05117 raise_exception(c, "INVALID", 1); 05118 } else { 05119 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 05120 c->name, c->exten, c->context); 05121 error = 1; /* we know what to do with it */ 05122 break; 05123 } 05124 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05125 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 05126 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05127 } else { /* keypress received, get more digits for a full extension */ 05128 int waittime = 0; 05129 if (digit) 05130 waittime = c->pbx->dtimeoutms; 05131 else if (!autofallthrough) 05132 waittime = c->pbx->rtimeoutms; 05133 if (!waittime) { 05134 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 05135 if (!status) 05136 status = "UNKNOWN"; 05137 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 05138 if (!strcasecmp(status, "CONGESTION")) 05139 res = pbx_builtin_congestion(c, "10"); 05140 else if (!strcasecmp(status, "CHANUNAVAIL")) 05141 res = pbx_builtin_congestion(c, "10"); 05142 else if (!strcasecmp(status, "BUSY")) 05143 res = pbx_builtin_busy(c, "10"); 05144 error = 1; /* XXX disable message */ 05145 break; /* exit from the 'for' loop */ 05146 } 05147 05148 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 05149 break; 05150 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 05151 timeout = 1; 05152 if (!timeout 05153 && ast_exists_extension(c, c->context, dst_exten, 1, 05154 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 05155 set_ext_pri(c, dst_exten, 1); 05156 } else { 05157 /* No such extension */ 05158 if (!timeout && !ast_strlen_zero(dst_exten)) { 05159 /* An invalid extension */ 05160 if (ast_exists_extension(c, c->context, "i", 1, 05161 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05162 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 05163 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 05164 set_ext_pri(c, "i", 1); 05165 } else if (ast_exists_extension(c, c->context, "e", 1, 05166 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05167 raise_exception(c, "INVALID", 1); 05168 } else { 05169 ast_log(LOG_WARNING, 05170 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", 05171 dst_exten, c->context); 05172 found = 1; /* XXX disable message */ 05173 break; 05174 } 05175 } else { 05176 /* A simple timeout */ 05177 if (ast_exists_extension(c, c->context, "t", 1, 05178 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05179 ast_verb(3, "Timeout on %s\n", c->name); 05180 set_ext_pri(c, "t", 1); 05181 } else if (ast_exists_extension(c, c->context, "e", 1, 05182 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05183 raise_exception(c, "RESPONSETIMEOUT", 1); 05184 } else { 05185 ast_log(LOG_WARNING, 05186 "Timeout, but no rule 't' or 'e' in context '%s'\n", 05187 c->context); 05188 found = 1; /* XXX disable message */ 05189 break; 05190 } 05191 } 05192 } 05193 ast_channel_lock(c); 05194 if (c->cdr) { 05195 ast_verb(2, "CDR updated on %s\n",c->name); 05196 ast_cdr_update(c); 05197 } 05198 ast_channel_unlock(c); 05199 } 05200 } 05201 05202 if (!found && !error) { 05203 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 05204 } 05205 05206 if (!args || !args->no_hangup_chan) { 05207 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 05208 } 05209 05210 if ((!args || !args->no_hangup_chan) 05211 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 05212 && ast_exists_extension(c, c->context, "h", 1, 05213 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05214 set_ext_pri(c, "h", 1); 05215 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 05216 ast_cdr_end(c->cdr); 05217 } 05218 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05219 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05220 &found, 1)) == 0) { 05221 c->priority++; 05222 } 05223 if (found && res) { 05224 /* Something bad happened, or a hangup has been requested. */ 05225 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05226 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05227 } 05228 } 05229 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 05230 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 05231 pbx_destroy(c->pbx); 05232 c->pbx = NULL; 05233 05234 if (!args || !args->no_hangup_chan) { 05235 ast_hangup(c); 05236 } 05237 05238 return 0; 05239 }
static void __init_extensionstate_buf | ( | void | ) | [static] |
static void __init_switch_data | ( | void | ) | [static] |
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2452 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02453 { 02454 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02455 02456 #ifdef NEED_DEBUG_HERE 02457 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02458 #endif 02459 02460 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 02461 #ifdef NEED_DEBUG_HERE 02462 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02463 #endif 02464 return 1; 02465 } 02466 02467 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02468 int ld = strlen(data), lp = strlen(pattern); 02469 02470 if (lp < ld) { /* pattern too short, cannot match */ 02471 #ifdef NEED_DEBUG_HERE 02472 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02473 #endif 02474 return 0; 02475 } 02476 /* depending on the mode, accept full or partial match or both */ 02477 if (mode == E_MATCH) { 02478 #ifdef NEED_DEBUG_HERE 02479 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 02480 #endif 02481 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 02482 } 02483 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 02484 #ifdef NEED_DEBUG_HERE 02485 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02486 #endif 02487 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02488 } else { 02489 #ifdef NEED_DEBUG_HERE 02490 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02491 #endif 02492 return 0; 02493 } 02494 } 02495 pattern++; /* skip leading _ */ 02496 /* 02497 * XXX below we stop at '/' which is a separator for the CID info. However we should 02498 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02499 */ 02500 while (*data && *pattern && *pattern != '/') { 02501 const char *end; 02502 02503 if (*data == '-') { /* skip '-' in data (just a separator) */ 02504 data++; 02505 continue; 02506 } 02507 switch (toupper(*pattern)) { 02508 case '[': /* a range */ 02509 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 02510 if (end == NULL) { 02511 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02512 return 0; /* unconditional failure */ 02513 } 02514 for (pattern++; pattern != end; pattern++) { 02515 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02516 if (*data >= pattern[0] && *data <= pattern[2]) 02517 break; /* match found */ 02518 else { 02519 pattern += 2; /* skip a total of 3 chars */ 02520 continue; 02521 } 02522 } else if (*data == pattern[0]) 02523 break; /* match found */ 02524 } 02525 if (pattern == end) { 02526 #ifdef NEED_DEBUG_HERE 02527 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 02528 #endif 02529 return 0; 02530 } 02531 pattern = end; /* skip and continue */ 02532 break; 02533 case 'N': 02534 if (*data < '2' || *data > '9') { 02535 #ifdef NEED_DEBUG_HERE 02536 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 02537 #endif 02538 return 0; 02539 } 02540 break; 02541 case 'X': 02542 if (*data < '0' || *data > '9') { 02543 #ifdef NEED_DEBUG_HERE 02544 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 02545 #endif 02546 return 0; 02547 } 02548 break; 02549 case 'Z': 02550 if (*data < '1' || *data > '9') { 02551 #ifdef NEED_DEBUG_HERE 02552 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 02553 #endif 02554 return 0; 02555 } 02556 break; 02557 case '.': /* Must match, even with more digits */ 02558 #ifdef NEED_DEBUG_HERE 02559 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02560 #endif 02561 return 1; 02562 case '!': /* Early match */ 02563 #ifdef NEED_DEBUG_HERE 02564 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02565 #endif 02566 return 2; 02567 case ' ': 02568 case '-': /* Ignore these in patterns */ 02569 data--; /* compensate the final data++ */ 02570 break; 02571 default: 02572 if (*data != *pattern) { 02573 #ifdef NEED_DEBUG_HERE 02574 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02575 #endif 02576 return 0; 02577 } 02578 } 02579 data++; 02580 pattern++; 02581 } 02582 if (*data) /* data longer than pattern, no match */ { 02583 #ifdef NEED_DEBUG_HERE 02584 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02585 #endif 02586 return 0; 02587 } 02588 02589 /* 02590 * match so far, but ran off the end of the data. 02591 * Depending on what is next, determine match or not. 02592 */ 02593 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02594 #ifdef NEED_DEBUG_HERE 02595 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02596 #endif 02597 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02598 } else if (*pattern == '!') { /* early match */ 02599 #ifdef NEED_DEBUG_HERE 02600 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02601 #endif 02602 return 2; 02603 } else { /* partial match */ 02604 #ifdef NEED_DEBUG_HERE 02605 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02606 #endif 02607 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02608 } 02609 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 3311 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.
03312 { 03313 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03314 struct pbx_exception *exception = NULL; 03315 if (!ds || !ds->data) 03316 return -1; 03317 exception = ds->data; 03318 if (!strcasecmp(data, "REASON")) 03319 ast_copy_string(buf, exception->reason, buflen); 03320 else if (!strcasecmp(data, "CONTEXT")) 03321 ast_copy_string(buf, exception->context, buflen); 03322 else if (!strncasecmp(data, "EXTEN", 5)) 03323 ast_copy_string(buf, exception->exten, buflen); 03324 else if (!strcasecmp(data, "PRIORITY")) 03325 snprintf(buf, buflen, "%d", exception->priority); 03326 else 03327 return -1; 03328 return 0; 03329 }
static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3529 of file pbx.c.
References ast_custom_function::arguments, 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::desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, and ast_custom_function::syntax.
Referenced by __ast_custom_function_register().
03530 { 03531 #ifdef AST_XML_DOCS 03532 char *tmpxml; 03533 03534 /* Let's try to find it in the Documentation XML */ 03535 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03536 return 0; 03537 } 03538 03539 if (ast_string_field_init(acf, 128)) { 03540 return -1; 03541 } 03542 03543 /* load synopsis */ 03544 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); 03545 ast_string_field_set(acf, synopsis, tmpxml); 03546 ast_free(tmpxml); 03547 03548 /* load description */ 03549 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); 03550 ast_string_field_set(acf, desc, tmpxml); 03551 ast_free(tmpxml); 03552 03553 /* load syntax */ 03554 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod)); 03555 ast_string_field_set(acf, syntax, tmpxml); 03556 ast_free(tmpxml); 03557 03558 /* load arguments */ 03559 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod)); 03560 ast_string_field_set(acf, arguments, tmpxml); 03561 ast_free(tmpxml); 03562 03563 /* load seealso */ 03564 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod)); 03565 ast_string_field_set(acf, seealso, tmpxml); 03566 ast_free(tmpxml); 03567 03568 acf->docsrc = AST_XML_DOC; 03569 #endif 03570 03571 return 0; 03572 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static] |
Definition at line 2130 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 ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().
02131 { 02132 struct match_char *m1 = NULL; 02133 struct match_char *m2 = NULL; 02134 struct match_char **m0; 02135 const char *pos; 02136 int already; 02137 int pattern = 0; 02138 int idx_cur; 02139 int idx_next; 02140 char extenbuf[512]; 02141 struct pattern_node pat_node[2]; 02142 02143 if (e1->matchcid) { 02144 if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) { 02145 ast_log(LOG_ERROR, 02146 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", 02147 e1->exten, e1->cidmatch); 02148 return NULL; 02149 } 02150 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */ 02151 } else { 02152 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 02153 } 02154 02155 #ifdef NEED_DEBUG 02156 ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf); 02157 #endif 02158 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 02159 m0 = &con->pattern_tree; 02160 already = 1; 02161 02162 pos = extenbuf; 02163 if (*pos == '_') { 02164 pattern = 1; 02165 ++pos; 02166 } 02167 idx_cur = 0; 02168 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf); 02169 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) { 02170 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node); 02171 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf); 02172 02173 /* See about adding node to tree. */ 02174 m2 = NULL; 02175 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern)) 02176 && m2->next_char) { 02177 if (!pat_node[idx_next].buf[0]) { 02178 /* 02179 * This is the end of the pattern, but not the end of the tree. 02180 * Mark this node with the exten... a shorter pattern might win 02181 * if the longer one doesn't match. 02182 */ 02183 if (findonly) { 02184 return m2; 02185 } 02186 if (m2->exten) { 02187 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02188 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02189 } 02190 m2->exten = e1; 02191 m2->deleted = 0; 02192 } 02193 m1 = m2->next_char; /* m1 points to the node to compare against */ 02194 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02195 } else { /* not already OR not m2 OR nor m2->next_char */ 02196 if (m2) { 02197 if (findonly) { 02198 return m2; 02199 } 02200 m1 = m2; /* while m0 stays the same */ 02201 } else { 02202 if (findonly) { 02203 return m1; 02204 } 02205 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0); 02206 if (!m1) { /* m1 is the node just added */ 02207 return NULL; 02208 } 02209 m0 = &m1->next_char; 02210 } 02211 if (!pat_node[idx_next].buf[0]) { 02212 if (m2 && m2->exten) { 02213 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02214 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02215 } 02216 m1->deleted = 0; 02217 m1->exten = e1; 02218 } 02219 02220 /* The 'already' variable is a mini-optimization designed to make it so that we 02221 * don't have to call already_in_tree when we know it will return false. 02222 */ 02223 already = 0; 02224 } 02225 } 02226 return m1; 02227 }
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] |
Definition at line 1932 of file pbx.c.
References ast_calloc, pattern_node::buf, insert_in_next_chars_alt_char_list(), match_char::next_char, ast_context::pattern_tree, and pattern_node::specif.
Referenced by add_exten_to_pattern_tree().
01933 { 01934 struct match_char *m; 01935 01936 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) { 01937 return NULL; 01938 } 01939 01940 /* strcpy is safe here since we know its size and have allocated 01941 * just enough space for when we allocated m 01942 */ 01943 strcpy(m->x, pattern->buf); 01944 01945 /* the specificity scores are the same as used in the old 01946 pattern matcher. */ 01947 m->is_pattern = is_pattern; 01948 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') { 01949 m->specificity = 0x0832; 01950 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') { 01951 m->specificity = 0x0931; 01952 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') { 01953 m->specificity = 0x0a30; 01954 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') { 01955 m->specificity = 0x18000; 01956 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') { 01957 m->specificity = 0x28000; 01958 } else { 01959 m->specificity = pattern->specif; 01960 } 01961 01962 if (!con->pattern_tree) { 01963 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01964 } else { 01965 if (already) { /* switch to the new regime (traversing vs appending)*/ 01966 insert_in_next_chars_alt_char_list(nextcharptr, m); 01967 } else { 01968 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01969 } 01970 } 01971 01972 return m; 01973 }
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 8277 of file pbx.c.
References ast_log(), ast_exten::exten, ast_exten::label, LOG_WARNING, ast_context::name, ast_exten::peer, and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
08279 { 08280 struct ast_exten *ep; 08281 struct ast_exten *eh=e; 08282 int repeated_label = 0; /* Track if this label is a repeat, assume no. */ 08283 08284 for (ep = NULL; e ; ep = e, e = e->peer) { 08285 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) { 08286 ast_log(LOG_WARNING, "Extension '%s', priority %d in '%s', label '%s' already in use at " 08287 "priority %d\n", tmp->exten, tmp->priority, con->name, tmp->label, e->priority); 08288 repeated_label = 1; 08289 } 08290 if (e->priority >= tmp->priority) { 08291 break; 08292 } 08293 } 08294 08295 if (repeated_label) { /* Discard the label since it's a repeat. */ 08296 tmp->label = NULL; 08297 } 08298 08299 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 08300 ast_hashtab_insert_safe(eh->peer_table, tmp); 08301 08302 if (tmp->label) { 08303 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08304 } 08305 ep->peer = tmp; 08306 return 0; /* success */ 08307 } 08308 if (e->priority == tmp->priority) { 08309 /* Can't have something exactly the same. Is this a 08310 replacement? If so, replace, otherwise, bonk. */ 08311 if (!replace) { 08312 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 08313 if (tmp->datad) { 08314 tmp->datad(tmp->data); 08315 /* if you free this, null it out */ 08316 tmp->data = NULL; 08317 } 08318 08319 ast_free(tmp); 08320 return -1; 08321 } 08322 /* we are replacing e, so copy the link fields and then update 08323 * whoever pointed to e to point to us 08324 */ 08325 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 08326 tmp->peer = e->peer; /* always meaningful */ 08327 if (ep) { /* We're in the peer list, just insert ourselves */ 08328 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 08329 08330 if (e->label) { 08331 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 08332 } 08333 08334 ast_hashtab_insert_safe(eh->peer_table,tmp); 08335 if (tmp->label) { 08336 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 08337 } 08338 08339 ep->peer = tmp; 08340 } else if (el) { /* We're the first extension. Take over e's functions */ 08341 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08342 tmp->peer_table = e->peer_table; 08343 tmp->peer_label_table = e->peer_label_table; 08344 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 08345 ast_hashtab_insert_safe(tmp->peer_table,tmp); 08346 if (e->label) { 08347 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08348 } 08349 if (tmp->label) { 08350 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08351 } 08352 08353 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08354 ast_hashtab_insert_safe(con->root_table, tmp); 08355 el->next = tmp; 08356 /* The pattern trie points to this exten; replace the pointer, 08357 and all will be well */ 08358 if (x) { /* if the trie isn't formed yet, don't sweat this */ 08359 if (x->exten) { /* this test for safety purposes */ 08360 x->exten = tmp; /* replace what would become a bad pointer */ 08361 } else { 08362 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08363 } 08364 } 08365 } else { /* We're the very first extension. */ 08366 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08367 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08368 ast_hashtab_insert_safe(con->root_table, tmp); 08369 tmp->peer_table = e->peer_table; 08370 tmp->peer_label_table = e->peer_label_table; 08371 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 08372 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08373 if (e->label) { 08374 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08375 } 08376 if (tmp->label) { 08377 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08378 } 08379 08380 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08381 ast_hashtab_insert_safe(con->root_table, tmp); 08382 con->root = tmp; 08383 /* The pattern trie points to this exten; replace the pointer, 08384 and all will be well */ 08385 if (x) { /* if the trie isn't formed yet; no problem */ 08386 if (x->exten) { /* this test for safety purposes */ 08387 x->exten = tmp; /* replace what would become a bad pointer */ 08388 } else { 08389 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08390 } 08391 } 08392 } 08393 if (tmp->priority == PRIORITY_HINT) 08394 ast_change_hint(e,tmp); 08395 /* Destroy the old one */ 08396 if (e->datad) 08397 e->datad(e->data); 08398 ast_free(e); 08399 } else { /* Slip ourselves in just before e */ 08400 tmp->peer = e; 08401 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 08402 if (ep) { /* Easy enough, we're just in the peer list */ 08403 if (tmp->label) { 08404 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08405 } 08406 ast_hashtab_insert_safe(eh->peer_table, tmp); 08407 ep->peer = tmp; 08408 } else { /* we are the first in some peer list, so link in the ext list */ 08409 tmp->peer_table = e->peer_table; 08410 tmp->peer_label_table = e->peer_label_table; 08411 e->peer_table = 0; 08412 e->peer_label_table = 0; 08413 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08414 if (tmp->label) { 08415 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08416 } 08417 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08418 ast_hashtab_insert_safe(con->root_table, tmp); 08419 if (el) 08420 el->next = tmp; /* in the middle... */ 08421 else 08422 con->root = tmp; /* ... or at the head */ 08423 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 08424 } 08425 /* And immediately return success. */ 08426 if (tmp->priority == PRIORITY_HINT) { 08427 ast_add_hint(tmp); 08428 } 08429 } 08430 return 0; 08431 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat, | |||
int | is_pattern | |||
) | [static] |
Definition at line 1870 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01871 { 01872 struct match_char *t; 01873 01874 if (!current) { 01875 return 0; 01876 } 01877 01878 for (t = current; t; t = t->alt_char) { 01879 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01880 return t; 01881 } 01882 } 01883 01884 return 0; 01885 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5387 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05388 { 05389 return countcalls; 05390 }
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 8112 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().
08115 { 08116 int ret = -1; 08117 struct ast_context *c; 08118 08119 c = find_context_locked(context); 08120 if (c) { 08121 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08122 application, data, datad, registrar); 08123 ast_unlock_contexts(); 08124 } 08125 08126 return ret; 08127 }
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 | |||
) |
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 8458 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), and pbx_load_users().
08462 { 08463 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08464 application, data, datad, registrar, 1); 08465 }
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 8474 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_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().
08478 { 08479 /* 08480 * Sort extensions (or patterns) according to the rules indicated above. 08481 * These are implemented by the function ext_cmp()). 08482 * All priorities for the same ext/pattern/cid are kept in a list, 08483 * using the 'peer' field as a link field.. 08484 */ 08485 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 08486 int res; 08487 int length; 08488 char *p; 08489 char expand_buf[VAR_BUF_SIZE]; 08490 struct ast_exten dummy_exten = {0}; 08491 char dummy_name[1024]; 08492 08493 if (ast_strlen_zero(extension)) { 08494 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", 08495 con->name); 08496 return -1; 08497 } 08498 08499 /* If we are adding a hint evalulate in variables and global variables */ 08500 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 08501 struct ast_channel *c = ast_dummy_channel_alloc(); 08502 08503 if (c) { 08504 ast_copy_string(c->exten, extension, sizeof(c->exten)); 08505 ast_copy_string(c->context, con->name, sizeof(c->context)); 08506 } 08507 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 08508 application = expand_buf; 08509 if (c) { 08510 ast_channel_unref(c); 08511 } 08512 } 08513 08514 length = sizeof(struct ast_exten); 08515 length += strlen(extension) + 1; 08516 length += strlen(application) + 1; 08517 if (label) 08518 length += strlen(label) + 1; 08519 if (callerid) 08520 length += strlen(callerid) + 1; 08521 else 08522 length ++; /* just the '\0' */ 08523 08524 /* Be optimistic: Build the extension structure first */ 08525 if (!(tmp = ast_calloc(1, length))) 08526 return -1; 08527 08528 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 08529 label = 0; 08530 08531 /* use p as dst in assignments, as the fields are const char * */ 08532 p = tmp->stuff; 08533 if (label) { 08534 tmp->label = p; 08535 strcpy(p, label); 08536 p += strlen(label) + 1; 08537 } 08538 tmp->exten = p; 08539 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 08540 tmp->priority = priority; 08541 tmp->cidmatch = p; /* but use p for assignments below */ 08542 08543 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 08544 if (callerid) { 08545 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 08546 tmp->matchcid = 1; 08547 } else { 08548 *p++ = '\0'; 08549 tmp->matchcid = 0; 08550 } 08551 tmp->app = p; 08552 strcpy(p, application); 08553 tmp->parent = con; 08554 tmp->data = data; 08555 tmp->datad = datad; 08556 tmp->registrar = registrar; 08557 08558 if (lock_context) { 08559 ast_wrlock_context(con); 08560 } 08561 08562 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 08563 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 08564 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 08565 dummy_exten.exten = dummy_name; 08566 dummy_exten.matchcid = 0; 08567 dummy_exten.cidmatch = 0; 08568 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 08569 if (!tmp2) { 08570 /* hmmm, not in the trie; */ 08571 add_exten_to_pattern_tree(con, tmp, 0); 08572 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 08573 } 08574 } 08575 res = 0; /* some compilers will think it is uninitialized otherwise */ 08576 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 08577 res = ext_cmp(e->exten, tmp->exten); 08578 if (res == 0) { /* extension match, now look at cidmatch */ 08579 if (!e->matchcid && !tmp->matchcid) 08580 res = 0; 08581 else if (tmp->matchcid && !e->matchcid) 08582 res = 1; 08583 else if (e->matchcid && !tmp->matchcid) 08584 res = -1; 08585 else 08586 res = ext_cmp(e->cidmatch, tmp->cidmatch); 08587 } 08588 if (res >= 0) 08589 break; 08590 } 08591 if (e && res == 0) { /* exact match, insert in the priority chain */ 08592 res = add_priority(con, tmp, el, e, replace); 08593 if (lock_context) { 08594 ast_unlock_context(con); 08595 } 08596 if (res < 0) { 08597 errno = EEXIST; /* XXX do we care ? */ 08598 return 0; /* XXX should we return -1 maybe ? */ 08599 } 08600 } else { 08601 /* 08602 * not an exact match, this is the first entry with this pattern, 08603 * so insert in the main list right before 'e' (if any) 08604 */ 08605 tmp->next = e; 08606 if (el) { /* there is another exten already in this context */ 08607 el->next = tmp; 08608 tmp->peer_table = ast_hashtab_create(13, 08609 hashtab_compare_exten_numbers, 08610 ast_hashtab_resize_java, 08611 ast_hashtab_newsize_java, 08612 hashtab_hash_priority, 08613 0); 08614 tmp->peer_label_table = ast_hashtab_create(7, 08615 hashtab_compare_exten_labels, 08616 ast_hashtab_resize_java, 08617 ast_hashtab_newsize_java, 08618 hashtab_hash_labels, 08619 0); 08620 if (label) { 08621 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08622 } 08623 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08624 } else { /* this is the first exten in this context */ 08625 if (!con->root_table) 08626 con->root_table = ast_hashtab_create(27, 08627 hashtab_compare_extens, 08628 ast_hashtab_resize_java, 08629 ast_hashtab_newsize_java, 08630 hashtab_hash_extens, 08631 0); 08632 con->root = tmp; 08633 con->root->peer_table = ast_hashtab_create(13, 08634 hashtab_compare_exten_numbers, 08635 ast_hashtab_resize_java, 08636 ast_hashtab_newsize_java, 08637 hashtab_hash_priority, 08638 0); 08639 con->root->peer_label_table = ast_hashtab_create(7, 08640 hashtab_compare_exten_labels, 08641 ast_hashtab_resize_java, 08642 ast_hashtab_newsize_java, 08643 hashtab_hash_labels, 08644 0); 08645 if (label) { 08646 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 08647 } 08648 ast_hashtab_insert_safe(con->root->peer_table, tmp); 08649 08650 } 08651 ast_hashtab_insert_safe(con->root_table, tmp); 08652 if (lock_context) { 08653 ast_unlock_context(con); 08654 } 08655 if (tmp->priority == PRIORITY_HINT) { 08656 ast_add_hint(tmp); 08657 } 08658 } 08659 if (option_debug) { 08660 if (tmp->matchcid) { 08661 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 08662 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 08663 } else { 08664 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 08665 tmp->exten, tmp->priority, con->name, con); 08666 } 08667 } 08668 08669 if (tmp->matchcid) { 08670 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 08671 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 08672 } else { 08673 ast_verb(3, "Added extension '%s' priority %d to %s\n", 08674 tmp->exten, tmp->priority, con->name); 08675 } 08676 08677 return 0; 08678 }
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 8092 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
08095 { 08096 int ret = -1; 08097 struct ast_context *c; 08098 08099 c = find_context(context); 08100 if (c) { 08101 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 08102 application, data, datad, registrar, 1); 08103 } 08104 08105 return ret; 08106 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 4734 of file pbx.c.
References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), destroy_hint(), hint_id_cmp(), and hints.
Referenced by ast_add_extension2_lockopt().
04735 { 04736 struct ast_hint *hint_new; 04737 struct ast_hint *hint_found; 04738 04739 if (!e) { 04740 return -1; 04741 } 04742 04743 /* 04744 * We must create the hint we wish to add before determining if 04745 * it is already in the hints container to avoid possible 04746 * deadlock when getting the current extension state. 04747 */ 04748 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint); 04749 if (!hint_new) { 04750 return -1; 04751 } 04752 04753 /* Initialize new hint. */ 04754 hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); 04755 if (!hint_new->callbacks) { 04756 ao2_ref(hint_new, -1); 04757 return -1; 04758 } 04759 hint_new->exten = e; 04760 hint_new->laststate = ast_extension_state2(e); 04761 04762 /* Prevent multiple add hints from adding the same hint at the same time. */ 04763 ao2_lock(hints); 04764 04765 /* Search if hint exists, do nothing */ 04766 hint_found = ao2_find(hints, e, 0); 04767 if (hint_found) { 04768 ao2_ref(hint_found, -1); 04769 ao2_unlock(hints); 04770 ao2_ref(hint_new, -1); 04771 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", 04772 ast_get_extension_name(e), ast_get_extension_app(e)); 04773 return -1; 04774 } 04775 04776 /* Add new hint to the hints container */ 04777 ast_debug(2, "HINTS: Adding hint %s: %s\n", 04778 ast_get_extension_name(e), ast_get_extension_app(e)); 04779 ao2_link(hints, hint_new); 04780 04781 ao2_unlock(hints); 04782 ao2_ref(hint_new, -1); 04783 04784 return 0; 04785 }
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 8152 of file pbx.c.
References ast_channel::_state, ast_channel::accountcode, 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, ast_channel::linkedid, LOG_WARNING, ast_channel::name, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmf(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().
08153 { 08154 int res = 0; 08155 struct ast_channel *tmpchan; 08156 struct { 08157 char *accountcode; 08158 char *exten; 08159 char *context; 08160 char *linkedid; 08161 char *name; 08162 struct ast_cdr *cdr; 08163 int amaflags; 08164 int state; 08165 format_t readformat; 08166 format_t writeformat; 08167 } tmpvars = { 0, }; 08168 08169 ast_channel_lock(chan); 08170 if (chan->pbx) { /* This channel is currently in the PBX */ 08171 ast_explicit_goto(chan, context, exten, priority + 1); 08172 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08173 ast_channel_unlock(chan); 08174 return res; 08175 } 08176 08177 /* In order to do it when the channel doesn't really exist within 08178 * the PBX, we have to make a new channel, masquerade, and start the PBX 08179 * at the new location */ 08180 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08181 tmpvars.exten = ast_strdupa(chan->exten); 08182 tmpvars.context = ast_strdupa(chan->context); 08183 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08184 tmpvars.name = ast_strdupa(chan->name); 08185 tmpvars.amaflags = chan->amaflags; 08186 tmpvars.state = chan->_state; 08187 tmpvars.writeformat = chan->writeformat; 08188 tmpvars.readformat = chan->readformat; 08189 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08190 08191 ast_channel_unlock(chan); 08192 08193 /* Do not hold any channel locks while calling channel_alloc() since the function 08194 * locks the channel container when linking the new channel in. */ 08195 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08196 ast_cdr_discard(tmpvars.cdr); 08197 return -1; 08198 } 08199 08200 /* copy the cdr info over */ 08201 if (tmpvars.cdr) { 08202 ast_cdr_discard(tmpchan->cdr); 08203 tmpchan->cdr = tmpvars.cdr; 08204 tmpvars.cdr = NULL; 08205 } 08206 08207 /* Make formats okay */ 08208 tmpchan->readformat = tmpvars.readformat; 08209 tmpchan->writeformat = tmpvars.writeformat; 08210 08211 /* Setup proper location. Never hold another channel lock while calling this function. */ 08212 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08213 08214 /* Masquerade into tmp channel */ 08215 if (ast_channel_masquerade(tmpchan, chan)) { 08216 /* Failed to set up the masquerade. It's probably chan_local 08217 * in the middle of optimizing itself out. Sad. :( */ 08218 ast_hangup(tmpchan); 08219 tmpchan = NULL; 08220 res = -1; 08221 } else { 08222 ast_do_masquerade(tmpchan); 08223 /* Start the PBX going on our stolen channel */ 08224 if (ast_pbx_start(tmpchan)) { 08225 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08226 ast_hangup(tmpchan); 08227 res = -1; 08228 } 08229 } 08230 08231 return res; 08232 }
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 8234 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08235 { 08236 struct ast_channel *chan; 08237 int res = -1; 08238 08239 if ((chan = ast_channel_get_by_name(channame))) { 08240 res = ast_async_goto(chan, context, exten, priority); 08241 chan = ast_channel_unref(chan); 08242 } 08243 08244 return res; 08245 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10547 of file pbx.c.
References __ast_goto_if_exists().
10548 { 10549 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10550 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10612 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10613 { 10614 return pbx_parseable_goto(chan, goto_string, 1); 10615 }
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 7736 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, strsep(), and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07737 { 07738 char *info; 07739 int j, num_fields, last_sep = -1; 07740 07741 /* Check for empty just in case */ 07742 if (ast_strlen_zero(info_in)) { 07743 return 0; 07744 } 07745 07746 /* make a copy just in case we were passed a static string */ 07747 info = ast_strdupa(info_in); 07748 07749 /* count the number of fields in the timespec */ 07750 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07751 if (info[j] == ',') { 07752 last_sep = j; 07753 num_fields++; 07754 } 07755 } 07756 07757 /* save the timezone, if it is specified */ 07758 if (num_fields == 5) { 07759 i->timezone = ast_strdup(info + last_sep + 1); 07760 } else { 07761 i->timezone = NULL; 07762 } 07763 07764 /* Assume everything except time */ 07765 i->monthmask = 0xfff; /* 12 bits */ 07766 i->daymask = 0x7fffffffU; /* 31 bits */ 07767 i->dowmask = 0x7f; /* 7 bits */ 07768 /* on each call, use strsep() to move info to the next argument */ 07769 get_timerange(i, strsep(&info, "|,")); 07770 if (info) 07771 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07772 if (info) 07773 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07774 if (info) 07775 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07776 return 1; 07777 }
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 4875 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(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
04876 { 04877 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04878 }
Change hint for an extension.
Definition at line 4788 of file pbx.c.
References ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_hint::exten, hints, and OBJ_UNLINK.
04789 { 04790 struct ast_hint *hint; 04791 04792 if (!oe || !ne) { 04793 return -1; 04794 } 04795 04796 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */ 04797 04798 /* 04799 * Unlink the hint from the hints container as the extension 04800 * name (which is the hash value) could change. 04801 */ 04802 hint = ao2_find(hints, oe, OBJ_UNLINK); 04803 if (!hint) { 04804 ao2_unlock(hints); 04805 return -1; 04806 } 04807 04808 /* Update the hint and put it back in the hints container. */ 04809 ao2_lock(hint); 04810 hint->exten = ne; 04811 ao2_unlock(hint); 04812 ao2_link(hints, hint); 04813 04814 ao2_unlock(hints); 04815 ao2_ref(hint, -1); 04816 04817 return 0; 04818 }
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 7779 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07780 { 07781 return ast_check_timing2(i, ast_tvnow()); 07782 }
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 7784 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().
07785 { 07786 struct ast_tm tm; 07787 07788 ast_localtime(&tv, &tm, i->timezone); 07789 07790 /* If it's not the right month, return */ 07791 if (!(i->monthmask & (1 << tm.tm_mon))) 07792 return 0; 07793 07794 /* If it's not that time of the month.... */ 07795 /* Warning, tm_mday has range 1..31! */ 07796 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07797 return 0; 07798 07799 /* If it's not the right day of the week */ 07800 if (!(i->dowmask & (1 << tm.tm_wday))) 07801 return 0; 07802 07803 /* Sanity check the hour just to be safe */ 07804 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07805 ast_log(LOG_WARNING, "Insane time...\n"); 07806 return 0; 07807 } 07808 07809 /* Now the tough part, we calculate if it fits 07810 in the right time based on min/hour */ 07811 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)))) 07812 return 0; 07813 07814 /* If we got this far, then we're good */ 07815 return 1; 07816 }
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 10617 of file pbx.c.
References app, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::list.
Referenced by handle_orig(), and handle_show_application().
10618 { 10619 struct ast_app *app = NULL; 10620 int which = 0; 10621 char *ret = NULL; 10622 size_t wordlen = strlen(word); 10623 10624 AST_RWLIST_RDLOCK(&apps); 10625 AST_RWLIST_TRAVERSE(&apps, app, list) { 10626 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10627 ret = ast_strdup(app->name); 10628 break; 10629 } 10630 } 10631 AST_RWLIST_UNLOCK(&apps); 10632 10633 return ret; 10634 }
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 |
0 | on success | |
-1 | on failure |
Definition at line 8020 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08021 { 08022 int ret = -1; 08023 struct ast_context *c; 08024 08025 c = find_context_locked(context); 08026 if (c) { 08027 ret = ast_context_add_ignorepat2(c, value, registrar); 08028 ast_unlock_contexts(); 08029 } 08030 return ret; 08031 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 8033 of file pbx.c.
References ast_calloc, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().
08034 { 08035 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08036 int length; 08037 char *pattern; 08038 length = sizeof(struct ast_ignorepat); 08039 length += strlen(value) + 1; 08040 if (!(ignorepat = ast_calloc(1, length))) 08041 return -1; 08042 /* The cast to char * is because we need to write the initial value. 08043 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08044 * sees the cast as dereferencing a type-punned pointer and warns about 08045 * it. This is the workaround (we're telling gcc, yes, that's really 08046 * what we wanted to do). 08047 */ 08048 pattern = (char *) ignorepat->pattern; 08049 strcpy(pattern, value); 08050 ignorepat->next = NULL; 08051 ignorepat->registrar = registrar; 08052 ast_wrlock_context(con); 08053 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08054 ignorepatl = ignorepatc; 08055 if (!strcasecmp(ignorepatc->pattern, value)) { 08056 /* Already there */ 08057 ast_unlock_context(con); 08058 errno = EEXIST; 08059 return -1; 08060 } 08061 } 08062 if (ignorepatl) 08063 ignorepatl->next = ignorepat; 08064 else 08065 con->ignorepats = ignorepat; 08066 ast_unlock_context(con); 08067 return 0; 08068 08069 }
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 |
0 | on success | |
-1 | on error |
Definition at line 7564 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07565 { 07566 int ret = -1; 07567 struct ast_context *c; 07568 07569 c = find_context_locked(context); 07570 if (c) { 07571 ret = ast_context_add_include2(c, include, registrar); 07572 ast_unlock_contexts(); 07573 } 07574 return ret; 07575 }
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 |
0 | on success | |
-1 | on failure |
Definition at line 7833 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_context_add_include(), and context_merge_incls_swits_igps_other_registrars().
07835 { 07836 struct ast_include *new_include; 07837 char *c; 07838 struct ast_include *i, *il = NULL; /* include, include_last */ 07839 int length; 07840 char *p; 07841 07842 length = sizeof(struct ast_include); 07843 length += 2 * (strlen(value) + 1); 07844 07845 /* allocate new include structure ... */ 07846 if (!(new_include = ast_calloc(1, length))) 07847 return -1; 07848 /* Fill in this structure. Use 'p' for assignments, as the fields 07849 * in the structure are 'const char *' 07850 */ 07851 p = new_include->stuff; 07852 new_include->name = p; 07853 strcpy(p, value); 07854 p += strlen(value) + 1; 07855 new_include->rname = p; 07856 strcpy(p, value); 07857 /* Strip off timing info, and process if it is there */ 07858 if ( (c = strchr(p, ',')) ) { 07859 *c++ = '\0'; 07860 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07861 } 07862 new_include->next = NULL; 07863 new_include->registrar = registrar; 07864 07865 ast_wrlock_context(con); 07866 07867 /* ... go to last include and check if context is already included too... */ 07868 for (i = con->includes; i; i = i->next) { 07869 if (!strcasecmp(i->name, new_include->name)) { 07870 ast_destroy_timing(&(new_include->timing)); 07871 ast_free(new_include); 07872 ast_unlock_context(con); 07873 errno = EEXIST; 07874 return -1; 07875 } 07876 il = i; 07877 } 07878 07879 /* ... include new context into context list, unlock, return */ 07880 if (il) 07881 il->next = new_include; 07882 else 07883 con->includes = new_include; 07884 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07885 07886 ast_unlock_context(con); 07887 07888 return 0; 07889 }
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 |
0 | on success | |
-1 | on failure |
Definition at line 7896 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07897 { 07898 int ret = -1; 07899 struct ast_context *c; 07900 07901 c = find_context_locked(context); 07902 if (c) { /* found, add switch to this context */ 07903 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07904 ast_unlock_contexts(); 07905 } 07906 return ret; 07907 }
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 7916 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, store_hint::list, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), and lua_register_switches().
07918 { 07919 struct ast_sw *new_sw; 07920 struct ast_sw *i; 07921 int length; 07922 char *p; 07923 07924 length = sizeof(struct ast_sw); 07925 length += strlen(value) + 1; 07926 if (data) 07927 length += strlen(data); 07928 length++; 07929 07930 /* allocate new sw structure ... */ 07931 if (!(new_sw = ast_calloc(1, length))) 07932 return -1; 07933 /* ... fill in this structure ... */ 07934 p = new_sw->stuff; 07935 new_sw->name = p; 07936 strcpy(new_sw->name, value); 07937 p += strlen(value) + 1; 07938 new_sw->data = p; 07939 if (data) { 07940 strcpy(new_sw->data, data); 07941 p += strlen(data) + 1; 07942 } else { 07943 strcpy(new_sw->data, ""); 07944 p++; 07945 } 07946 new_sw->eval = eval; 07947 new_sw->registrar = registrar; 07948 07949 /* ... try to lock this context ... */ 07950 ast_wrlock_context(con); 07951 07952 /* ... go to last sw and check if context is already swd too... */ 07953 AST_LIST_TRAVERSE(&con->alts, i, list) { 07954 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07955 ast_free(new_sw); 07956 ast_unlock_context(con); 07957 errno = EEXIST; 07958 return -1; 07959 } 07960 } 07961 07962 /* ... sw new context into context list, unlock, return */ 07963 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07964 07965 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07966 07967 ast_unlock_context(con); 07968 07969 return 0; 07970 }
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 |
Definition at line 9279 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(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09280 { 09281 ast_wrlock_contexts(); 09282 __ast_context_destroy(contexts, contexts_table, con,registrar); 09283 ast_unlock_contexts(); 09284 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2656 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().
02657 { 02658 struct ast_context *tmp; 02659 struct fake_context item; 02660 02661 if (!name) { 02662 return NULL; 02663 } 02664 ast_rdlock_contexts(); 02665 if (contexts_table) { 02666 ast_copy_string(item.name, name, sizeof(item.name)); 02667 tmp = ast_hashtab_lookup(contexts_table, &item); 02668 } else { 02669 tmp = NULL; 02670 while ((tmp = ast_walk_contexts(tmp))) { 02671 if (!strcasecmp(name, tmp->name)) { 02672 break; 02673 } 02674 } 02675 } 02676 ast_unlock_contexts(); 02677 return tmp; 02678 }
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.
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 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 7165 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, name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), and set_config().
07166 { 07167 struct ast_context *tmp, **local_contexts; 07168 struct fake_context search; 07169 int length = sizeof(struct ast_context) + strlen(name) + 1; 07170 07171 if (!contexts_table) { 07172 /* Protect creation of contexts_table from reentrancy. */ 07173 ast_wrlock_contexts(); 07174 if (!contexts_table) { 07175 contexts_table = ast_hashtab_create(17, 07176 ast_hashtab_compare_contexts, 07177 ast_hashtab_resize_java, 07178 ast_hashtab_newsize_java, 07179 ast_hashtab_hash_contexts, 07180 0); 07181 } 07182 ast_unlock_contexts(); 07183 } 07184 07185 ast_copy_string(search.name, name, sizeof(search.name)); 07186 if (!extcontexts) { 07187 ast_rdlock_contexts(); 07188 local_contexts = &contexts; 07189 tmp = ast_hashtab_lookup(contexts_table, &search); 07190 ast_unlock_contexts(); 07191 if (tmp) { 07192 tmp->refcount++; 07193 return tmp; 07194 } 07195 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07196 local_contexts = extcontexts; 07197 tmp = ast_hashtab_lookup(exttable, &search); 07198 if (tmp) { 07199 tmp->refcount++; 07200 return tmp; 07201 } 07202 } 07203 07204 if ((tmp = ast_calloc(1, length))) { 07205 ast_rwlock_init(&tmp->lock); 07206 ast_mutex_init(&tmp->macrolock); 07207 strcpy(tmp->name, name); 07208 tmp->root = NULL; 07209 tmp->root_table = NULL; 07210 tmp->registrar = ast_strdup(registrar); 07211 tmp->includes = NULL; 07212 tmp->ignorepats = NULL; 07213 tmp->refcount = 1; 07214 } else { 07215 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07216 return NULL; 07217 } 07218 07219 if (!extcontexts) { 07220 ast_wrlock_contexts(); 07221 tmp->next = *local_contexts; 07222 *local_contexts = tmp; 07223 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07224 ast_unlock_contexts(); 07225 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07226 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07227 } else { 07228 tmp->next = *local_contexts; 07229 if (exttable) 07230 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07231 07232 *local_contexts = tmp; 07233 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07234 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07235 } 07236 return tmp; 07237 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 5765 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05766 { 05767 struct ast_context *c; 05768 int ret = -1; 05769 05770 c = find_context_locked(context); 05771 if (c) { 05772 ast_unlock_contexts(); 05773 05774 /* if we found context, lock macrolock */ 05775 ret = ast_mutex_lock(&c->macrolock); 05776 } 05777 05778 return ret; 05779 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
Definition at line 5570 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), remove_exten_if_exist(), unregister_exten(), and UnregisterExtension().
05571 { 05572 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05573 }
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 5600 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
05601 { 05602 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05603 }
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 5575 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().
05576 { 05577 int ret = -1; /* default error return */ 05578 struct ast_context *c; 05579 05580 c = find_context_locked(context); 05581 if (c) { /* ... remove extension ... */ 05582 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 05583 matchcallerid, registrar, 0); 05584 ast_unlock_contexts(); 05585 } 05586 05587 return ret; 05588 }
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 5605 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, destroy_exten(), ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
05606 { 05607 struct ast_exten *exten, *prev_exten = NULL; 05608 struct ast_exten *peer; 05609 struct ast_exten ex, *exten2, *exten3; 05610 char dummy_name[1024]; 05611 struct ast_exten *previous_peer = NULL; 05612 struct ast_exten *next_peer = NULL; 05613 int found = 0; 05614 05615 if (!already_locked) 05616 ast_wrlock_context(con); 05617 05618 /* Handle this is in the new world */ 05619 05620 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05621 * peers, not just those matching the callerid. */ 05622 #ifdef NEED_DEBUG 05623 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05624 #endif 05625 #ifdef CONTEXT_DEBUG 05626 check_contexts(__FILE__, __LINE__); 05627 #endif 05628 /* find this particular extension */ 05629 ex.exten = dummy_name; 05630 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05631 ex.cidmatch = callerid; 05632 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05633 exten = ast_hashtab_lookup(con->root_table, &ex); 05634 if (exten) { 05635 if (priority == 0) { 05636 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05637 if (!exten2) 05638 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); 05639 if (con->pattern_tree) { 05640 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05641 05642 if (x->exten) { /* this test for safety purposes */ 05643 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05644 x->exten = 0; /* get rid of what will become a bad pointer */ 05645 } else { 05646 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05647 } 05648 } 05649 } else { 05650 ex.priority = priority; 05651 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05652 if (exten2) { 05653 05654 if (exten2->label) { /* if this exten has a label, remove that, too */ 05655 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05656 if (!exten3) 05657 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); 05658 } 05659 05660 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05661 if (!exten3) 05662 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); 05663 if (exten2 == exten && exten2->peer) { 05664 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05665 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05666 } 05667 if (ast_hashtab_size(exten->peer_table) == 0) { 05668 /* well, if the last priority of an exten is to be removed, 05669 then, the extension is removed, too! */ 05670 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05671 if (!exten3) 05672 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05673 if (con->pattern_tree) { 05674 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05675 if (x->exten) { /* this test for safety purposes */ 05676 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05677 x->exten = 0; /* get rid of what will become a bad pointer */ 05678 } 05679 } 05680 } 05681 } else { 05682 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05683 priority, exten->exten, con->name); 05684 } 05685 } 05686 } else { 05687 /* hmmm? this exten is not in this pattern tree? */ 05688 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05689 extension, con->name); 05690 } 05691 #ifdef NEED_DEBUG 05692 if (con->pattern_tree) { 05693 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05694 log_match_char_tree(con->pattern_tree, " "); 05695 } 05696 #endif 05697 05698 /* scan the extension list to find first matching extension-registrar */ 05699 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05700 if (!strcmp(exten->exten, extension) && 05701 (!registrar || !strcmp(exten->registrar, registrar)) && 05702 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05703 break; 05704 } 05705 if (!exten) { 05706 /* we can't find right extension */ 05707 if (!already_locked) 05708 ast_unlock_context(con); 05709 return -1; 05710 } 05711 05712 /* scan the priority list to remove extension with exten->priority == priority */ 05713 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05714 peer && !strcmp(peer->exten, extension) && (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch))); 05715 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05716 if ((priority == 0 || peer->priority == priority) && 05717 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05718 (!registrar || !strcmp(peer->registrar, registrar) )) { 05719 found = 1; 05720 05721 /* we are first priority extension? */ 05722 if (!previous_peer) { 05723 /* 05724 * We are first in the priority chain, so must update the extension chain. 05725 * The next node is either the next priority or the next extension 05726 */ 05727 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05728 if (peer->peer) { 05729 /* move the peer_table and peer_label_table down to the next peer, if 05730 it is there */ 05731 peer->peer->peer_table = peer->peer_table; 05732 peer->peer->peer_label_table = peer->peer_label_table; 05733 peer->peer_table = NULL; 05734 peer->peer_label_table = NULL; 05735 } 05736 if (!prev_exten) { /* change the root... */ 05737 con->root = next_node; 05738 } else { 05739 prev_exten->next = next_node; /* unlink */ 05740 } 05741 if (peer->peer) { /* update the new head of the pri list */ 05742 peer->peer->next = peer->next; 05743 } 05744 } else { /* easy, we are not first priority in extension */ 05745 previous_peer->peer = peer->peer; 05746 } 05747 05748 /* now, free whole priority extension */ 05749 destroy_exten(peer); 05750 } else { 05751 previous_peer = peer; 05752 } 05753 } 05754 if (!already_locked) 05755 ast_unlock_context(con); 05756 return found ? 0 : -1; 05757 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7976 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07977 { 07978 int ret = -1; 07979 struct ast_context *c; 07980 07981 c = find_context_locked(context); 07982 if (c) { 07983 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 07984 ast_unlock_contexts(); 07985 } 07986 return ret; 07987 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7989 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().
07990 { 07991 struct ast_ignorepat *ip, *ipl = NULL; 07992 07993 ast_wrlock_context(con); 07994 07995 for (ip = con->ignorepats; ip; ip = ip->next) { 07996 if (!strcmp(ip->pattern, ignorepat) && 07997 (!registrar || (registrar == ip->registrar))) { 07998 if (ipl) { 07999 ipl->next = ip->next; 08000 ast_free(ip); 08001 } else { 08002 con->ignorepats = ip->next; 08003 ast_free(ip); 08004 } 08005 ast_unlock_context(con); 08006 return 0; 08007 } 08008 ipl = ip; 08009 } 08010 08011 ast_unlock_context(con); 08012 errno = EINVAL; 08013 return -1; 08014 }
int ast_context_remove_include | ( | const char * | context, | |
const char * | include, | |||
const char * | registrar | |||
) |
Remove a context include.
0 | on success | |
-1 | on failure |
Definition at line 5463 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05464 { 05465 int ret = -1; 05466 struct ast_context *c; 05467 05468 c = find_context_locked(context); 05469 if (c) { 05470 /* found, remove include from this context ... */ 05471 ret = ast_context_remove_include2(c, include, registrar); 05472 ast_unlock_contexts(); 05473 } 05474 return ret; 05475 }
int ast_context_remove_include2 | ( | struct ast_context * | con, | |
const char * | include, | |||
const char * | registrar | |||
) |
Removes an include by an ast_context structure.
0 | on success. | |
-1 | on failure. |
Definition at line 5486 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().
05487 { 05488 struct ast_include *i, *pi = NULL; 05489 int ret = -1; 05490 05491 ast_wrlock_context(con); 05492 05493 /* find our include */ 05494 for (i = con->includes; i; pi = i, i = i->next) { 05495 if (!strcmp(i->name, include) && 05496 (!registrar || !strcmp(i->registrar, registrar))) { 05497 /* remove from list */ 05498 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05499 if (pi) 05500 pi->next = i->next; 05501 else 05502 con->includes = i->next; 05503 /* free include and return */ 05504 ast_destroy_timing(&(i->timing)); 05505 ast_free(i); 05506 ret = 0; 05507 break; 05508 } 05509 } 05510 05511 ast_unlock_context(con); 05512 05513 return ret; 05514 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 5521 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05522 { 05523 int ret = -1; /* default error return */ 05524 struct ast_context *c; 05525 05526 c = find_context_locked(context); 05527 if (c) { 05528 /* remove switch from this context ... */ 05529 ret = ast_context_remove_switch2(c, sw, data, registrar); 05530 ast_unlock_contexts(); 05531 } 05532 return ret; 05533 }
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 5543 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::list, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
05544 { 05545 struct ast_sw *i; 05546 int ret = -1; 05547 05548 ast_wrlock_context(con); 05549 05550 /* walk switches */ 05551 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05552 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05553 (!registrar || !strcmp(i->registrar, registrar))) { 05554 /* found, remove from list */ 05555 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05556 AST_LIST_REMOVE_CURRENT(list); 05557 ast_free(i); /* free switch and return */ 05558 ret = 0; 05559 break; 05560 } 05561 } 05562 AST_LIST_TRAVERSE_SAFE_END; 05563 05564 ast_unlock_context(con); 05565 05566 return ret; 05567 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5786 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05787 { 05788 struct ast_context *c; 05789 int ret = -1; 05790 05791 c = find_context_locked(context); 05792 if (c) { 05793 ast_unlock_contexts(); 05794 05795 /* if we found context, unlock macrolock */ 05796 ret = ast_mutex_unlock(&c->macrolock); 05797 } 05798 05799 return ret; 05800 }
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 10502 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().
10503 { 10504 struct ast_include *inc = NULL; 10505 int res = 0; 10506 10507 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10508 if (ast_context_find(inc->rname)) 10509 continue; 10510 10511 res = -1; 10512 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10513 ast_get_context_name(con), inc->rname); 10514 break; 10515 } 10516 10517 return res; 10518 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 3485 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_func_read(), ast_func_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().
03486 { 03487 struct ast_custom_function *acf = NULL; 03488 03489 AST_RWLIST_RDLOCK(&acf_root); 03490 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03491 if (!strcmp(name, acf->name)) 03492 break; 03493 } 03494 AST_RWLIST_UNLOCK(&acf_root); 03495 03496 return acf; 03497 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3499 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by _unload_module(), load_module(), reload(), and unload_module().
03500 { 03501 struct ast_custom_function *cur; 03502 03503 if (!acf) { 03504 return -1; 03505 } 03506 03507 AST_RWLIST_WRLOCK(&acf_root); 03508 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03509 #ifdef AST_XML_DOCS 03510 if (cur->docsrc == AST_XML_DOC) { 03511 ast_string_field_free_memory(acf); 03512 } 03513 #endif 03514 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03515 } 03516 AST_RWLIST_UNLOCK(&acf_root); 03517 03518 return cur ? 0 : -1; 03519 }
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 7818 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().
07819 { 07820 if (i->timezone) { 07821 ast_free(i->timezone); 07822 i->timezone = NULL; 07823 } 07824 return 0; 07825 }
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 4308 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().
04309 { 04310 switch (devstate) { 04311 case AST_DEVICE_ONHOLD: 04312 return AST_EXTENSION_ONHOLD; 04313 case AST_DEVICE_BUSY: 04314 return AST_EXTENSION_BUSY; 04315 case AST_DEVICE_UNKNOWN: 04316 return AST_EXTENSION_NOT_INUSE; 04317 case AST_DEVICE_UNAVAILABLE: 04318 case AST_DEVICE_INVALID: 04319 return AST_EXTENSION_UNAVAILABLE; 04320 case AST_DEVICE_RINGINUSE: 04321 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04322 case AST_DEVICE_RINGING: 04323 return AST_EXTENSION_RINGING; 04324 case AST_DEVICE_INUSE: 04325 return AST_EXTENSION_INUSE; 04326 case AST_DEVICE_NOT_INUSE: 04327 return AST_EXTENSION_NOT_INUSE; 04328 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04329 break; 04330 } 04331 04332 return AST_EXTENSION_NOT_INUSE; 04333 }
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 4860 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_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().
04861 { 04862 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04863 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8129 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(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
08130 { 08131 if (!chan) 08132 return -1; 08133 08134 ast_channel_lock(chan); 08135 08136 if (!ast_strlen_zero(context)) 08137 ast_copy_string(chan->context, context, sizeof(chan->context)); 08138 if (!ast_strlen_zero(exten)) 08139 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08140 if (priority > -1) { 08141 chan->priority = priority; 08142 /* see flag description in channel.h for explanation */ 08143 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08144 chan->priority--; 08145 } 08146 08147 ast_channel_unlock(chan); 08148 08149 return 0; 08150 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2633 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().
02634 { 02635 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02636 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02637 return extension_match_core(pattern, data, needmore); 02638 }
int ast_extension_cmp | ( | const char * | a, | |
const char * | b | |||
) |
Determine if one extension should match before another.
a | extension to compare with b | |
b | extension to compare with a |
0 | if the two extensions have equal matching priority | |
1 | on a > b | |
-1 | on a < b |
Definition at line 2435 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02436 { 02437 return ext_cmp(a, b); 02438 }
int ast_extension_match | ( | const char * | pattern, | |
const char * | extension | |||
) |
Determine if a given extension matches a given pattern (in NXX format).
pattern | pattern to match | |
extension | extension to check against the pattern. |
1 | on match | |
0 | on failure |
Definition at line 2628 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(), show_dialplan_helper(), and sig_pri_msn_match().
02629 { 02630 return extension_match_core(pattern, data, E_MATCH); 02631 }
int ast_extension_state | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) |
Uses hint and devicestate callback to get the state of an extension.
c | this is not important | |
context | which context to look in | |
exten | which extension to get state |
Definition at line 4378 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().
04379 { 04380 struct ast_exten *e; 04381 04382 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04383 return -1; /* No hint, return -1 */ 04384 } 04385 04386 if (e->exten[0] == '_') { 04387 /* Create this hint on-the-fly */ 04388 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04389 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04390 e->registrar); 04391 if (!(e = ast_hint_extension(c, context, exten))) { 04392 /* Improbable, but not impossible */ 04393 return -1; 04394 } 04395 } 04396 04397 return ast_extension_state2(e); /* Check all devices in the hint */ 04398 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4353 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().
04354 { 04355 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32); 04356 04357 if (!e || !hint_app) { 04358 return -1; 04359 } 04360 04361 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e)); 04362 return ast_extension_state3(hint_app); 04363 }
const char* ast_extension_state2str | ( | int | extension_state | ) |
Return string representation of the state of an extension.
extension_state | is the numerical state delivered by ast_extension_state |
Definition at line 4366 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().
04367 { 04368 int i; 04369 04370 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04371 if (extension_states[i].extension_state == extension_state) 04372 return extension_states[i].text; 04373 } 04374 return "Unknown"; 04375 }
static int ast_extension_state3 | ( | struct ast_str * | hint_app | ) | [static] |
Definition at line 4335 of file pbx.c.
References ast_device_state(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_str_buffer(), and strsep().
Referenced by ast_extension_state2(), and handle_statechange().
04336 { 04337 char *cur; 04338 char *rest; 04339 struct ast_devstate_aggregate agg; 04340 04341 /* One or more devices separated with a & character */ 04342 rest = ast_str_buffer(hint_app); 04343 04344 ast_devstate_aggregate_init(&agg); 04345 while ((cur = strsep(&rest, "&"))) { 04346 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04347 } 04348 04349 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04350 }
int ast_extension_state_add | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
void * | data | |||
) |
Registers a state change callback.
context | which context to look in | |
exten | which extension to get state | |
change_cb | callback to call if state changed | |
data | to pass to callback |
-1 | on failure | |
ID | on success |
Definition at line 4599 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
04601 { 04602 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 04603 }
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 | |||
) |
Registers a state change callback with destructor.
10.1.0
context | which context to look in | |
exten | which extension to get state | |
change_cb | callback to call if state changed | |
destroy_cb | callback to call when registration destroyed. | |
data | to pass to callback |
The destroy_cb is called when the registration is deleted so the registerer can release any associated resources.
-1 | on failure | |
ID | on success |
Definition at line 4512 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_exten::cidmatch, ast_exten::data, destroy_state_cb(), ast_exten::exten, hints, 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().
04514 { 04515 struct ast_hint *hint; 04516 struct ast_state_cb *state_cb; 04517 struct ast_exten *e; 04518 int id; 04519 04520 /* If there's no context and extension: add callback to statecbs list */ 04521 if (!context && !exten) { 04522 /* Prevent multiple adds from adding the same change_cb at the same time. */ 04523 ao2_lock(statecbs); 04524 04525 /* Remove any existing change_cb. */ 04526 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 04527 04528 /* Now insert the change_cb */ 04529 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04530 ao2_unlock(statecbs); 04531 return -1; 04532 } 04533 state_cb->id = 0; 04534 state_cb->change_cb = change_cb; 04535 state_cb->destroy_cb = destroy_cb; 04536 state_cb->data = data; 04537 ao2_link(statecbs, state_cb); 04538 04539 ao2_ref(state_cb, -1); 04540 ao2_unlock(statecbs); 04541 return 0; 04542 } 04543 04544 if (!context || !exten) 04545 return -1; 04546 04547 /* This callback type is for only one hint, so get the hint */ 04548 e = ast_hint_extension(NULL, context, exten); 04549 if (!e) { 04550 return -1; 04551 } 04552 04553 /* If this is a pattern, dynamically create a new extension for this 04554 * particular match. Note that this will only happen once for each 04555 * individual extension, because the pattern will no longer match first. 04556 */ 04557 if (e->exten[0] == '_') { 04558 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04559 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04560 e->registrar); 04561 e = ast_hint_extension(NULL, context, exten); 04562 if (!e || e->exten[0] == '_') { 04563 return -1; 04564 } 04565 } 04566 04567 /* Find the hint in the hints container */ 04568 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04569 hint = ao2_find(hints, e, 0); 04570 if (!hint) { 04571 ao2_unlock(hints); 04572 return -1; 04573 } 04574 04575 /* Now insert the callback in the callback list */ 04576 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04577 ao2_ref(hint, -1); 04578 ao2_unlock(hints); 04579 return -1; 04580 } 04581 do { 04582 id = stateid++; /* Unique ID for this callback */ 04583 /* Do not allow id to ever be -1 or 0. */ 04584 } while (id == -1 || id == 0); 04585 state_cb->id = id; 04586 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 04587 state_cb->destroy_cb = destroy_cb; 04588 state_cb->data = data; /* Data for the callback */ 04589 ao2_link(hint->callbacks, state_cb); 04590 04591 ao2_ref(state_cb, -1); 04592 ao2_ref(hint, -1); 04593 ao2_unlock(hints); 04594 04595 return id; 04596 }
int ast_extension_state_del | ( | int | id, | |
ast_state_cb_type | change_cb | |||
) |
Deletes a registered state change callback by ID.
id | of the registered state callback to delete | |
change_cb | callback to call if state changed (Used if id == 0 (global)) |
0 | success | |
-1 | failure |
Definition at line 4621 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().
04622 { 04623 struct ast_state_cb *p_cur; 04624 int ret = -1; 04625 04626 if (!id) { /* id == 0 is a callback without extension */ 04627 if (!change_cb) { 04628 return ret; 04629 } 04630 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 04631 if (p_cur) { 04632 ret = 0; 04633 ao2_ref(p_cur, -1); 04634 } 04635 } else { /* callback with extension, find the callback based on ID */ 04636 struct ast_hint *hint; 04637 04638 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04639 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04640 if (hint) { 04641 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04642 if (p_cur) { 04643 ret = 0; 04644 ao2_ref(p_cur, -1); 04645 } 04646 ao2_ref(hint, -1); 04647 } 04648 ao2_unlock(hints); 04649 } 04650 04651 return ret; 04652 }
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 4865 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().
04866 { 04867 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04868 }
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.
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.
Definition at line 4870 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
04871 { 04872 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04873 }
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 |
0 | success | |
non-zero | failure |
Definition at line 3643 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, ast_module_user::chan, copy(), func_args(), 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().
03644 { 03645 char *copy = ast_strdupa(function); 03646 char *args = func_args(copy); 03647 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03648 int res; 03649 struct ast_module_user *u = NULL; 03650 03651 if (acfptr == NULL) { 03652 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03653 } else if (!acfptr->read && !acfptr->read2) { 03654 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03655 } else if (acfptr->read) { 03656 if (acfptr->mod) { 03657 u = __ast_module_user_add(acfptr->mod, chan); 03658 } 03659 res = acfptr->read(chan, copy, args, workspace, len); 03660 if (acfptr->mod && u) { 03661 __ast_module_user_remove(acfptr->mod, u); 03662 } 03663 return res; 03664 } else { 03665 struct ast_str *str = ast_str_create(16); 03666 if (acfptr->mod) { 03667 u = __ast_module_user_add(acfptr->mod, chan); 03668 } 03669 res = acfptr->read2(chan, copy, args, &str, 0); 03670 if (acfptr->mod && u) { 03671 __ast_module_user_remove(acfptr->mod, u); 03672 } 03673 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03674 ast_free(str); 03675 return res; 03676 } 03677 return -1; 03678 }
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 |
0 | success | |
non-zero | failure |
Definition at line 3680 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, ast_module_user::chan, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, str, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
03681 { 03682 char *copy = ast_strdupa(function); 03683 char *args = func_args(copy); 03684 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03685 int res; 03686 struct ast_module_user *u = NULL; 03687 03688 if (acfptr == NULL) { 03689 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03690 } else if (!acfptr->read && !acfptr->read2) { 03691 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03692 } else { 03693 if (acfptr->mod) { 03694 u = __ast_module_user_add(acfptr->mod, chan); 03695 } 03696 ast_str_reset(*str); 03697 if (acfptr->read2) { 03698 /* ast_str enabled */ 03699 res = acfptr->read2(chan, copy, args, str, maxlen); 03700 } else { 03701 /* Legacy function pointer, allocate buffer for result */ 03702 int maxsize = ast_str_size(*str); 03703 if (maxlen > -1) { 03704 if (maxlen == 0) { 03705 if (acfptr->read_max) { 03706 maxsize = acfptr->read_max; 03707 } else { 03708 maxsize = VAR_BUF_SIZE; 03709 } 03710 } else { 03711 maxsize = maxlen; 03712 } 03713 ast_str_make_space(str, maxsize); 03714 } 03715 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03716 } 03717 if (acfptr->mod && u) { 03718 __ast_module_user_remove(acfptr->mod, u); 03719 } 03720 return res; 03721 } 03722 return -1; 03723 }
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 |
0 | success | |
non-zero | failure |
Definition at line 3725 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, ast_module_user::chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03726 { 03727 char *copy = ast_strdupa(function); 03728 char *args = func_args(copy); 03729 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03730 03731 if (acfptr == NULL) 03732 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03733 else if (!acfptr->write) 03734 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03735 else { 03736 int res; 03737 struct ast_module_user *u = NULL; 03738 if (acfptr->mod) 03739 u = __ast_module_user_add(acfptr->mod, chan); 03740 res = acfptr->write(chan, copy, args, value); 03741 if (acfptr->mod && u) 03742 __ast_module_user_remove(acfptr->mod, u); 03743 return res; 03744 } 03745 03746 return -1; 03747 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10354 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), 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().
10355 { 10356 return con ? con->name : NULL; 10357 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10392 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10393 { 10394 return c ? c->registrar : NULL; 10395 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10422 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().
10423 { 10424 return e ? e->app : NULL; 10425 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10427 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().
10428 { 10429 return e ? e->data : NULL; 10430 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10417 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10418 { 10419 return e ? e->cidmatch : NULL; 10420 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 10359 of file pbx.c.
References exten.
Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 10369 of file pbx.c.
References exten.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 10412 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10413 { 10414 return e ? e->matchcid : 0; 10415 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10364 of file pbx.c.
References 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().
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10384 of file pbx.c.
References exten.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10397 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10398 { 10399 return e ? e->registrar : NULL; 10400 }
int ast_get_hint | ( | char * | hint, | |
int | hintsize, | |||
char * | name, | |||
int | namesize, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
If an extension hint exists, return non-zero.
hint | buffer for hint | |
hintsize | size of hint buffer, in bytes | |
name | buffer for name portion of hint | |
namesize | size of name buffer | |
c | Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded. | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 4822 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().
04823 { 04824 struct ast_exten *e = ast_hint_extension(c, context, exten); 04825 04826 if (e) { 04827 if (hint) 04828 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04829 if (name) { 04830 const char *tmp = ast_get_extension_app_data(e); 04831 if (tmp) 04832 ast_copy_string(name, tmp, namesize); 04833 } 04834 return -1; 04835 } 04836 return 0; 04837 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10379 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().
10380 { 10381 return ip ? ip->pattern : NULL; 10382 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10407 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().
10408 { 10409 return ip ? ip->registrar : NULL; 10410 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 10374 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().
10375 { 10376 return inc ? inc->name : NULL; 10377 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 10402 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().
10403 { 10404 return i ? i->registrar : NULL; 10405 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10437 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().
10438 { 10439 return sw ? sw->data : NULL; 10440 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10442 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10443 { 10444 return sw->eval; 10445 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10432 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().
10433 { 10434 return sw ? sw->name : NULL; 10435 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10447 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().
10448 { 10449 return sw ? sw->registrar : NULL; 10450 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10542 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(), priority_jump(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10543 { 10544 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10545 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1065 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01066 { 01067 const struct ast_context *ac = ah_a; 01068 const struct ast_context *bc = ah_b; 01069 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01070 return 1; 01071 /* assume context names are registered in a string table! */ 01072 return strcmp(ac->name, bc->name); 01073 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1108 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().
01109 { 01110 const struct ast_context *ac = obj; 01111 return ast_hashtab_hash_string(ac->name); 01112 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
Definition at line 4299 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().
04300 { 04301 struct ast_exten *e; 04302 ast_rdlock_contexts(); 04303 e = ast_hint_extension_nolock(c, context, exten); 04304 ast_unlock_contexts(); 04305 return e; 04306 }
static struct ast_exten* ast_hint_extension_nolock | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
Find hint for given extension in context.
Definition at line 4293 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().
04294 { 04295 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04296 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04297 }
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 |
0 | if the pattern should not be ignored | |
non-zero | if the pattern should be ignored |
Definition at line 8071 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(), pri_ss_thread(), and skinny_ss().
08072 { 08073 struct ast_context *con = ast_context_find(context); 08074 08075 if (con) { 08076 struct ast_ignorepat *pat; 08077 08078 for (pat = con->ignorepats; pat; pat = pat->next) { 08079 if (ast_extension_match(pat->pattern, pattern)) 08080 return 1; 08081 } 08082 } 08083 08084 return 0; 08085 }
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 4880 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), collect_digits(), dahdi_r2_on_dnis_digit_received(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_ss_thread(), readexten_exec(), and skinny_ss().
04881 { 04882 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04883 }
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 7369 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_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, store_hint::data, E_MATCH, store_hint::exten, hints, ast_hint::laststate, store_hint::laststate, store_hint::list, ast_context::next, store_hint::next, OBJ_UNLINK, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07370 { 07371 double ft; 07372 struct ast_context *tmp; 07373 struct ast_context *oldcontextslist; 07374 struct ast_hashtab *oldtable; 07375 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07376 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07377 struct store_hint *saved_hint; 07378 struct ast_hint *hint; 07379 struct ast_exten *exten; 07380 int length; 07381 struct ast_state_cb *thiscb; 07382 struct ast_hashtab_iter *iter; 07383 struct ao2_iterator i; 07384 struct timeval begintime; 07385 struct timeval writelocktime; 07386 struct timeval endlocktime; 07387 struct timeval enddeltime; 07388 07389 /* 07390 * It is very important that this function hold the hints 07391 * container lock _and_ the conlock during its operation; not 07392 * only do we need to ensure that the list of contexts and 07393 * extensions does not change, but also that no hint callbacks 07394 * (watchers) are added or removed during the merge/delete 07395 * process 07396 * 07397 * In addition, the locks _must_ be taken in this order, because 07398 * there are already other code paths that use this order 07399 */ 07400 07401 begintime = ast_tvnow(); 07402 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07403 ast_wrlock_contexts(); 07404 iter = ast_hashtab_start_traversal(contexts_table); 07405 while ((tmp = ast_hashtab_next(iter))) { 07406 context_merge(extcontexts, exttable, tmp, registrar); 07407 } 07408 ast_hashtab_end_traversal(iter); 07409 07410 ao2_lock(hints); 07411 writelocktime = ast_tvnow(); 07412 07413 /* preserve all watchers for hints */ 07414 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07415 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07416 if (ao2_container_count(hint->callbacks)) { 07417 ao2_lock(hint); 07418 if (!hint->exten) { 07419 /* The extension has already been destroyed. (Should never happen here) */ 07420 ao2_unlock(hint); 07421 continue; 07422 } 07423 07424 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07425 + sizeof(*saved_hint); 07426 if (!(saved_hint = ast_calloc(1, length))) { 07427 ao2_unlock(hint); 07428 continue; 07429 } 07430 07431 /* This removes all the callbacks from the hint into saved_hint. */ 07432 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07433 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07434 /* 07435 * We intentionally do not unref thiscb to account for the 07436 * non-ao2 reference in saved_hint->callbacks 07437 */ 07438 } 07439 07440 saved_hint->laststate = hint->laststate; 07441 saved_hint->context = saved_hint->data; 07442 strcpy(saved_hint->data, hint->exten->parent->name); 07443 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07444 strcpy(saved_hint->exten, hint->exten->exten); 07445 ao2_unlock(hint); 07446 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07447 } 07448 } 07449 ao2_iterator_destroy(&i); 07450 07451 /* save the old table and list */ 07452 oldtable = contexts_table; 07453 oldcontextslist = contexts; 07454 07455 /* move in the new table and list */ 07456 contexts_table = exttable; 07457 contexts = *extcontexts; 07458 07459 /* 07460 * Restore the watchers for hints that can be found; notify 07461 * those that cannot be restored. 07462 */ 07463 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07464 struct pbx_find_info q = { .stacklen = 0 }; 07465 07466 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07467 PRIORITY_HINT, NULL, "", E_MATCH); 07468 /* 07469 * If this is a pattern, dynamically create a new extension for this 07470 * particular match. Note that this will only happen once for each 07471 * individual extension, because the pattern will no longer match first. 07472 */ 07473 if (exten && exten->exten[0] == '_') { 07474 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07475 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07476 exten->registrar); 07477 /* rwlocks are not recursive locks */ 07478 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07479 saved_hint->exten); 07480 } 07481 07482 /* Find the hint in the hints container */ 07483 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07484 if (!hint) { 07485 /* 07486 * Notify watchers of this removed hint later when we aren't 07487 * encumberd by so many locks. 07488 */ 07489 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07490 } else { 07491 ao2_lock(hint); 07492 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07493 ao2_link(hint->callbacks, thiscb); 07494 /* Ref that we added when putting into saved_hint->callbacks */ 07495 ao2_ref(thiscb, -1); 07496 } 07497 hint->laststate = saved_hint->laststate; 07498 ao2_unlock(hint); 07499 ao2_ref(hint, -1); 07500 ast_free(saved_hint); 07501 } 07502 } 07503 07504 ao2_unlock(hints); 07505 ast_unlock_contexts(); 07506 07507 /* 07508 * Notify watchers of all removed hints with the same lock 07509 * environment as handle_statechange(). 07510 */ 07511 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 07512 /* this hint has been removed, notify the watchers */ 07513 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07514 thiscb->change_cb(saved_hint->context, saved_hint->exten, 07515 AST_EXTENSION_REMOVED, thiscb->data); 07516 /* Ref that we added when putting into saved_hint->callbacks */ 07517 ao2_ref(thiscb, -1); 07518 } 07519 ast_free(saved_hint); 07520 } 07521 07522 ast_mutex_unlock(&context_merge_lock); 07523 endlocktime = ast_tvnow(); 07524 07525 /* 07526 * The old list and hashtab no longer are relevant, delete them 07527 * while the rest of asterisk is now freely using the new stuff 07528 * instead. 07529 */ 07530 07531 ast_hashtab_destroy(oldtable, NULL); 07532 07533 for (tmp = oldcontextslist; tmp; ) { 07534 struct ast_context *next; /* next starting point */ 07535 07536 next = tmp->next; 07537 __ast_internal_context_destroy(tmp); 07538 tmp = next; 07539 } 07540 enddeltime = ast_tvnow(); 07541 07542 ft = ast_tvdiff_us(writelocktime, begintime); 07543 ft /= 1000000.0; 07544 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07545 07546 ft = ast_tvdiff_us(endlocktime, writelocktime); 07547 ft /= 1000000.0; 07548 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07549 07550 ft = ast_tvdiff_us(enddeltime, endlocktime); 07551 ft /= 1000000.0; 07552 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07553 07554 ft = ast_tvdiff_us(enddeltime, begintime); 07555 ft /= 1000000.0; 07556 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07557 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10607 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().
10608 { 10609 return pbx_parseable_goto(chan, goto_string, 0); 10610 }
int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 10672 of file pbx.c.
References ao2_container_alloc, HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hints, statecbs, and statecbs_cmp().
Referenced by main().
10673 { 10674 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 10675 statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); 10676 10677 return (hints && statecbs) ? 0 : -1; 10678 }
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 8948 of file pbx.c.
References __ast_request_and_dial(), 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(), async_stat::chan, errno, LOG_WARNING, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
08949 { 08950 struct ast_channel *chan; 08951 struct app_tmp *tmp; 08952 int res = -1, cdr_res = -1; 08953 struct outgoing_helper oh; 08954 08955 memset(&oh, 0, sizeof(oh)); 08956 oh.vars = vars; 08957 oh.account = account; 08958 08959 if (locked_channel) 08960 *locked_channel = NULL; 08961 if (ast_strlen_zero(app)) { 08962 res = -1; 08963 goto outgoing_app_cleanup; 08964 } 08965 if (synchronous) { 08966 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08967 if (chan) { 08968 ast_set_variables(chan, vars); 08969 if (account) 08970 ast_cdr_setaccount(chan, account); 08971 if (chan->_state == AST_STATE_UP) { 08972 res = 0; 08973 ast_verb(4, "Channel %s was answered.\n", chan->name); 08974 tmp = ast_calloc(1, sizeof(*tmp)); 08975 if (!tmp || ast_string_field_init(tmp, 252)) { 08976 if (tmp) { 08977 ast_free(tmp); 08978 } 08979 res = -1; 08980 } else { 08981 ast_string_field_set(tmp, app, app); 08982 ast_string_field_set(tmp, data, appdata); 08983 tmp->chan = chan; 08984 if (synchronous > 1) { 08985 if (locked_channel) 08986 ast_channel_unlock(chan); 08987 ast_pbx_run_app(tmp); 08988 } else { 08989 if (locked_channel) 08990 ast_channel_lock(chan); 08991 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 08992 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 08993 ast_string_field_free_memory(tmp); 08994 ast_free(tmp); 08995 if (locked_channel) 08996 ast_channel_unlock(chan); 08997 ast_hangup(chan); 08998 res = -1; 08999 } else { 09000 if (locked_channel) 09001 *locked_channel = chan; 09002 } 09003 } 09004 } 09005 } else { 09006 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09007 if (chan->cdr) { /* update the cdr */ 09008 /* here we update the status of the call, which sould be busy. 09009 * if that fails then we set the status to failed */ 09010 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09011 ast_cdr_failed(chan->cdr); 09012 } 09013 ast_hangup(chan); 09014 } 09015 } 09016 09017 if (res < 0) { /* the call failed for some reason */ 09018 if (*reason == 0) { /* if the call failed (not busy or no answer) 09019 * update the cdr with the failed message */ 09020 cdr_res = ast_pbx_outgoing_cdr_failed(); 09021 if (cdr_res != 0) { 09022 res = cdr_res; 09023 goto outgoing_app_cleanup; 09024 } 09025 } 09026 } 09027 09028 } else { 09029 struct async_stat *as; 09030 if (!(as = ast_calloc(1, sizeof(*as)))) { 09031 res = -1; 09032 goto outgoing_app_cleanup; 09033 } 09034 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09035 if (!chan) { 09036 ast_free(as); 09037 res = -1; 09038 goto outgoing_app_cleanup; 09039 } 09040 as->chan = chan; 09041 ast_copy_string(as->app, app, sizeof(as->app)); 09042 if (appdata) 09043 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09044 as->timeout = timeout; 09045 ast_set_variables(chan, vars); 09046 if (account) 09047 ast_cdr_setaccount(chan, account); 09048 /* Start a new thread, and get something handling this channel. */ 09049 if (locked_channel) 09050 ast_channel_lock(chan); 09051 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09052 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09053 ast_free(as); 09054 if (locked_channel) 09055 ast_channel_unlock(chan); 09056 ast_hangup(chan); 09057 res = -1; 09058 goto outgoing_app_cleanup; 09059 } else { 09060 if (locked_channel) 09061 *locked_channel = chan; 09062 } 09063 res = 0; 09064 } 09065 outgoing_app_cleanup: 09066 ast_variables_destroy(vars); 09067 return res; 09068 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 8752 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().
08753 { 08754 /* allocate a channel */ 08755 struct ast_channel *chan = ast_dummy_channel_alloc(); 08756 08757 if (!chan) 08758 return -1; /* failure */ 08759 08760 chan->cdr = ast_cdr_alloc(); 08761 if (!chan->cdr) { 08762 /* allocation of the cdr failed */ 08763 chan = ast_channel_unref(chan); /* free the channel */ 08764 return -1; /* return failure */ 08765 } 08766 08767 /* allocation of the cdr was successful */ 08768 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 08769 ast_cdr_start(chan->cdr); /* record the start and stop time */ 08770 ast_cdr_end(chan->cdr); 08771 ast_cdr_failed(chan->cdr); /* set the status to failed */ 08772 ast_cdr_detach(chan->cdr); /* post and free the record */ 08773 chan->cdr = NULL; 08774 chan = ast_channel_unref(chan); /* free the channel */ 08775 08776 return 0; /* success */ 08777 }
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 8779 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, outgoing_helper::cid_name, outgoing_helper::cid_num, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
08780 { 08781 struct ast_channel *chan; 08782 struct async_stat *as; 08783 int res = -1, cdr_res = -1; 08784 struct outgoing_helper oh; 08785 08786 if (synchronous) { 08787 oh.context = context; 08788 oh.exten = exten; 08789 oh.priority = priority; 08790 oh.cid_num = cid_num; 08791 oh.cid_name = cid_name; 08792 oh.account = account; 08793 oh.vars = vars; 08794 oh.parent_channel = NULL; 08795 08796 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08797 if (channel) { 08798 *channel = chan; 08799 if (chan) 08800 ast_channel_lock(chan); 08801 } 08802 if (chan) { 08803 if (chan->_state == AST_STATE_UP) { 08804 res = 0; 08805 ast_verb(4, "Channel %s was answered.\n", chan->name); 08806 08807 if (synchronous > 1) { 08808 if (channel) 08809 ast_channel_unlock(chan); 08810 if (ast_pbx_run(chan)) { 08811 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08812 if (channel) 08813 *channel = NULL; 08814 ast_hangup(chan); 08815 chan = NULL; 08816 res = -1; 08817 } 08818 } else { 08819 if (ast_pbx_start(chan)) { 08820 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 08821 if (channel) { 08822 *channel = NULL; 08823 ast_channel_unlock(chan); 08824 } 08825 ast_hangup(chan); 08826 res = -1; 08827 } 08828 chan = NULL; 08829 } 08830 } else { 08831 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08832 08833 if (chan->cdr) { /* update the cdr */ 08834 /* here we update the status of the call, which sould be busy. 08835 * if that fails then we set the status to failed */ 08836 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08837 ast_cdr_failed(chan->cdr); 08838 } 08839 08840 if (channel) { 08841 *channel = NULL; 08842 ast_channel_unlock(chan); 08843 } 08844 ast_hangup(chan); 08845 chan = NULL; 08846 } 08847 } 08848 08849 if (res < 0) { /* the call failed for some reason */ 08850 if (*reason == 0) { /* if the call failed (not busy or no answer) 08851 * update the cdr with the failed message */ 08852 cdr_res = ast_pbx_outgoing_cdr_failed(); 08853 if (cdr_res != 0) { 08854 res = cdr_res; 08855 goto outgoing_exten_cleanup; 08856 } 08857 } 08858 08859 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08860 /* check if "failed" exists */ 08861 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08862 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 08863 if (chan) { 08864 char failed_reason[4] = ""; 08865 if (!ast_strlen_zero(context)) 08866 ast_copy_string(chan->context, context, sizeof(chan->context)); 08867 set_ext_pri(chan, "failed", 1); 08868 ast_set_variables(chan, vars); 08869 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08870 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08871 if (account) 08872 ast_cdr_setaccount(chan, account); 08873 if (ast_pbx_run(chan)) { 08874 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08875 ast_hangup(chan); 08876 } 08877 chan = NULL; 08878 } 08879 } 08880 } 08881 } else { 08882 if (!(as = ast_calloc(1, sizeof(*as)))) { 08883 res = -1; 08884 goto outgoing_exten_cleanup; 08885 } 08886 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 08887 if (channel) { 08888 *channel = chan; 08889 if (chan) 08890 ast_channel_lock(chan); 08891 } 08892 if (!chan) { 08893 ast_free(as); 08894 res = -1; 08895 goto outgoing_exten_cleanup; 08896 } 08897 as->chan = chan; 08898 ast_copy_string(as->context, context, sizeof(as->context)); 08899 set_ext_pri(as->chan, exten, priority); 08900 as->timeout = timeout; 08901 ast_set_variables(chan, vars); 08902 if (account) 08903 ast_cdr_setaccount(chan, account); 08904 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08905 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08906 ast_free(as); 08907 if (channel) { 08908 *channel = NULL; 08909 ast_channel_unlock(chan); 08910 } 08911 ast_hangup(chan); 08912 res = -1; 08913 goto outgoing_exten_cleanup; 08914 } 08915 res = 0; 08916 } 08917 outgoing_exten_cleanup: 08918 ast_variables_destroy(vars); 08919 return res; 08920 }
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 |
Zero | on success | |
non-zero | on failure |
Definition at line 5382 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), do_notify(), mgcp_ss(), pri_ss_thread(), skinny_newcall(), and unistim_ss().
05383 { 05384 return ast_pbx_run_args(c, NULL); 05385 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 8932 of file pbx.c.
References app_tmp::app, app, ast_free, ast_hangup(), ast_log(), ast_string_field_free_memory, ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, ast_channel::name, pbx_exec(), and pbx_findapp().
Referenced by ast_pbx_outgoing_app().
08933 { 08934 struct app_tmp *tmp = data; 08935 struct ast_app *app; 08936 app = pbx_findapp(tmp->app); 08937 if (app) { 08938 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 08939 pbx_exec(tmp->chan, app, tmp->data); 08940 } else 08941 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 08942 ast_hangup(tmp->chan); 08943 ast_string_field_free_memory(tmp); 08944 ast_free(tmp); 08945 return NULL; 08946 }
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 |
Zero | on success | |
non-zero | on failure |
Definition at line 5362 of file pbx.c.
References __ast_pbx_run(), args, 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(), and handle_gosub().
05363 { 05364 enum ast_pbx_result res = AST_PBX_SUCCESS; 05365 05366 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05367 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05368 return AST_PBX_FAILED; 05369 } 05370 05371 if (increase_call_count(c)) { 05372 return AST_PBX_CALL_LIMIT; 05373 } 05374 05375 res = __ast_pbx_run(c, args); 05376 05377 decrease_call_count(); 05378 05379 return res; 05380 }
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 5335 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(), rpt_call(), skinny_new(), unistim_new(), and usbradio_new().
05336 { 05337 pthread_t t; 05338 05339 if (!c) { 05340 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05341 return AST_PBX_FAILED; 05342 } 05343 05344 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05345 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05346 return AST_PBX_FAILED; 05347 } 05348 05349 if (increase_call_count(c)) 05350 return AST_PBX_CALL_LIMIT; 05351 05352 /* Start a new thread, and get something handling this channel. */ 05353 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05354 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05355 decrease_call_count(); 05356 return AST_PBX_FAILED; 05357 } 05358 05359 return AST_PBX_SUCCESS; 05360 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5392 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05393 { 05394 return totalcalls; 05395 }
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 10341 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().
10342 { 10343 return ast_rwlock_rdlock(&con->lock); 10344 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10323 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().
10324 { 10325 return ast_mutex_lock(&conlock); 10326 }
int ast_register_application2 | ( | const char * | app, | |
int(*)(struct ast_channel *, const char *) | execute, | |||
const char * | synopsis, | |||
const char * | description, | |||
void * | mod | |||
) |
Register an application.
app | Short name of the application | |
execute | a function callback to execute the application. It should return non-zero if the channel needs to be hung up. | |
synopsis | a short description (one line synopsis) of the application | |
description | long description with all of the details about the use of the application | |
mod | module this application belongs to |
0 | success | |
-1 | failure. |
Definition at line 5803 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, ast_app::list, 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().
05804 { 05805 struct ast_app *tmp, *cur = NULL; 05806 char tmps[80]; 05807 int length, res; 05808 #ifdef AST_XML_DOCS 05809 char *tmpxml; 05810 #endif 05811 05812 AST_RWLIST_WRLOCK(&apps); 05813 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 05814 if (!(res = strcasecmp(app, tmp->name))) { 05815 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 05816 AST_RWLIST_UNLOCK(&apps); 05817 return -1; 05818 } else if (res < 0) 05819 break; 05820 } 05821 05822 length = sizeof(*tmp) + strlen(app) + 1; 05823 05824 if (!(tmp = ast_calloc(1, length))) { 05825 AST_RWLIST_UNLOCK(&apps); 05826 return -1; 05827 } 05828 05829 if (ast_string_field_init(tmp, 128)) { 05830 AST_RWLIST_UNLOCK(&apps); 05831 ast_free(tmp); 05832 return -1; 05833 } 05834 05835 strcpy(tmp->name, app); 05836 tmp->execute = execute; 05837 tmp->module = mod; 05838 05839 #ifdef AST_XML_DOCS 05840 /* Try to lookup the docs in our XML documentation database */ 05841 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05842 /* load synopsis */ 05843 tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module)); 05844 ast_string_field_set(tmp, synopsis, tmpxml); 05845 ast_free(tmpxml); 05846 05847 /* load description */ 05848 tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); 05849 ast_string_field_set(tmp, description, tmpxml); 05850 ast_free(tmpxml); 05851 05852 /* load syntax */ 05853 tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module)); 05854 ast_string_field_set(tmp, syntax, tmpxml); 05855 ast_free(tmpxml); 05856 05857 /* load arguments */ 05858 tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module)); 05859 ast_string_field_set(tmp, arguments, tmpxml); 05860 ast_free(tmpxml); 05861 05862 /* load seealso */ 05863 tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module)); 05864 ast_string_field_set(tmp, seealso, tmpxml); 05865 ast_free(tmpxml); 05866 tmp->docsrc = AST_XML_DOC; 05867 } else { 05868 #endif 05869 ast_string_field_set(tmp, synopsis, synopsis); 05870 ast_string_field_set(tmp, description, description); 05871 #ifdef AST_XML_DOCS 05872 tmp->docsrc = AST_STATIC_DOC; 05873 } 05874 #endif 05875 05876 /* Store in alphabetical order */ 05877 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 05878 if (strcasecmp(tmp->name, cur->name) < 0) { 05879 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 05880 break; 05881 } 05882 } 05883 AST_RWLIST_TRAVERSE_SAFE_END; 05884 if (!cur) 05885 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 05886 05887 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 05888 05889 AST_RWLIST_UNLOCK(&apps); 05890 05891 return 0; 05892 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
0 | success | |
non-zero | failure |
Definition at line 5898 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_switch::list, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
05899 { 05900 struct ast_switch *tmp; 05901 05902 AST_RWLIST_WRLOCK(&switches); 05903 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05904 if (!strcasecmp(tmp->name, sw->name)) { 05905 AST_RWLIST_UNLOCK(&switches); 05906 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05907 return -1; 05908 } 05909 } 05910 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05911 AST_RWLIST_UNLOCK(&switches); 05912 05913 return 0; 05914 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 4701 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().
04702 { 04703 /* Cleanup the Notifys if hint is removed */ 04704 struct ast_hint *hint; 04705 04706 if (!e) { 04707 return -1; 04708 } 04709 04710 hint = ao2_find(hints, e, OBJ_UNLINK); 04711 if (!hint) { 04712 return -1; 04713 } 04714 04715 /* 04716 * The extension is being destroyed so we must save some 04717 * information to notify that the extension is deactivated. 04718 */ 04719 ao2_lock(hint); 04720 ast_copy_string(hint->context_name, 04721 ast_get_context_name(ast_get_extension_context(hint->exten)), 04722 sizeof(hint->context_name)); 04723 ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten), 04724 sizeof(hint->exten_name)); 04725 hint->exten = NULL; 04726 ao2_unlock(hint); 04727 04728 ao2_ref(hint, -1); 04729 04730 return 0; 04731 }
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 4885 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), and loopback_exec().
04886 { 04887 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04888 }
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 | |||
) |
If an extension hint exists, return non-zero.
hint | buffer for hint | |
hintsize | Maximum size of hint buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
name | buffer for name portion of hint | |
namesize | Maximum size of name buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
c | Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded. | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 4840 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), ast_str_set(), and fake_context::name.
Referenced by ast_str_retrieve_variable().
04841 { 04842 struct ast_exten *e = ast_hint_extension(c, context, exten); 04843 04844 if (!e) { 04845 return 0; 04846 } 04847 04848 if (hint) { 04849 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 04850 } 04851 if (name) { 04852 const char *tmp = ast_get_extension_app_data(e); 04853 if (tmp) { 04854 ast_str_set(name, namesize, "%s", tmp); 04855 } 04856 } 04857 return -1; 04858 }
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 3130 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_channel::name, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, str, ast_party_dialed::transit_network_select, and ast_channel::uniqueid.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03131 { 03132 const char not_found = '\0'; 03133 char *tmpvar; 03134 const char *ret; 03135 const char *s; /* the result */ 03136 int offset, length; 03137 int i, need_substring; 03138 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03139 03140 if (c) { 03141 ast_channel_lock(c); 03142 places[0] = &c->varshead; 03143 } 03144 /* 03145 * Make a copy of var because parse_variable_name() modifies the string. 03146 * Then if called directly, we might need to run substring() on the result; 03147 * remember this for later in 'need_substring', 'offset' and 'length' 03148 */ 03149 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03150 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03151 03152 /* 03153 * Look first into predefined variables, then into variable lists. 03154 * Variable 's' points to the result, according to the following rules: 03155 * s == ¬_found (set at the beginning) means that we did not find a 03156 * matching variable and need to look into more places. 03157 * If s != ¬_found, s is a valid result string as follows: 03158 * s = NULL if the variable does not have a value; 03159 * you typically do this when looking for an unset predefined variable. 03160 * s = workspace if the result has been assembled there; 03161 * typically done when the result is built e.g. with an snprintf(), 03162 * so we don't need to do an additional copy. 03163 * s != workspace in case we have a string, that needs to be copied 03164 * (the ast_copy_string is done once for all at the end). 03165 * Typically done when the result is already available in some string. 03166 */ 03167 s = ¬_found; /* default value */ 03168 if (c) { /* This group requires a valid channel */ 03169 /* Names with common parts are looked up a piece at a time using strncmp. */ 03170 if (!strncmp(var, "CALL", 4)) { 03171 if (!strncmp(var + 4, "ING", 3)) { 03172 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03173 ast_str_set(str, maxlen, "%d", 03174 ast_party_id_presentation(&c->caller.id)); 03175 s = ast_str_buffer(*str); 03176 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03177 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03178 s = ast_str_buffer(*str); 03179 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03180 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03181 s = ast_str_buffer(*str); 03182 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03183 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03184 s = ast_str_buffer(*str); 03185 } 03186 } 03187 } else if (!strcmp(var, "HINT")) { 03188 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03189 } else if (!strcmp(var, "HINTNAME")) { 03190 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03191 } else if (!strcmp(var, "EXTEN")) { 03192 s = c->exten; 03193 } else if (!strcmp(var, "CONTEXT")) { 03194 s = c->context; 03195 } else if (!strcmp(var, "PRIORITY")) { 03196 ast_str_set(str, maxlen, "%d", c->priority); 03197 s = ast_str_buffer(*str); 03198 } else if (!strcmp(var, "CHANNEL")) { 03199 s = c->name; 03200 } else if (!strcmp(var, "UNIQUEID")) { 03201 s = c->uniqueid; 03202 } else if (!strcmp(var, "HANGUPCAUSE")) { 03203 ast_str_set(str, maxlen, "%d", c->hangupcause); 03204 s = ast_str_buffer(*str); 03205 } 03206 } 03207 if (s == ¬_found) { /* look for more */ 03208 if (!strcmp(var, "EPOCH")) { 03209 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03210 s = ast_str_buffer(*str); 03211 } else if (!strcmp(var, "SYSTEMNAME")) { 03212 s = ast_config_AST_SYSTEM_NAME; 03213 } else if (!strcmp(var, "ENTITYID")) { 03214 char workspace[20]; 03215 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03216 s = workspace; 03217 } 03218 } 03219 /* if not found, look into chanvars or global vars */ 03220 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03221 struct ast_var_t *variables; 03222 if (!places[i]) 03223 continue; 03224 if (places[i] == &globals) 03225 ast_rwlock_rdlock(&globalslock); 03226 AST_LIST_TRAVERSE(places[i], variables, entries) { 03227 if (!strcasecmp(ast_var_name(variables), var)) { 03228 s = ast_var_value(variables); 03229 break; 03230 } 03231 } 03232 if (places[i] == &globals) 03233 ast_rwlock_unlock(&globalslock); 03234 } 03235 if (s == ¬_found || s == NULL) { 03236 ast_debug(5, "Result of '%s' is NULL\n", var); 03237 ret = NULL; 03238 } else { 03239 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03240 if (s != ast_str_buffer(*str)) { 03241 ast_str_set(str, maxlen, "%s", s); 03242 } 03243 ret = ast_str_buffer(*str); 03244 if (need_substring) { 03245 ret = ast_str_substring(*str, offset, length); 03246 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03247 } 03248 } 03249 03250 if (c) { 03251 ast_channel_unlock(c); 03252 } 03253 return ret; 03254 }
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 3928 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_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().
03929 { 03930 size_t used; 03931 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 03932 }
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 3749 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().
03750 { 03751 /* Substitutes variables into buf, based on string templ */ 03752 char *cp4 = NULL; 03753 const char *tmp, *whereweare; 03754 int orig_size = 0; 03755 int offset, offset2, isfunction; 03756 const char *nextvar, *nextexp, *nextthing; 03757 const char *vars, *vare; 03758 char *finalvars; 03759 int pos, brackets, needsub, len; 03760 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03761 03762 ast_str_reset(*buf); 03763 whereweare = tmp = templ; 03764 while (!ast_strlen_zero(whereweare)) { 03765 /* reset our buffer */ 03766 ast_str_reset(substr3); 03767 03768 /* Assume we're copying the whole remaining string */ 03769 pos = strlen(whereweare); 03770 nextvar = NULL; 03771 nextexp = NULL; 03772 nextthing = strchr(whereweare, '$'); 03773 if (nextthing) { 03774 switch (nextthing[1]) { 03775 case '{': 03776 nextvar = nextthing; 03777 pos = nextvar - whereweare; 03778 break; 03779 case '[': 03780 nextexp = nextthing; 03781 pos = nextexp - whereweare; 03782 break; 03783 default: 03784 pos = 1; 03785 } 03786 } 03787 03788 if (pos) { 03789 /* Copy that many bytes */ 03790 ast_str_append_substr(buf, maxlen, whereweare, pos); 03791 03792 templ += pos; 03793 whereweare += pos; 03794 } 03795 03796 if (nextvar) { 03797 /* We have a variable. Find the start and end, and determine 03798 if we are going to have to recursively call ourselves on the 03799 contents */ 03800 vars = vare = nextvar + 2; 03801 brackets = 1; 03802 needsub = 0; 03803 03804 /* Find the end of it */ 03805 while (brackets && *vare) { 03806 if ((vare[0] == '$') && (vare[1] == '{')) { 03807 needsub++; 03808 } else if (vare[0] == '{') { 03809 brackets++; 03810 } else if (vare[0] == '}') { 03811 brackets--; 03812 } else if ((vare[0] == '$') && (vare[1] == '[')) 03813 needsub++; 03814 vare++; 03815 } 03816 if (brackets) 03817 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03818 len = vare - vars - 1; 03819 03820 /* Skip totally over variable string */ 03821 whereweare += (len + 3); 03822 03823 /* Store variable name (and truncate) */ 03824 ast_str_set_substr(&substr1, 0, vars, len); 03825 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03826 03827 /* Substitute if necessary */ 03828 if (needsub) { 03829 size_t used; 03830 if (!substr2) { 03831 substr2 = ast_str_create(16); 03832 } 03833 03834 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03835 finalvars = ast_str_buffer(substr2); 03836 } else { 03837 finalvars = ast_str_buffer(substr1); 03838 } 03839 03840 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03841 if (isfunction) { 03842 /* Evaluate function */ 03843 if (c || !headp) { 03844 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03845 } else { 03846 struct varshead old; 03847 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03848 if (bogus) { 03849 memcpy(&old, &bogus->varshead, sizeof(old)); 03850 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03851 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03852 /* Don't deallocate the varshead that was passed in */ 03853 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03854 ast_channel_unref(bogus); 03855 } else { 03856 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03857 } 03858 } 03859 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03860 } else { 03861 /* Retrieve variable value */ 03862 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 03863 cp4 = ast_str_buffer(substr3); 03864 } 03865 if (cp4) { 03866 ast_str_substring(substr3, offset, offset2); 03867 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03868 } 03869 } else if (nextexp) { 03870 /* We have an expression. Find the start and end, and determine 03871 if we are going to have to recursively call ourselves on the 03872 contents */ 03873 vars = vare = nextexp + 2; 03874 brackets = 1; 03875 needsub = 0; 03876 03877 /* Find the end of it */ 03878 while (brackets && *vare) { 03879 if ((vare[0] == '$') && (vare[1] == '[')) { 03880 needsub++; 03881 brackets++; 03882 vare++; 03883 } else if (vare[0] == '[') { 03884 brackets++; 03885 } else if (vare[0] == ']') { 03886 brackets--; 03887 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03888 needsub++; 03889 vare++; 03890 } 03891 vare++; 03892 } 03893 if (brackets) 03894 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03895 len = vare - vars - 1; 03896 03897 /* Skip totally over expression */ 03898 whereweare += (len + 3); 03899 03900 /* Store variable name (and truncate) */ 03901 ast_str_set_substr(&substr1, 0, vars, len); 03902 03903 /* Substitute if necessary */ 03904 if (needsub) { 03905 size_t used; 03906 if (!substr2) { 03907 substr2 = ast_str_create(16); 03908 } 03909 03910 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03911 finalvars = ast_str_buffer(substr2); 03912 } else { 03913 finalvars = ast_str_buffer(substr1); 03914 } 03915 03916 if (ast_str_expr(&substr3, 0, c, finalvars)) { 03917 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 03918 } 03919 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03920 } 03921 } 03922 *used = ast_str_strlen(*buf) - orig_size; 03923 ast_free(substr1); 03924 ast_free(substr2); 03925 ast_free(substr3); 03926 }
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 3934 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().
03935 { 03936 size_t used; 03937 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 03938 }
static const char* ast_str_substring | ( | struct ast_str * | value, | |
int | offset, | |||
int | length | |||
) | [static] |
Definition at line 3065 of file pbx.c.
References ast_str_buffer(), ast_str_reset(), ast_str_strlen(), ast_str_update(), and value.
Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().
03066 { 03067 int lr; /* length of the input string after the copy */ 03068 03069 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 03070 03071 /* Quick check if no need to do anything */ 03072 if (offset == 0 && length >= lr) /* take the whole string */ 03073 return ast_str_buffer(value); 03074 03075 if (offset < 0) { /* translate negative offset into positive ones */ 03076 offset = lr + offset; 03077 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03078 offset = 0; 03079 } 03080 03081 /* too large offset result in empty string so we know what to return */ 03082 if (offset >= lr) { 03083 ast_str_reset(value); 03084 return ast_str_buffer(value); 03085 } 03086 03087 if (offset > 0) { 03088 /* Go ahead and chop off the beginning */ 03089 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 03090 lr -= offset; 03091 } 03092 03093 if (length >= 0 && length < lr) { /* truncate if necessary */ 03094 char *tmp = ast_str_buffer(value); 03095 tmp[length] = '\0'; 03096 ast_str_update(value); 03097 } else if (length < 0) { 03098 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 03099 char *tmp = ast_str_buffer(value); 03100 tmp[lr + length] = '\0'; 03101 ast_str_update(value); 03102 } else { 03103 ast_str_reset(value); 03104 } 03105 } else { 03106 /* Nothing to do, but update the buffer length */ 03107 ast_str_update(value); 03108 } 03109 03110 return ast_str_buffer(value); 03111 }
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 10346 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().
10347 { 10348 return ast_rwlock_unlock(&con->lock); 10349 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10328 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().
10329 { 10330 return ast_mutex_unlock(&conlock); 10331 }
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) |
0 | success | |
-1 | failure |
Definition at line 7144 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::list, ast_app::name, and unreference_cached_app().
Referenced by __unload_module(), load_module(), and unload_module().
07145 { 07146 struct ast_app *tmp; 07147 07148 AST_RWLIST_WRLOCK(&apps); 07149 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 07150 if (!strcasecmp(app, tmp->name)) { 07151 unreference_cached_app(tmp); 07152 AST_RWLIST_REMOVE_CURRENT(list); 07153 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 07154 ast_string_field_free_memory(tmp); 07155 ast_free(tmp); 07156 break; 07157 } 07158 } 07159 AST_RWLIST_TRAVERSE_SAFE_END; 07160 AST_RWLIST_UNLOCK(&apps); 07161 07162 return tmp ? 0 : -1; 07163 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 5916 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_switch::list.
Referenced by __unload_module(), and unload_module().
05917 { 05918 AST_RWLIST_WRLOCK(&switches); 05919 AST_RWLIST_REMOVE(&switches, sw, list); 05920 AST_RWLIST_UNLOCK(&switches); 05921 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 10460 of file pbx.c.
References exten, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
10462 { 10463 if (!exten) 10464 return con ? con->root : NULL; 10465 else 10466 return exten->next; 10467 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 10493 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10495 { 10496 if (!ip) 10497 return con ? con->ignorepats : NULL; 10498 else 10499 return ip->next; 10500 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 10484 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
10486 { 10487 if (!inc) 10488 return con ? con->includes : NULL; 10489 else 10490 return inc->next; 10491 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 10469 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, AST_LIST_NEXT, and ast_sw::list.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10471 { 10472 if (!sw) 10473 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10474 else 10475 return AST_LIST_NEXT(sw, list); 10476 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 10455 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 | |||
) |
Definition at line 10478 of file pbx.c.
References exten, and ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
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 10336 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().
10337 { 10338 return ast_rwlock_wrlock(&con->lock); 10339 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10318 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().
10319 { 10320 return ast_mutex_lock(&conlock); 10321 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 8691 of file pbx.c.
References ast_channel::_state, app, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_free, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), AST_STATE_UP, ast_strlen_zero(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, LOG_ERROR, LOG_WARNING, ast_channel::name, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, and async_stat::timeout.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
08692 { 08693 struct async_stat *as = data; 08694 struct ast_channel *chan = as->chan; 08695 int timeout = as->timeout; 08696 int res; 08697 struct ast_frame *f; 08698 struct ast_app *app; 08699 08700 while (timeout && (chan->_state != AST_STATE_UP)) { 08701 res = ast_waitfor(chan, timeout); 08702 if (res < 1) 08703 break; 08704 if (timeout > -1) 08705 timeout = res; 08706 f = ast_read(chan); 08707 if (!f) 08708 break; 08709 if (f->frametype == AST_FRAME_CONTROL) { 08710 if ((f->subclass.integer == AST_CONTROL_BUSY) || 08711 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 08712 ast_frfree(f); 08713 break; 08714 } 08715 } 08716 ast_frfree(f); 08717 } 08718 if (chan->_state == AST_STATE_UP) { 08719 if (!ast_strlen_zero(as->app)) { 08720 app = pbx_findapp(as->app); 08721 if (app) { 08722 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 08723 pbx_exec(chan, app, as->appdata); 08724 } else 08725 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 08726 } else { 08727 if (!ast_strlen_zero(as->context)) 08728 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 08729 if (!ast_strlen_zero(as->exten)) 08730 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 08731 if (as->priority > 0) 08732 chan->priority = as->priority; 08733 /* Run the PBX */ 08734 if (ast_pbx_run(chan)) { 08735 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 08736 } else { 08737 /* PBX will have taken care of this */ 08738 chan = NULL; 08739 } 08740 } 08741 } 08742 ast_free(as); 08743 if (chan) 08744 ast_hangup(chan); 08745 return NULL; 08746 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1608 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().
01609 { 01610 char extenstr[40]; 01611 struct ast_str *my_prefix = ast_str_alloca(1024); 01612 01613 extenstr[0] = '\0'; 01614 01615 if (node && node->exten) 01616 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01617 01618 if (strlen(node->x) > 1) { 01619 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01620 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01621 node->exten ? node->exten->exten : "", extenstr); 01622 } else { 01623 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01624 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01625 node->exten ? node->exten->exten : "", extenstr); 01626 } 01627 01628 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01629 01630 if (node->next_char) 01631 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01632 01633 if (node->alt_char) 01634 cli_match_char_tree(node->alt_char, prefix, fd); 01635 }
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 4906 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.
04907 { 04908 int digit; 04909 04910 buf[pos] = '\0'; /* make sure it is properly terminated */ 04911 while (ast_matchmore_extension(c, c->context, buf, 1, 04912 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04913 /* As long as we're willing to wait, and as long as it's not defined, 04914 keep reading digits until we can't possibly get a right answer anymore. */ 04915 digit = ast_waitfordigit(c, waittime); 04916 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04917 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 04918 } else { 04919 if (!digit) /* No entry */ 04920 break; 04921 if (digit < 0) /* Error, maybe a hangup */ 04922 return -1; 04923 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 04924 buf[pos++] = digit; 04925 buf[pos] = '\0'; 04926 } 04927 waittime = c->pbx->dtimeoutms; 04928 } 04929 } 04930 return 0; 04931 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 1056 of file pbx.c.
Referenced by get_pattern_node().
01057 { 01058 const unsigned char *ac = a; 01059 const unsigned char *bc = b; 01060 01061 return *ac - *bc; 01062 }
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 6103 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().
06104 { 06105 struct ast_hint *hint; 06106 char *ret = NULL; 06107 int which = 0; 06108 int wordlen; 06109 struct ao2_iterator i; 06110 06111 if (pos != 3) 06112 return NULL; 06113 06114 wordlen = strlen(word); 06115 06116 /* walk through all hints */ 06117 i = ao2_iterator_init(hints, 0); 06118 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06119 ao2_lock(hint); 06120 if (!hint->exten) { 06121 /* The extension has already been destroyed */ 06122 ao2_unlock(hint); 06123 continue; 06124 } 06125 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 06126 ret = ast_strdup(ast_get_extension_name(hint->exten)); 06127 ao2_unlock(hint); 06128 ao2_ref(hint, -1); 06129 break; 06130 } 06131 ao2_unlock(hint); 06132 } 06133 ao2_iterator_destroy(&i); 06134 06135 return ret; 06136 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 6313 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().
06315 { 06316 struct ast_context *c = NULL; 06317 char *ret = NULL; 06318 int which = 0; 06319 int wordlen; 06320 06321 /* we are do completion of [exten@]context on second position only */ 06322 if (pos != 2) 06323 return NULL; 06324 06325 ast_rdlock_contexts(); 06326 06327 wordlen = strlen(word); 06328 06329 /* walk through all contexts and return the n-th match */ 06330 while ( (c = ast_walk_contexts(c)) ) { 06331 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06332 ret = ast_strdup(ast_get_context_name(c)); 06333 break; 06334 } 06335 } 06336 06337 ast_unlock_contexts(); 06338 06339 return ret; 06340 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7285 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, store_hint::context, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, ast_exten::datad, ast_exten::exten, store_hint::first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_exten::peer_table, ast_exten::priority, and ast_exten::registrar.
Referenced by ast_merge_contexts_and_delete().
07286 { 07287 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 07288 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 07289 struct ast_hashtab_iter *exten_iter; 07290 struct ast_hashtab_iter *prio_iter; 07291 int insert_count = 0; 07292 int first = 1; 07293 07294 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 07295 the current registrar, and copy them to the new context. If the new context does not 07296 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 07297 only create the empty matching context if the old one meets the criteria */ 07298 07299 if (context->root_table) { 07300 exten_iter = ast_hashtab_start_traversal(context->root_table); 07301 while ((exten_item=ast_hashtab_next(exten_iter))) { 07302 if (new) { 07303 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 07304 } else { 07305 new_exten_item = NULL; 07306 } 07307 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07308 while ((prio_item=ast_hashtab_next(prio_iter))) { 07309 int res1; 07310 char *dupdstr; 07311 07312 if (new_exten_item) { 07313 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 07314 } else { 07315 new_prio_item = NULL; 07316 } 07317 if (strcmp(prio_item->registrar,registrar) == 0) { 07318 continue; 07319 } 07320 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 07321 if (!new) { 07322 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 */ 07323 } 07324 07325 /* copy in the includes, switches, and ignorepats */ 07326 if (first) { /* but, only need to do this once */ 07327 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07328 first = 0; 07329 } 07330 07331 if (!new) { 07332 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07333 return; /* no sense continuing. */ 07334 } 07335 /* we will not replace existing entries in the new context with stuff from the old context. 07336 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07337 07338 dupdstr = ast_strdup(prio_item->data); 07339 07340 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07341 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07342 if (!res1 && new_exten_item && new_prio_item){ 07343 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07344 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07345 } else { 07346 /* 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, 07347 and no double frees take place, either! */ 07348 insert_count++; 07349 } 07350 } 07351 ast_hashtab_end_traversal(prio_iter); 07352 } 07353 ast_hashtab_end_traversal(exten_iter); 07354 } 07355 07356 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07357 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07358 /* we could have given it the registrar of the other module who incremented the refcount, 07359 but that's not available, so we give it the registrar we know about */ 07360 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07361 07362 /* copy in the includes, switches, and ignorepats */ 07363 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07364 } 07365 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7252 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().
07253 { 07254 struct ast_include *i; 07255 struct ast_ignorepat *ip; 07256 struct ast_sw *sw; 07257 07258 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); 07259 /* copy in the includes, switches, and ignorepats */ 07260 /* walk through includes */ 07261 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 07262 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 07263 continue; /* not mine */ 07264 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 07265 } 07266 07267 /* walk through switches */ 07268 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 07269 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 07270 continue; /* not mine */ 07271 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)); 07272 } 07273 07274 /* walk thru ignorepats ... */ 07275 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 07276 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 07277 continue; /* not mine */ 07278 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 07279 } 07280 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2229 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, ast_context::root_table, and t1.
Referenced by pbx_find_extension().
02230 { 02231 struct ast_hashtab_iter *t1; 02232 struct ast_exten *e1; 02233 #ifdef NEED_DEBUG 02234 int biggest_bucket, resizes, numobjs, numbucks; 02235 02236 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02237 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02238 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02239 numobjs, numbucks, biggest_bucket, resizes); 02240 #endif 02241 t1 = ast_hashtab_start_traversal(con->root_table); 02242 while ((e1 = ast_hashtab_next(t1))) { 02243 if (e1->exten) { 02244 add_exten_to_pattern_tree(con, e1, 0); 02245 } else { 02246 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02247 } 02248 } 02249 ast_hashtab_end_traversal(t1); 02250 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 5293 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().
05294 { 05295 ast_mutex_lock(&maxcalllock); 05296 if (countcalls > 0) 05297 countcalls--; 05298 ast_mutex_unlock(&maxcalllock); 05299 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 5301 of file pbx.c.
References ast_free, ast_hashtab_destroy(), ast_remove_hint(), ast_exten::priority, and PRIORITY_HINT.
Referenced by __ast_internal_context_destroy(), and ast_context_remove_extension_callerid2().
05302 { 05303 if (e->priority == PRIORITY_HINT) 05304 ast_remove_hint(e); 05305 05306 if (e->peer_table) 05307 ast_hashtab_destroy(e->peer_table,0); 05308 if (e->peer_label_table) 05309 ast_hashtab_destroy(e->peer_label_table, 0); 05310 if (e->datad) 05311 e->datad(e->data); 05312 ast_free(e); 05313 }
static void destroy_hint | ( | void * | obj | ) | [static] |
Definition at line 4671 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().
04672 { 04673 struct ast_hint *hint = obj; 04674 04675 if (hint->callbacks) { 04676 struct ast_state_cb *state_cb; 04677 const char *context_name; 04678 const char *exten_name; 04679 04680 if (hint->exten) { 04681 context_name = ast_get_context_name(ast_get_extension_context(hint->exten)); 04682 exten_name = ast_get_extension_name(hint->exten); 04683 hint->exten = NULL; 04684 } else { 04685 /* The extension has already been destroyed */ 04686 context_name = hint->context_name; 04687 exten_name = hint->exten_name; 04688 } 04689 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 04690 /* Notify with -1 and remove all callbacks */ 04691 /* NOTE: The casts will not be needed for v1.10 and later */ 04692 state_cb->change_cb((char *) context_name, (char *) exten_name, 04693 AST_EXTENSION_DEACTIVATED, state_cb->data); 04694 ao2_ref(state_cb, -1); 04695 } 04696 ao2_ref(hint->callbacks, -1); 04697 } 04698 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2252 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().
02253 { 02254 /* destroy all the alternates */ 02255 if (pattern_tree->alt_char) { 02256 destroy_pattern_tree(pattern_tree->alt_char); 02257 pattern_tree->alt_char = 0; 02258 } 02259 /* destroy all the nexts */ 02260 if (pattern_tree->next_char) { 02261 destroy_pattern_tree(pattern_tree->next_char); 02262 pattern_tree->next_char = 0; 02263 } 02264 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02265 ast_free(pattern_tree); 02266 }
static void destroy_state_cb | ( | void * | doomed | ) | [static] |
Definition at line 4502 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().
04503 { 04504 struct ast_state_cb *state_cb = doomed; 04505 04506 if (state_cb->destroy_cb) { 04507 state_cb->destroy_cb(state_cb->id, state_cb->data); 04508 } 04509 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 10213 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(), device_state_tps, handle_statechange(), and LOG_ERROR.
10214 { 10215 const char *device; 10216 struct statechange *sc; 10217 10218 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 10219 if (ast_strlen_zero(device)) { 10220 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 10221 return; 10222 } 10223 10224 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 10225 return; 10226 strcpy(sc->dev, device); 10227 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 10228 ast_free(sc); 10229 } 10230 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3256 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03257 { 03258 struct pbx_exception *exception = data; 03259 ast_string_field_free_memory(exception); 03260 ast_free(exception); 03261 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 2402 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02403 { 02404 /* make sure non-patterns come first. 02405 * If a is not a pattern, it either comes first or 02406 * we do a more complex pattern comparison. 02407 */ 02408 int ret = 0; 02409 02410 if (a[0] != '_') 02411 return (b[0] == '_') ? -1 : strcmp(a, b); 02412 02413 /* Now we know a is a pattern; if b is not, a comes first */ 02414 if (b[0] != '_') 02415 return 1; 02416 02417 /* ok we need full pattern sorting routine. 02418 * skip past the underscores */ 02419 ++a; ++b; 02420 do { 02421 unsigned char bitwise[2][32] = { { 0, } }; 02422 ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]); 02423 if (ret == 0) { 02424 /* Are the classes different, even though they score the same? */ 02425 ret = memcmp(bitwise[0], bitwise[1], 32); 02426 } 02427 } while (!ret && a && b); 02428 if (ret == 0) { 02429 return 0; 02430 } else { 02431 return (ret > 0) ? 1 : -1; 02432 } 02433 }
static int ext_cmp1 | ( | const char ** | p, | |
unsigned char * | bitwise | |||
) | [static] |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
ext_cmp1 compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, while bit 8-15 are the cardinality of the set minus 1. This way more specific patterns (smaller cardinality) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x000xx one character, xx 0x0yyxx yy character set starting with xx 0x10000 '.' (one or more of anything) 0x20000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is equivalent to NUL. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.
Definition at line 2322 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
02323 { 02324 int c, cmin = 0xff, count = 0; 02325 const char *end; 02326 02327 /* load value and advance pointer */ 02328 c = *(*p)++; 02329 02330 /* always return unless we have a set of chars */ 02331 switch (toupper(c)) { 02332 default: /* ordinary character */ 02333 bitwise[c / 8] = 1 << (c % 8); 02334 return 0x0100 | (c & 0xff); 02335 02336 case 'N': /* 2..9 */ 02337 bitwise[6] = 0xfc; 02338 bitwise[7] = 0x03; 02339 return 0x0800 | '2'; 02340 02341 case 'X': /* 0..9 */ 02342 bitwise[6] = 0xff; 02343 bitwise[7] = 0x03; 02344 return 0x0A00 | '0'; 02345 02346 case 'Z': /* 1..9 */ 02347 bitwise[6] = 0xfe; 02348 bitwise[7] = 0x03; 02349 return 0x0900 | '1'; 02350 02351 case '.': /* wildcard */ 02352 return 0x18000; 02353 02354 case '!': /* earlymatch */ 02355 return 0x28000; /* less specific than NULL */ 02356 02357 case '\0': /* empty string */ 02358 *p = NULL; 02359 return 0x30000; 02360 02361 case '[': /* pattern */ 02362 break; 02363 } 02364 /* locate end of set */ 02365 end = strchr(*p, ']'); 02366 02367 if (end == NULL) { 02368 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02369 return 0x40000; /* XXX make this entry go last... */ 02370 } 02371 02372 for (; *p < end ; (*p)++) { 02373 unsigned char c1, c2; /* first-last char in range */ 02374 c1 = (unsigned char)((*p)[0]); 02375 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02376 c2 = (unsigned char)((*p)[2]); 02377 *p += 2; /* skip a total of 3 chars */ 02378 } else { /* individual character */ 02379 c2 = c1; 02380 } 02381 if (c1 < cmin) { 02382 cmin = c1; 02383 } 02384 for (; c1 <= c2; c1++) { 02385 unsigned char mask = 1 << (c1 % 8); 02386 /*!\note If two patterns score the same, the one with the lowest 02387 * ascii values will compare as coming first. */ 02388 /* Flag the character as included (used) and count it. */ 02389 if (!(bitwise[ c1 / 8 ] & mask)) { 02390 bitwise[ c1 / 8 ] |= mask; 02391 count += 0x100; 02392 } 02393 } 02394 } 02395 (*p)++; 02396 return count == 0 ? 0x30000 : (count | cmin); 02397 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 8248 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
08249 { 08250 int count = 0; 08251 int insquares = 0; 08252 08253 while (*src && (count < len - 1)) { 08254 if (*src == '[') { 08255 insquares = 1; 08256 } else if (*src == ']') { 08257 insquares = 0; 08258 } else if (*src == ' ' && !insquares) { 08259 src++; 08260 continue; 08261 } 08262 *dst = *src; 08263 dst++; 08264 src++; 08265 count++; 08266 } 08267 *dst = '\0'; 08268 08269 return count; 08270 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2615 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().
02616 { 02617 int i; 02618 static int prof_id = -2; /* marker for 'unallocated' id */ 02619 if (prof_id == -2) { 02620 prof_id = ast_add_profile("ext_match", 0); 02621 } 02622 ast_mark(prof_id, 1); 02623 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode); 02624 ast_mark(prof_id, 0); 02625 return i; 02626 }
static struct ast_context * find_context | ( | const char * | context | ) | [static] |
lookup for a context with a given name,
found | context or NULL if not found. |
Definition at line 5427 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05428 { 05429 struct fake_context item; 05430 05431 ast_copy_string(item.name, context, sizeof(item.name)); 05432 05433 return ast_hashtab_lookup(contexts_table, &item); 05434 }
static struct ast_context * find_context_locked | ( | const char * | context | ) | [static] |
lookup for a context with a given name,
with | conlock held if found. | |
NULL | if not found. |
Definition at line 5441 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().
05442 { 05443 struct ast_context *c; 05444 struct fake_context item; 05445 05446 ast_copy_string(item.name, context, sizeof(item.name)); 05447 05448 ast_rdlock_contexts(); 05449 c = ast_hashtab_lookup(contexts_table, &item); 05450 if (!c) { 05451 ast_unlock_contexts(); 05452 } 05453 05454 return c; 05455 }
static int find_hint_by_cb_id | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Remove a watcher from the callback list.
Definition at line 4606 of file pbx.c.
References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.
Referenced by ast_extension_state_del().
04607 { 04608 struct ast_state_cb *state_cb; 04609 const struct ast_hint *hint = obj; 04610 int *id = arg; 04611 04612 if ((state_cb = ao2_find(hint->callbacks, id, 0))) { 04613 ao2_ref(state_cb, -1); 04614 return CMP_MATCH | CMP_STOP; 04615 } 04616 04617 return 0; 04618 }
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 3625 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03626 { 03627 char *args = strchr(function, '('); 03628 03629 if (!args) { 03630 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 03631 } else { 03632 char *p; 03633 *args++ = '\0'; 03634 if ((p = strrchr(args, ')'))) { 03635 *p = '\0'; 03636 } else { 03637 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 03638 } 03639 } 03640 return args; 03641 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static] |
Definition at line 1637 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, and match_char::next_char.
01638 { 01639 /* find the exten at the end of the rope */ 01640 struct match_char *node2 = node; 01641 01642 for (node2 = node; node2; node2 = node2->next_char) { 01643 if (node2->exten) { 01644 #ifdef NEED_DEBUG_HERE 01645 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01646 #endif 01647 return node2->exten; 01648 } 01649 } 01650 #ifdef NEED_DEBUG_HERE 01651 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01652 #endif 01653 return 0; 01654 }
static const char* get_pattern_node | ( | struct pattern_node * | node, | |
const char * | src, | |||
int | pattern, | |||
const char * | extenbuf | |||
) | [static] |
Definition at line 1986 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().
01987 { 01988 #define INC_DST_OVERFLOW_CHECK \ 01989 do { \ 01990 if (dst - node->buf < sizeof(node->buf) - 1) { \ 01991 ++dst; \ 01992 } else { \ 01993 overflow = 1; \ 01994 } \ 01995 } while (0) 01996 01997 node->specif = 0; 01998 node->buf[0] = '\0'; 01999 while (*src) { 02000 if (*src == '[' && pattern) { 02001 char *dst = node->buf; 02002 const char *src_next; 02003 int length; 02004 int overflow = 0; 02005 02006 /* get past the '[' */ 02007 ++src; 02008 for (;;) { 02009 if (*src == '\\') { 02010 /* Escaped character. */ 02011 ++src; 02012 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') { 02013 *dst = *src++; 02014 INC_DST_OVERFLOW_CHECK; 02015 } 02016 } else if (*src == '-') { 02017 unsigned char first; 02018 unsigned char last; 02019 02020 src_next = src; 02021 first = *(src_next - 1); 02022 last = *++src_next; 02023 02024 if (last == '\\') { 02025 /* Escaped character. */ 02026 last = *++src_next; 02027 } 02028 02029 /* Possible char range. */ 02030 if (node->buf[0] && last) { 02031 /* Expand the char range. */ 02032 while (++first <= last) { 02033 *dst = first; 02034 INC_DST_OVERFLOW_CHECK; 02035 } 02036 src = src_next + 1; 02037 } else { 02038 /* 02039 * There was no left or right char for the range. 02040 * It is just a '-'. 02041 */ 02042 *dst = *src++; 02043 INC_DST_OVERFLOW_CHECK; 02044 } 02045 } else if (*src == '\0') { 02046 ast_log(LOG_WARNING, 02047 "A matching ']' was not found for '[' in exten pattern '%s'\n", 02048 extenbuf); 02049 break; 02050 } else if (*src == ']') { 02051 ++src; 02052 break; 02053 } else { 02054 *dst = *src++; 02055 INC_DST_OVERFLOW_CHECK; 02056 } 02057 } 02058 /* null terminate the exploded range */ 02059 *dst = '\0'; 02060 02061 if (overflow) { 02062 ast_log(LOG_ERROR, 02063 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n", 02064 extenbuf); 02065 node->buf[0] = '\0'; 02066 continue; 02067 } 02068 02069 /* Sort the characters in character set. */ 02070 length = strlen(node->buf); 02071 if (!length) { 02072 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n", 02073 extenbuf); 02074 node->buf[0] = '\0'; 02075 continue; 02076 } 02077 qsort(node->buf, length, 1, compare_char); 02078 02079 /* Remove duplicate characters from character set. */ 02080 dst = node->buf; 02081 src_next = node->buf; 02082 while (*src_next++) { 02083 if (*dst != *src_next) { 02084 *++dst = *src_next; 02085 } 02086 } 02087 02088 length = strlen(node->buf); 02089 length <<= 8; 02090 node->specif = length | (unsigned char) node->buf[0]; 02091 break; 02092 } else if (*src == '-') { 02093 /* Skip dashes in all extensions. */ 02094 ++src; 02095 } else { 02096 if (*src == '\\') { 02097 /* 02098 * XXX The escape character here does not remove any special 02099 * meaning to characters except the '[', '\\', and '-' 02100 * characters since they are special only in this function. 02101 */ 02102 node->buf[0] = *++src; 02103 if (!node->buf[0]) { 02104 break; 02105 } 02106 } else { 02107 node->buf[0] = *src; 02108 if (pattern) { 02109 /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02110 if (node->buf[0] == 'n') { 02111 node->buf[0] = 'N'; 02112 } else if (node->buf[0] == 'x') { 02113 node->buf[0] = 'X'; 02114 } else if (node->buf[0] == 'z') { 02115 node->buf[0] = 'Z'; 02116 } 02117 } 02118 } 02119 node->buf[1] = '\0'; 02120 node->specif = 1; 02121 ++src; 02122 break; 02123 } 02124 } 02125 return src; 02126 02127 #undef INC_DST_OVERFLOW_CHECK 02128 }
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 7604 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and strsep().
Referenced by ast_build_timing().
07605 { 07606 int start, end; /* start and ending position */ 07607 unsigned int mask = 0; 07608 char *part; 07609 07610 /* Check for whole range */ 07611 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 07612 return (1 << max) - 1; 07613 } 07614 07615 while ((part = strsep(&src, "&"))) { 07616 /* Get start and ending position */ 07617 char *endpart = strchr(part, '-'); 07618 if (endpart) { 07619 *endpart++ = '\0'; 07620 } 07621 /* Find the start */ 07622 if ((start = lookup_name(part, names, max)) < 0) { 07623 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 07624 continue; 07625 } 07626 if (endpart) { /* find end of range */ 07627 if ((end = lookup_name(endpart, names, max)) < 0) { 07628 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 07629 continue; 07630 } 07631 } else { 07632 end = start; 07633 } 07634 /* Fill the mask. Remember that ranges are cyclic */ 07635 mask |= (1 << end); /* initialize with last element */ 07636 while (start != end) { 07637 mask |= (1 << start); 07638 if (++start >= max) { 07639 start = 0; 07640 } 07641 } 07642 } 07643 return mask; 07644 }
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 7647 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, ast_timing::minmask, and strsep().
Referenced by ast_build_timing().
07648 { 07649 char *endpart, *part; 07650 int x; 07651 int st_h, st_m; 07652 int endh, endm; 07653 int minute_start, minute_end; 07654 07655 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 07656 memset(i->minmask, 0, sizeof(i->minmask)); 07657 07658 /* 1-minute per bit */ 07659 /* Star is all times */ 07660 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 07661 /* 48, because each hour takes 2 integers; 30 bits each */ 07662 for (x = 0; x < 48; x++) { 07663 i->minmask[x] = 0x3fffffff; /* 30 bits */ 07664 } 07665 return; 07666 } 07667 /* Otherwise expect a range */ 07668 while ((part = strsep(×, "&"))) { 07669 if (!(endpart = strchr(part, '-'))) { 07670 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07671 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 07672 continue; 07673 } 07674 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 07675 continue; 07676 } 07677 *endpart++ = '\0'; 07678 /* why skip non digits? Mostly to skip spaces */ 07679 while (*endpart && !isdigit(*endpart)) { 07680 endpart++; 07681 } 07682 if (!*endpart) { 07683 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 07684 continue; 07685 } 07686 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07687 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 07688 continue; 07689 } 07690 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 07691 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 07692 continue; 07693 } 07694 minute_start = st_h * 60 + st_m; 07695 minute_end = endh * 60 + endm; 07696 /* Go through the time and enable each appropriate bit */ 07697 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 07698 i->minmask[x / 30] |= (1 << (x % 30)); 07699 } 07700 /* Do the last one */ 07701 i->minmask[x / 30] |= (1 << (x % 30)); 07702 } 07703 /* All done */ 07704 return; 07705 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 6638 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(), exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), strsep(), ast_cli_entry::usage, and ast_cli_args::word.
06639 { 06640 char *exten = NULL, *context = NULL; 06641 /* Variables used for different counters */ 06642 struct dialplan_counters counters; 06643 const char *incstack[AST_PBX_MAX_STACK]; 06644 06645 switch (cmd) { 06646 case CLI_INIT: 06647 e->command = "dialplan debug"; 06648 e->usage = 06649 "Usage: dialplan debug [context]\n" 06650 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 06651 return NULL; 06652 case CLI_GENERATE: 06653 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06654 } 06655 06656 memset(&counters, 0, sizeof(counters)); 06657 06658 if (a->argc != 2 && a->argc != 3) 06659 return CLI_SHOWUSAGE; 06660 06661 /* we obtain [exten@]context? if yes, split them ... */ 06662 /* note: we ignore the exten totally here .... */ 06663 if (a->argc == 3) { 06664 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06665 context = ast_strdupa(a->argv[2]); 06666 exten = strsep(&context, "@"); 06667 /* change empty strings to NULL */ 06668 if (ast_strlen_zero(exten)) 06669 exten = NULL; 06670 } else { /* no '@' char, only context given */ 06671 context = ast_strdupa(a->argv[2]); 06672 } 06673 if (ast_strlen_zero(context)) 06674 context = NULL; 06675 } 06676 /* else Show complete dial plan, context and exten are NULL */ 06677 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06678 06679 /* check for input failure and throw some error messages */ 06680 if (context && !counters.context_existence) { 06681 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06682 return CLI_FAILURE; 06683 } 06684 06685 06686 ast_cli(a->fd,"-= %d %s. =-\n", 06687 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06688 06689 /* everything ok */ 06690 return CLI_SUCCESS; 06691 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7008 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.
07009 { 07010 struct ast_channel *chan; 07011 const char *chan_name, *var_name, *var_value; 07012 07013 switch (cmd) { 07014 case CLI_INIT: 07015 e->command = "dialplan set chanvar"; 07016 e->usage = 07017 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 07018 " Set channel variable <varname> to <value>\n"; 07019 return NULL; 07020 case CLI_GENERATE: 07021 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07022 } 07023 07024 if (a->argc != e->args + 3) 07025 return CLI_SHOWUSAGE; 07026 07027 chan_name = a->argv[e->args]; 07028 var_name = a->argv[e->args + 1]; 07029 var_value = a->argv[e->args + 2]; 07030 07031 if (!(chan = ast_channel_get_by_name(chan_name))) { 07032 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 07033 return CLI_FAILURE; 07034 } 07035 07036 pbx_builtin_setvar_helper(chan, var_name, var_value); 07037 07038 chan = ast_channel_unref(chan); 07039 07040 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 07041 07042 return CLI_SUCCESS; 07043 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7045 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.
07046 { 07047 int oldval = 0; 07048 07049 switch (cmd) { 07050 case CLI_INIT: 07051 e->command = "dialplan set extenpatternmatchnew true"; 07052 e->usage = 07053 "Usage: dialplan set extenpatternmatchnew true|false\n" 07054 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07055 return NULL; 07056 case CLI_GENERATE: 07057 return NULL; 07058 } 07059 07060 if (a->argc != 4) 07061 return CLI_SHOWUSAGE; 07062 07063 oldval = pbx_set_extenpatternmatchnew(1); 07064 07065 if (oldval) 07066 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07067 else 07068 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07069 07070 return CLI_SUCCESS; 07071 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6986 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.
06987 { 06988 switch (cmd) { 06989 case CLI_INIT: 06990 e->command = "dialplan set global"; 06991 e->usage = 06992 "Usage: dialplan set global <name> <value>\n" 06993 " Set global dialplan variable <name> to <value>\n"; 06994 return NULL; 06995 case CLI_GENERATE: 06996 return NULL; 06997 } 06998 06999 if (a->argc != e->args + 2) 07000 return CLI_SHOWUSAGE; 07001 07002 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 07003 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 07004 07005 return CLI_SUCCESS; 07006 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6002 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_complete_applications(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_app::list, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.
06003 { 06004 struct ast_app *aa; 06005 int app, no_registered_app = 1; 06006 06007 switch (cmd) { 06008 case CLI_INIT: 06009 e->command = "core show application"; 06010 e->usage = 06011 "Usage: core show application <application> [<application> [<application> [...]]]\n" 06012 " Describes a particular application.\n"; 06013 return NULL; 06014 case CLI_GENERATE: 06015 /* 06016 * There is a possibility to show informations about more than one 06017 * application at one time. You can type 'show application Dial Echo' and 06018 * you will see informations about these two applications ... 06019 */ 06020 return ast_complete_applications(a->line, a->word, a->n); 06021 } 06022 06023 if (a->argc < 4) { 06024 return CLI_SHOWUSAGE; 06025 } 06026 06027 AST_RWLIST_RDLOCK(&apps); 06028 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06029 /* Check for each app that was supplied as an argument */ 06030 for (app = 3; app < a->argc; app++) { 06031 if (strcasecmp(aa->name, a->argv[app])) { 06032 continue; 06033 } 06034 06035 /* We found it! */ 06036 no_registered_app = 0; 06037 06038 print_app_docs(aa, a->fd); 06039 } 06040 } 06041 AST_RWLIST_UNLOCK(&apps); 06042 06043 /* we found at least one app? no? */ 06044 if (no_registered_app) { 06045 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 06046 return CLI_FAILURE; 06047 } 06048 06049 return CLI_SUCCESS; 06050 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6227 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_app::list, ast_cli_args::n, ast_app::name, ast_cli_args::pos, strcasestr(), ast_app::synopsis, ast_cli_entry::usage, and ast_cli_args::word.
06228 { 06229 struct ast_app *aa; 06230 int like = 0, describing = 0; 06231 int total_match = 0; /* Number of matches in like clause */ 06232 int total_apps = 0; /* Number of apps registered */ 06233 static const char * const choices[] = { "like", "describing", NULL }; 06234 06235 switch (cmd) { 06236 case CLI_INIT: 06237 e->command = "core show applications [like|describing]"; 06238 e->usage = 06239 "Usage: core show applications [{like|describing} <text>]\n" 06240 " List applications which are currently available.\n" 06241 " If 'like', <text> will be a substring of the app name\n" 06242 " If 'describing', <text> will be a substring of the description\n"; 06243 return NULL; 06244 case CLI_GENERATE: 06245 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 06246 } 06247 06248 AST_RWLIST_RDLOCK(&apps); 06249 06250 if (AST_RWLIST_EMPTY(&apps)) { 06251 ast_cli(a->fd, "There are no registered applications\n"); 06252 AST_RWLIST_UNLOCK(&apps); 06253 return CLI_SUCCESS; 06254 } 06255 06256 /* core list applications like <keyword> */ 06257 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 06258 like = 1; 06259 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 06260 describing = 1; 06261 } 06262 06263 /* core list applications describing <keyword1> [<keyword2>] [...] */ 06264 if ((!like) && (!describing)) { 06265 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 06266 } else { 06267 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 06268 } 06269 06270 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06271 int printapp = 0; 06272 total_apps++; 06273 if (like) { 06274 if (strcasestr(aa->name, a->argv[4])) { 06275 printapp = 1; 06276 total_match++; 06277 } 06278 } else if (describing) { 06279 if (aa->description) { 06280 /* Match all words on command line */ 06281 int i; 06282 printapp = 1; 06283 for (i = 4; i < a->argc; i++) { 06284 if (!strcasestr(aa->description, a->argv[i])) { 06285 printapp = 0; 06286 } else { 06287 total_match++; 06288 } 06289 } 06290 } 06291 } else { 06292 printapp = 1; 06293 } 06294 06295 if (printapp) { 06296 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 06297 } 06298 } 06299 if ((!like) && (!describing)) { 06300 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 06301 } else { 06302 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 06303 } 06304 06305 AST_RWLIST_UNLOCK(&apps); 06306 06307 return CLI_SUCCESS; 06308 }
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 6951 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.
06952 { 06953 struct ast_channel *chan = NULL; 06954 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 06955 06956 switch (cmd) { 06957 case CLI_INIT: 06958 e->command = "dialplan show chanvar"; 06959 e->usage = 06960 "Usage: dialplan show chanvar <channel>\n" 06961 " List current channel variables and their values\n"; 06962 return NULL; 06963 case CLI_GENERATE: 06964 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 06965 } 06966 06967 if (a->argc != e->args + 1) 06968 return CLI_SHOWUSAGE; 06969 06970 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 06971 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 06972 return CLI_FAILURE; 06973 } 06974 06975 pbx_builtin_serialize_variables(chan, &vars); 06976 06977 if (ast_str_strlen(vars)) { 06978 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 06979 } 06980 06981 chan = ast_channel_unref(chan); 06982 06983 return CLI_SUCCESS; 06984 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6571 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(), exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), strsep(), ast_cli_entry::usage, and ast_cli_args::word.
06572 { 06573 char *exten = NULL, *context = NULL; 06574 /* Variables used for different counters */ 06575 struct dialplan_counters counters; 06576 const char *incstack[AST_PBX_MAX_STACK]; 06577 06578 switch (cmd) { 06579 case CLI_INIT: 06580 e->command = "dialplan show"; 06581 e->usage = 06582 "Usage: dialplan show [[exten@]context]\n" 06583 " Show dialplan\n"; 06584 return NULL; 06585 case CLI_GENERATE: 06586 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06587 } 06588 06589 memset(&counters, 0, sizeof(counters)); 06590 06591 if (a->argc != 2 && a->argc != 3) 06592 return CLI_SHOWUSAGE; 06593 06594 /* we obtain [exten@]context? if yes, split them ... */ 06595 if (a->argc == 3) { 06596 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06597 context = ast_strdupa(a->argv[2]); 06598 exten = strsep(&context, "@"); 06599 /* change empty strings to NULL */ 06600 if (ast_strlen_zero(exten)) 06601 exten = NULL; 06602 } else { /* no '@' char, only context given */ 06603 context = ast_strdupa(a->argv[2]); 06604 } 06605 if (ast_strlen_zero(context)) 06606 context = NULL; 06607 } 06608 /* else Show complete dial plan, context and exten are NULL */ 06609 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06610 06611 /* check for input failure and throw some error messages */ 06612 if (context && !counters.context_existence) { 06613 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06614 return CLI_FAILURE; 06615 } 06616 06617 if (exten && !counters.extension_existence) { 06618 if (context) 06619 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 06620 exten, context); 06621 else 06622 ast_cli(a->fd, 06623 "There is no existence of '%s' extension in all contexts\n", 06624 exten); 06625 return CLI_FAILURE; 06626 } 06627 06628 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 06629 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 06630 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 06631 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06632 06633 /* everything ok */ 06634 return CLI_SUCCESS; 06635 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3378 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_custom_function::arguments, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), ast_free, ast_malloc, AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_custom_function::desc, ast_custom_function::docsrc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, S_OR, ast_custom_function::seealso, ast_custom_function::synopsis, synopsis, ast_custom_function::syntax, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
03379 { 03380 struct ast_custom_function *acf; 03381 /* Maximum number of characters added by terminal coloring is 22 */ 03382 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03383 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03384 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03385 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03386 char *ret = NULL; 03387 int which = 0; 03388 int wordlen; 03389 03390 switch (cmd) { 03391 case CLI_INIT: 03392 e->command = "core show function"; 03393 e->usage = 03394 "Usage: core show function <function>\n" 03395 " Describe a particular dialplan function.\n"; 03396 return NULL; 03397 case CLI_GENERATE: 03398 wordlen = strlen(a->word); 03399 /* case-insensitive for convenience in this 'complete' function */ 03400 AST_RWLIST_RDLOCK(&acf_root); 03401 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03402 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03403 ret = ast_strdup(acf->name); 03404 break; 03405 } 03406 } 03407 AST_RWLIST_UNLOCK(&acf_root); 03408 03409 return ret; 03410 } 03411 03412 if (a->argc < 4) { 03413 return CLI_SHOWUSAGE; 03414 } 03415 03416 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03417 ast_cli(a->fd, "No function by that name registered.\n"); 03418 return CLI_FAILURE; 03419 } 03420 03421 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03422 if (!(syntax = ast_malloc(syntax_size))) { 03423 ast_cli(a->fd, "Memory allocation failure!\n"); 03424 return CLI_FAILURE; 03425 } 03426 03427 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03428 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03429 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03430 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03431 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03432 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03433 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03434 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03435 #ifdef AST_XML_DOCS 03436 if (acf->docsrc == AST_XML_DOC) { 03437 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03438 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03439 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03440 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03441 } else 03442 #endif 03443 { 03444 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03445 synopsis = ast_malloc(synopsis_size); 03446 03447 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03448 description = ast_malloc(description_size); 03449 03450 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03451 arguments = ast_malloc(arguments_size); 03452 03453 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03454 seealso = ast_malloc(seealso_size); 03455 03456 /* check allocated memory. */ 03457 if (!synopsis || !description || !arguments || !seealso) { 03458 ast_free(synopsis); 03459 ast_free(description); 03460 ast_free(arguments); 03461 ast_free(seealso); 03462 ast_free(syntax); 03463 return CLI_FAILURE; 03464 } 03465 03466 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03467 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03468 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03469 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03470 } 03471 03472 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03473 infotitle, syntitle, synopsis, destitle, description, 03474 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03475 03476 ast_free(arguments); 03477 ast_free(synopsis); 03478 ast_free(description); 03479 ast_free(seealso); 03480 ast_free(syntax); 03481 03482 return CLI_SUCCESS; 03483 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3336 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, S_OR, ast_custom_function::synopsis, ast_custom_function::syntax, and ast_cli_entry::usage.
03337 { 03338 struct ast_custom_function *acf; 03339 int count_acf = 0; 03340 int like = 0; 03341 03342 switch (cmd) { 03343 case CLI_INIT: 03344 e->command = "core show functions [like]"; 03345 e->usage = 03346 "Usage: core show functions [like <text>]\n" 03347 " List builtin functions, optionally only those matching a given string\n"; 03348 return NULL; 03349 case CLI_GENERATE: 03350 return NULL; 03351 } 03352 03353 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03354 like = 1; 03355 } else if (a->argc != 3) { 03356 return CLI_SHOWUSAGE; 03357 } 03358 03359 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03360 03361 AST_RWLIST_RDLOCK(&acf_root); 03362 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03363 if (!like || strstr(acf->name, a->argv[4])) { 03364 count_acf++; 03365 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03366 S_OR(acf->name, ""), 03367 S_OR(acf->syntax, ""), 03368 S_OR(acf->synopsis, "")); 03369 } 03370 } 03371 AST_RWLIST_UNLOCK(&acf_root); 03372 03373 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03374 03375 return CLI_SUCCESS; 03376 }
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 6893 of file pbx.c.
References ast_cli(), AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_var_t::entries, ast_cli_args::fd, globals, globalslock, and ast_cli_entry::usage.
06894 { 06895 int i = 0; 06896 struct ast_var_t *newvariable; 06897 06898 switch (cmd) { 06899 case CLI_INIT: 06900 e->command = "dialplan show globals"; 06901 e->usage = 06902 "Usage: dialplan show globals\n" 06903 " List current global dialplan variables and their values\n"; 06904 return NULL; 06905 case CLI_GENERATE: 06906 return NULL; 06907 } 06908 06909 ast_rwlock_rdlock(&globalslock); 06910 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 06911 i++; 06912 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 06913 } 06914 ast_rwlock_unlock(&globalslock); 06915 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 06916 06917 return CLI_SUCCESS; 06918 }
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 6139 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.
06140 { 06141 struct ast_hint *hint; 06142 int watchers; 06143 int num = 0, extenlen; 06144 struct ao2_iterator i; 06145 06146 switch (cmd) { 06147 case CLI_INIT: 06148 e->command = "core show hint"; 06149 e->usage = 06150 "Usage: core show hint <exten>\n" 06151 " List registered hint\n"; 06152 return NULL; 06153 case CLI_GENERATE: 06154 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 06155 } 06156 06157 if (a->argc < 4) 06158 return CLI_SHOWUSAGE; 06159 06160 if (ao2_container_count(hints) == 0) { 06161 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06162 return CLI_SUCCESS; 06163 } 06164 06165 extenlen = strlen(a->argv[3]); 06166 i = ao2_iterator_init(hints, 0); 06167 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06168 ao2_lock(hint); 06169 if (!hint->exten) { 06170 /* The extension has already been destroyed */ 06171 ao2_unlock(hint); 06172 continue; 06173 } 06174 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 06175 watchers = ao2_container_count(hint->callbacks); 06176 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06177 ast_get_extension_name(hint->exten), 06178 ast_get_context_name(ast_get_extension_context(hint->exten)), 06179 ast_get_extension_app(hint->exten), 06180 ast_extension_state2str(hint->laststate), watchers); 06181 num++; 06182 } 06183 ao2_unlock(hint); 06184 } 06185 ao2_iterator_destroy(&i); 06186 if (!num) 06187 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 06188 else 06189 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 06190 return CLI_SUCCESS; 06191 }
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 6053 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.
06054 { 06055 struct ast_hint *hint; 06056 int num = 0; 06057 int watchers; 06058 struct ao2_iterator i; 06059 06060 switch (cmd) { 06061 case CLI_INIT: 06062 e->command = "core show hints"; 06063 e->usage = 06064 "Usage: core show hints\n" 06065 " List registered hints\n"; 06066 return NULL; 06067 case CLI_GENERATE: 06068 return NULL; 06069 } 06070 06071 if (ao2_container_count(hints) == 0) { 06072 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06073 return CLI_SUCCESS; 06074 } 06075 /* ... we have hints ... */ 06076 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 06077 06078 i = ao2_iterator_init(hints, 0); 06079 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06080 ao2_lock(hint); 06081 if (!hint->exten) { 06082 /* The extension has already been destroyed */ 06083 ao2_unlock(hint); 06084 continue; 06085 } 06086 watchers = ao2_container_count(hint->callbacks); 06087 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06088 ast_get_extension_name(hint->exten), 06089 ast_get_context_name(ast_get_extension_context(hint->exten)), 06090 ast_get_extension_app(hint->exten), 06091 ast_extension_state2str(hint->laststate), watchers); 06092 ao2_unlock(hint); 06093 num++; 06094 } 06095 ao2_iterator_destroy(&i); 06096 06097 ast_cli(a->fd, "----------------\n"); 06098 ast_cli(a->fd, "- %d hints registered\n", num); 06099 return CLI_SUCCESS; 06100 }
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 6195 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::list, ast_switch::name, and ast_cli_entry::usage.
06196 { 06197 struct ast_switch *sw; 06198 06199 switch (cmd) { 06200 case CLI_INIT: 06201 e->command = "core show switches"; 06202 e->usage = 06203 "Usage: core show switches\n" 06204 " List registered switches\n"; 06205 return NULL; 06206 case CLI_GENERATE: 06207 return NULL; 06208 } 06209 06210 AST_RWLIST_RDLOCK(&switches); 06211 06212 if (AST_RWLIST_EMPTY(&switches)) { 06213 AST_RWLIST_UNLOCK(&switches); 06214 ast_cli(a->fd, "There are no registered alternative switches\n"); 06215 return CLI_SUCCESS; 06216 } 06217 06218 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 06219 AST_RWLIST_TRAVERSE(&switches, sw, list) 06220 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 06221 06222 AST_RWLIST_UNLOCK(&switches); 06223 06224 return CLI_SUCCESS; 06225 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4400 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, context_merge_lock, statechange::dev, ast_hint::exten, hints, ast_hint::laststate, parse(), statecbs, and strsep().
04401 { 04402 struct ast_hint *hint; 04403 struct ast_str *hint_app; 04404 struct statechange *sc = datap; 04405 struct ao2_iterator i; 04406 struct ao2_iterator cb_iter; 04407 char context_name[AST_MAX_CONTEXT]; 04408 char exten_name[AST_MAX_EXTENSION]; 04409 04410 hint_app = ast_str_create(1024); 04411 if (!hint_app) { 04412 ast_free(sc); 04413 return -1; 04414 } 04415 04416 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ 04417 i = ao2_iterator_init(hints, 0); 04418 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 04419 struct ast_state_cb *state_cb; 04420 char *cur, *parse; 04421 int state; 04422 04423 ao2_lock(hint); 04424 if (!hint->exten) { 04425 /* The extension has already been destroyed */ 04426 ao2_unlock(hint); 04427 continue; 04428 } 04429 04430 /* Does this hint monitor the device that changed state? */ 04431 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04432 parse = ast_str_buffer(hint_app); 04433 while ((cur = strsep(&parse, "&"))) { 04434 if (!strcasecmp(cur, sc->dev)) { 04435 /* The hint monitors the device. */ 04436 break; 04437 } 04438 } 04439 if (!cur) { 04440 /* The hint does not monitor the device. */ 04441 ao2_unlock(hint); 04442 continue; 04443 } 04444 04445 /* 04446 * Save off strings in case the hint extension gets destroyed 04447 * while we are notifying the watchers. 04448 */ 04449 ast_copy_string(context_name, 04450 ast_get_context_name(ast_get_extension_context(hint->exten)), 04451 sizeof(context_name)); 04452 ast_copy_string(exten_name, ast_get_extension_name(hint->exten), 04453 sizeof(exten_name)); 04454 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04455 ao2_unlock(hint); 04456 04457 /* 04458 * Get device state for this hint. 04459 * 04460 * NOTE: We cannot hold any locks while determining the hint 04461 * device state or notifying the watchers without causing a 04462 * deadlock. (conlock, hints, and hint) 04463 */ 04464 state = ast_extension_state3(hint_app); 04465 if (state == hint->laststate) { 04466 continue; 04467 } 04468 04469 /* Device state changed since last check - notify the watchers. */ 04470 hint->laststate = state; /* record we saw the change */ 04471 04472 /* For general callbacks */ 04473 cb_iter = ao2_iterator_init(statecbs, 0); 04474 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04475 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04476 } 04477 ao2_iterator_destroy(&cb_iter); 04478 04479 /* For extension callbacks */ 04480 cb_iter = ao2_iterator_init(hint->callbacks, 0); 04481 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04482 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04483 } 04484 ao2_iterator_destroy(&cb_iter); 04485 } 04486 ao2_iterator_destroy(&i); 04487 ast_mutex_unlock(&context_merge_lock); 04488 04489 ast_free(hint_app); 04490 ast_free(sc); 04491 return 0; 04492 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7073 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.
07074 { 07075 int oldval = 0; 07076 07077 switch (cmd) { 07078 case CLI_INIT: 07079 e->command = "dialplan set extenpatternmatchnew false"; 07080 e->usage = 07081 "Usage: dialplan set extenpatternmatchnew true|false\n" 07082 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07083 return NULL; 07084 case CLI_GENERATE: 07085 return NULL; 07086 } 07087 07088 if (a->argc != 4) 07089 return CLI_SHOWUSAGE; 07090 07091 oldval = pbx_set_extenpatternmatchnew(0); 07092 07093 if (!oldval) 07094 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07095 else 07096 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07097 07098 return CLI_SUCCESS; 07099 }
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 1094 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01095 { 01096 const struct ast_exten *ac = ah_a; 01097 const struct ast_exten *bc = ah_b; 01098 return ac->priority != bc->priority; 01099 }
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1075 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01076 { 01077 const struct ast_exten *ac = ah_a; 01078 const struct ast_exten *bc = ah_b; 01079 int x = strcmp(ac->exten, bc->exten); 01080 if (x) { /* if exten names are diff, then return */ 01081 return x; 01082 } 01083 01084 /* but if they are the same, do the cidmatch values match? */ 01085 if (ac->matchcid && bc->matchcid) { 01086 return strcmp(ac->cidmatch,bc->cidmatch); 01087 } else if (!ac->matchcid && !bc->matchcid) { 01088 return 0; /* if there's no matchcid on either side, then this is a match */ 01089 } else { 01090 return 1; /* if there's matchcid on one but not the other, they are different */ 01091 } 01092 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1114 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01115 { 01116 const struct ast_exten *ac = obj; 01117 unsigned int x = ast_hashtab_hash_string(ac->exten); 01118 unsigned int y = 0; 01119 if (ac->matchcid) 01120 y = ast_hashtab_hash_string(ac->cidmatch); 01121 return x+y; 01122 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1130 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01131 { 01132 const struct ast_exten *ac = obj; 01133 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01134 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1124 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01125 { 01126 const struct ast_exten *ac = obj; 01127 return ast_hashtab_hash_int(ac->priority); 01128 }
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 10636 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().
10637 { 10638 const struct ast_hint *hint = obj; 10639 const char *exten_name; 10640 int res; 10641 10642 exten_name = ast_get_extension_name(hint->exten); 10643 if (ast_strlen_zero(exten_name)) { 10644 /* 10645 * If the exten or extension name isn't set, return 0 so that 10646 * the ao2_find() search will start in the first bucket. 10647 */ 10648 res = 0; 10649 } else { 10650 res = ast_str_case_hash(exten_name); 10651 } 10652 10653 return res; 10654 }
static int hint_id_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4655 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
04656 { 04657 const struct ast_state_cb *cb = obj; 04658 int *id = arg; 04659 04660 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 04661 }
static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 10236 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.
10238 { 10239 struct ast_data *data_hint; 10240 struct ast_hint *hint; 10241 int watchers; 10242 struct ao2_iterator i; 10243 10244 if (ao2_container_count(hints) == 0) { 10245 return 0; 10246 } 10247 10248 i = ao2_iterator_init(hints, 0); 10249 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 10250 watchers = ao2_container_count(hint->callbacks); 10251 data_hint = ast_data_add_node(data_root, "hint"); 10252 if (!data_hint) { 10253 continue; 10254 } 10255 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 10256 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 10257 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 10258 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 10259 ast_data_add_int(data_hint, "watchers", watchers); 10260 10261 if (!ast_data_search_match(search, data_hint)) { 10262 ast_data_remove_node(data_root, data_hint); 10263 } 10264 } 10265 ao2_iterator_destroy(&i); 10266 10267 return 0; 10268 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1474 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01475 { 01476 if (!i->hastime) 01477 return 1; 01478 01479 return ast_check_timing(&(i->timing)); 01480 }
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 5246 of file pbx.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, countcalls, getloadavg(), LOG_WARNING, maxcalllock, ast_channel::name, option_maxcalls, option_maxload, option_minmemfree, and totalcalls.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
05247 { 05248 int failed = 0; 05249 double curloadavg; 05250 #if defined(HAVE_SYSINFO) 05251 long curfreemem; 05252 struct sysinfo sys_info; 05253 #endif 05254 05255 ast_mutex_lock(&maxcalllock); 05256 if (option_maxcalls) { 05257 if (countcalls >= option_maxcalls) { 05258 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 05259 failed = -1; 05260 } 05261 } 05262 if (option_maxload) { 05263 getloadavg(&curloadavg, 1); 05264 if (curloadavg >= option_maxload) { 05265 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 05266 failed = -1; 05267 } 05268 } 05269 #if defined(HAVE_SYSINFO) 05270 if (option_minmemfree) { 05271 if (!sysinfo(&sys_info)) { 05272 /* make sure that the free system memory is above the configured low watermark 05273 * convert the amount of freeram from mem_units to MB */ 05274 curfreemem = sys_info.freeram * sys_info.mem_unit; 05275 curfreemem /= 1024 * 1024; 05276 if (curfreemem < option_minmemfree) { 05277 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 05278 failed = -1; 05279 } 05280 } 05281 } 05282 #endif 05283 05284 if (!failed) { 05285 countcalls++; 05286 totalcalls++; 05287 } 05288 ast_mutex_unlock(&maxcalllock); 05289 05290 return failed; 05291 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1891 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01892 { 01893 struct match_char *curr, *lcurr; 01894 01895 /* insert node into the tree at "current", so the alt_char list from current is 01896 sorted in increasing value as you go to the leaves */ 01897 if (!(*parent_ptr)) { 01898 *parent_ptr = node; 01899 return; 01900 } 01901 01902 if ((*parent_ptr)->specificity > node->specificity) { 01903 /* insert at head */ 01904 node->alt_char = (*parent_ptr); 01905 *parent_ptr = node; 01906 return; 01907 } 01908 01909 lcurr = *parent_ptr; 01910 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01911 if (curr->specificity > node->specificity) { 01912 node->alt_char = curr; 01913 lcurr->alt_char = node; 01914 break; 01915 } 01916 lcurr = curr; 01917 } 01918 01919 if (!curr) { 01920 lcurr->alt_char = node; 01921 } 01922 01923 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 10279 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_taskprocessor_get(), ast_verb, builtins, device_state_cb(), device_state_sub, device_state_tps, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), pbx_cli, pbx_data_providers, and testtime_function.
Referenced by main().
10280 { 10281 int x; 10282 10283 /* Initialize the PBX */ 10284 ast_verb(1, "Asterisk PBX Core Initializing\n"); 10285 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 10286 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 10287 } 10288 10289 ast_verb(1, "Registering builtin applications:\n"); 10290 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10291 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 10292 __ast_custom_function_register(&exception_function, NULL); 10293 __ast_custom_function_register(&testtime_function, NULL); 10294 10295 /* Register builtin applications */ 10296 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10297 ast_verb(1, "[%s]\n", builtins[x].name); 10298 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 10299 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 10300 return -1; 10301 } 10302 } 10303 10304 /* Register manager application */ 10305 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 10306 10307 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 10308 AST_EVENT_IE_END))) { 10309 return -1; 10310 } 10311 10312 return 0; 10313 }
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 7581 of file pbx.c.
Referenced by get_range().
07582 { 07583 int i; 07584 07585 if (names && *s > '9') { 07586 for (i = 0; names[i]; i++) { 07587 if (!strcasecmp(s, names[i])) { 07588 return i; 07589 } 07590 } 07591 } 07592 07593 /* Allow months and weekdays to be specified as numbers, as well */ 07594 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 07595 /* What the array offset would have been: "1" would be at offset 0 */ 07596 return i - 1; 07597 } 07598 return -1; /* error return */ 07599 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 6694 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan_helper().
06695 { 06696 astman_send_listack(s, m, "DialPlan list will follow", "start"); 06697 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 6840 of file pbx.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), exten, and manager_show_dialplan_helper().
Referenced by load_pbx().
06841 { 06842 const char *exten, *context; 06843 const char *id = astman_get_header(m, "ActionID"); 06844 char idtext[256]; 06845 06846 /* Variables used for different counters */ 06847 struct dialplan_counters counters; 06848 06849 if (!ast_strlen_zero(id)) 06850 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 06851 else 06852 idtext[0] = '\0'; 06853 06854 memset(&counters, 0, sizeof(counters)); 06855 06856 exten = astman_get_header(m, "Extension"); 06857 context = astman_get_header(m, "Context"); 06858 06859 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 06860 06861 if (context && !counters.context_existence) { 06862 char errorbuf[BUFSIZ]; 06863 06864 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 06865 astman_send_error(s, m, errorbuf); 06866 return 0; 06867 } 06868 if (exten && !counters.extension_existence) { 06869 char errorbuf[BUFSIZ]; 06870 06871 if (context) 06872 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 06873 else 06874 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 06875 astman_send_error(s, m, errorbuf); 06876 return 0; 06877 } 06878 06879 astman_append(s, "Event: ShowDialPlanComplete\r\n" 06880 "EventList: Complete\r\n" 06881 "ListItems: %d\r\n" 06882 "ListExtensions: %d\r\n" 06883 "ListPriorities: %d\r\n" 06884 "ListContexts: %d\r\n" 06885 "%s" 06886 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 06887 06888 /* everything ok */ 06889 return 0; 06890 }
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 6703 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().
06707 { 06708 struct ast_context *c; 06709 int res = 0, old_total_exten = dpc->total_exten; 06710 06711 if (ast_strlen_zero(exten)) 06712 exten = NULL; 06713 if (ast_strlen_zero(context)) 06714 context = NULL; 06715 06716 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 06717 06718 /* try to lock contexts */ 06719 if (ast_rdlock_contexts()) { 06720 astman_send_error(s, m, "Failed to lock contexts"); 06721 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 06722 return -1; 06723 } 06724 06725 c = NULL; /* walk all contexts ... */ 06726 while ( (c = ast_walk_contexts(c)) ) { 06727 struct ast_exten *e; 06728 struct ast_include *i; 06729 struct ast_ignorepat *ip; 06730 06731 if (context && strcmp(ast_get_context_name(c), context) != 0) 06732 continue; /* not the name we want */ 06733 06734 dpc->context_existence = 1; 06735 06736 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 06737 06738 if (ast_rdlock_context(c)) { /* failed to lock */ 06739 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 06740 continue; 06741 } 06742 06743 /* XXX note- an empty context is not printed */ 06744 e = NULL; /* walk extensions in context */ 06745 while ( (e = ast_walk_context_extensions(c, e)) ) { 06746 struct ast_exten *p; 06747 06748 /* looking for extension? is this our extension? */ 06749 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 06750 /* not the one we are looking for, continue */ 06751 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 06752 continue; 06753 } 06754 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 06755 06756 dpc->extension_existence = 1; 06757 06758 /* may we print context info? */ 06759 dpc->total_context++; 06760 dpc->total_exten++; 06761 06762 p = NULL; /* walk next extension peers */ 06763 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06764 int prio = ast_get_extension_priority(p); 06765 06766 dpc->total_prio++; 06767 if (!dpc->total_items++) 06768 manager_dpsendack(s, m); 06769 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06770 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 06771 06772 /* XXX maybe make this conditional, if p != e ? */ 06773 if (ast_get_extension_label(p)) 06774 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 06775 06776 if (prio == PRIORITY_HINT) { 06777 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 06778 } else { 06779 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)); 06780 } 06781 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 06782 } 06783 } 06784 06785 i = NULL; /* walk included and write info ... */ 06786 while ( (i = ast_walk_context_includes(c, i)) ) { 06787 if (exten) { 06788 /* Check all includes for the requested extension */ 06789 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 06790 } else { 06791 if (!dpc->total_items++) 06792 manager_dpsendack(s, m); 06793 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06794 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)); 06795 astman_append(s, "\r\n"); 06796 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 06797 } 06798 } 06799 06800 ip = NULL; /* walk ignore patterns and write info ... */ 06801 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06802 const char *ipname = ast_get_ignorepat_name(ip); 06803 char ignorepat[AST_MAX_EXTENSION]; 06804 06805 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06806 if (!exten || ast_extension_match(ignorepat, exten)) { 06807 if (!dpc->total_items++) 06808 manager_dpsendack(s, m); 06809 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06810 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 06811 astman_append(s, "\r\n"); 06812 } 06813 } 06814 if (!rinclude) { 06815 struct ast_sw *sw = NULL; 06816 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06817 if (!dpc->total_items++) 06818 manager_dpsendack(s, m); 06819 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06820 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)); 06821 astman_append(s, "\r\n"); 06822 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 06823 } 06824 } 06825 06826 ast_unlock_context(c); 06827 } 06828 ast_unlock_contexts(); 06829 06830 if (dpc->total_exten == old_total_exten) { 06831 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 06832 /* Nothing new under the sun */ 06833 return -1; 06834 } else { 06835 return res; 06836 } 06837 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2686 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02687 { 02688 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02689 failing to get a number should count as a match, otherwise not */ 02690 02691 if (ast_strlen_zero(callerid)) { 02692 return ast_strlen_zero(cidpattern) ? 1 : 0; 02693 } 02694 02695 return ast_extension_match(cidpattern, callerid); 02696 }
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 1715 of file pbx.c.
References match_char::alt_char, ast_debug, ast_hashtab_lookup(), ast_log(), match_char::deleted, E_FINDLABEL, E_MATCH, E_SPAWN, ast_exten::exten, match_char::exten, match_char::is_pattern, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, match_char::specificity, update_scoreboard(), and match_char::x.
Referenced by pbx_find_extension().
01716 { 01717 struct match_char *p; /* note minimal stack storage requirements */ 01718 struct ast_exten pattern = { .label = label }; 01719 #ifdef DEBUG_THIS 01720 if (tree) 01721 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01722 else 01723 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01724 #endif 01725 for (p = tree; p; p = p->alt_char) { 01726 if (p->is_pattern) { 01727 if (p->x[0] == 'N') { 01728 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01729 #define NEW_MATCHER_CHK_MATCH \ 01730 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01731 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01732 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01733 if (!p->deleted) { \ 01734 if (action == E_FINDLABEL) { \ 01735 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01736 ast_debug(4, "Found label in preferred extension\n"); \ 01737 return; \ 01738 } \ 01739 } else { \ 01740 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01741 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01742 } \ 01743 } \ 01744 } \ 01745 } 01746 01747 #define NEW_MATCHER_RECURSE \ 01748 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01749 || p->next_char->x[0] == '!')) { \ 01750 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01751 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01752 if (score->exten) { \ 01753 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01754 return; /* the first match is all we need */ \ 01755 } \ 01756 } else { \ 01757 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01758 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01759 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01760 "NULL"); \ 01761 return; /* the first match is all we need */ \ 01762 } \ 01763 } \ 01764 } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \ 01765 score->canmatch = 1; \ 01766 score->canmatch_exten = get_canmatch_exten(p); \ 01767 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01768 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01769 return; \ 01770 } \ 01771 } 01772 01773 NEW_MATCHER_CHK_MATCH; 01774 NEW_MATCHER_RECURSE; 01775 } 01776 } else if (p->x[0] == 'Z') { 01777 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01778 NEW_MATCHER_CHK_MATCH; 01779 NEW_MATCHER_RECURSE; 01780 } 01781 } else if (p->x[0] == 'X') { 01782 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01783 NEW_MATCHER_CHK_MATCH; 01784 NEW_MATCHER_RECURSE; 01785 } 01786 } else if (p->x[0] == '.' && p->x[1] == 0) { 01787 /* how many chars will the . match against? */ 01788 int i = 0; 01789 const char *str2 = str; 01790 while (*str2 && *str2 != '/') { 01791 str2++; 01792 i++; 01793 } 01794 if (p->exten && *str2 != '/') { 01795 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01796 if (score->exten) { 01797 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01798 return; /* the first match is all we need */ 01799 } 01800 } 01801 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01802 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01803 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01804 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01805 return; /* the first match is all we need */ 01806 } 01807 } 01808 } else if (p->x[0] == '!' && p->x[1] == 0) { 01809 /* how many chars will the . match against? */ 01810 int i = 1; 01811 const char *str2 = str; 01812 while (*str2 && *str2 != '/') { 01813 str2++; 01814 i++; 01815 } 01816 if (p->exten && *str2 != '/') { 01817 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01818 if (score->exten) { 01819 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01820 return; /* the first match is all we need */ 01821 } 01822 } 01823 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01824 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01825 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01826 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01827 return; /* the first match is all we need */ 01828 } 01829 } 01830 } else if (p->x[0] == '/' && p->x[1] == 0) { 01831 /* the pattern in the tree includes the cid match! */ 01832 if (p->next_char && callerid && *callerid) { 01833 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01834 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01835 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01836 return; /* the first match is all we need */ 01837 } 01838 } 01839 } else if (strchr(p->x, *str)) { 01840 ast_debug(4, "Nothing strange about this match\n"); 01841 NEW_MATCHER_CHK_MATCH; 01842 NEW_MATCHER_RECURSE; 01843 } 01844 } else if (strchr(p->x, *str)) { 01845 ast_debug(4, "Nothing strange about this match\n"); 01846 NEW_MATCHER_CHK_MATCH; 01847 NEW_MATCHER_RECURSE; 01848 } 01849 } 01850 ast_debug(4, "return at end of func\n"); 01851 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 2996 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
02997 { 02998 int parens = 0; 02999 03000 *offset = 0; 03001 *length = INT_MAX; 03002 *isfunc = 0; 03003 for (; *var; var++) { 03004 if (*var == '(') { 03005 (*isfunc)++; 03006 parens++; 03007 } else if (*var == ')') { 03008 parens--; 03009 } else if (*var == ':' && parens == 0) { 03010 *var++ = '\0'; 03011 sscanf(var, "%30d:%30d", offset, length); 03012 return 1; /* offset:length valid */ 03013 } 03014 } 03015 return 0; 03016 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10112 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), ast_var_t::entries, globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), and reload().
10113 { 10114 struct ast_var_t *vardata; 10115 10116 ast_rwlock_wrlock(&globalslock); 10117 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10118 ast_var_delete(vardata); 10119 ast_rwlock_unlock(&globalslock); 10120 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Return a pointer to the value of the corresponding channel variable.
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
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 9874 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, and globalslock.
Referenced by _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(), dahdi_r2_answer(), dahdi_r2_get_channel_category(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sig_pri_call(), sig_pri_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().
09875 { 09876 struct ast_var_t *variables; 09877 const char *ret = NULL; 09878 int i; 09879 struct varshead *places[2] = { NULL, &globals }; 09880 09881 if (!name) 09882 return NULL; 09883 09884 if (chan) { 09885 ast_channel_lock(chan); 09886 places[0] = &chan->varshead; 09887 } 09888 09889 for (i = 0; i < 2; i++) { 09890 if (!places[i]) 09891 continue; 09892 if (places[i] == &globals) 09893 ast_rwlock_rdlock(&globalslock); 09894 AST_LIST_TRAVERSE(places[i], variables, entries) { 09895 if (!strcmp(name, ast_var_name(variables))) { 09896 ret = ast_var_value(variables); 09897 break; 09898 } 09899 } 09900 if (places[i] == &globals) 09901 ast_rwlock_unlock(&globalslock); 09902 if (ret) 09903 break; 09904 } 09905 09906 if (chan) 09907 ast_channel_unlock(chan); 09908 09909 return ret; 09910 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10134 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
10135 { 10136 char *condition, *branch1, *branch2, *branch; 10137 char *stringp; 10138 10139 if (ast_strlen_zero(data)) { 10140 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 10141 return 0; 10142 } 10143 10144 stringp = ast_strdupa(data); 10145 condition = strsep(&stringp,"?"); 10146 branch1 = strsep(&stringp,":"); 10147 branch2 = strsep(&stringp,""); 10148 branch = pbx_checkcondition(condition) ? branch1 : branch2; 10149 10150 if (ast_strlen_zero(branch)) { 10151 ast_debug(1, "Not taking any branch\n"); 10152 return 0; 10153 } 10154 10155 return pbx_builtin_goto(chan, branch); 10156 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10070 of file pbx.c.
References 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(), strsep(), value, and VAR_BUF_SIZE.
10071 { 10072 char *name; 10073 char *value; 10074 char *channel; 10075 char tmp[VAR_BUF_SIZE]; 10076 static int deprecation_warning = 0; 10077 10078 if (ast_strlen_zero(data)) { 10079 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 10080 return 0; 10081 } 10082 tmp[0] = 0; 10083 if (!deprecation_warning) { 10084 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 10085 deprecation_warning = 1; 10086 } 10087 10088 value = ast_strdupa(data); 10089 name = strsep(&value,"="); 10090 channel = strsep(&value,","); 10091 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 10092 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 10093 if (chan2) { 10094 char *s = alloca(strlen(value) + 4); 10095 if (s) { 10096 sprintf(s, "${%s}", value); 10097 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 10098 } 10099 chan2 = ast_channel_unref(chan2); 10100 } 10101 pbx_builtin_setvar_helper(chan, name, tmp); 10102 } 10103 10104 return(0); 10105 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9400 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().
09401 { 09402 const char *options = data; 09403 int answer = 1; 09404 09405 /* Some channels can receive DTMF in unanswered state; some cannot */ 09406 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 09407 answer = 0; 09408 } 09409 09410 /* If the channel is hungup, stop waiting */ 09411 if (ast_check_hangup(chan)) { 09412 return -1; 09413 } else if (chan->_state != AST_STATE_UP && answer) { 09414 __ast_answer(chan, 0, 1); 09415 } 09416 09417 ast_indicate(chan, AST_CONTROL_INCOMPLETE); 09418 09419 return AST_PBX_INCOMPLETE; 09420 }
static int pbx_builtin_noop | ( | struct ast_channel * | , | |
const char * | ||||
) | [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 9912 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, and LOG_WARNING.
Referenced by acf_odbc_read(), acf_odbc_write(), and frame_set_var().
09913 { 09914 struct ast_var_t *newvariable; 09915 struct varshead *headp; 09916 09917 if (name[strlen(name)-1] == ')') { 09918 char *function = ast_strdupa(name); 09919 09920 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 09921 ast_func_write(chan, function, value); 09922 return; 09923 } 09924 09925 if (chan) { 09926 ast_channel_lock(chan); 09927 headp = &chan->varshead; 09928 } else { 09929 ast_rwlock_wrlock(&globalslock); 09930 headp = &globals; 09931 } 09932 09933 if (value) { 09934 if (headp == &globals) 09935 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09936 newvariable = ast_var_assign(name, value); 09937 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09938 } 09939 09940 if (chan) 09941 ast_channel_unlock(chan); 09942 else 09943 ast_rwlock_unlock(&globalslock); 09944 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason | |||
) |
Definition at line 3305 of file pbx.c.
References raise_exception().
03306 { 03307 /* Priority will become 1, next time through the AUTOLOOP */ 03308 return raise_exception(chan, reason, 0); 03309 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10195 of file pbx.c.
References ast_say_character_str(), and ast_channel::language.
10196 { 10197 int res = 0; 10198 10199 if (data) 10200 res = ast_say_character_str(chan, data, "", chan->language); 10201 return res; 10202 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10186 of file pbx.c.
References ast_say_digit_str(), and ast_channel::language.
10187 { 10188 int res = 0; 10189 10190 if (data) 10191 res = ast_say_digit_str(chan, data, "", chan->language); 10192 return res; 10193 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10158 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), ast_channel::language, LOG_WARNING, and strsep().
10159 { 10160 char tmp[256]; 10161 char *number = tmp; 10162 char *options; 10163 10164 if (ast_strlen_zero(data)) { 10165 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 10166 return -1; 10167 } 10168 ast_copy_string(tmp, data, sizeof(tmp)); 10169 strsep(&number, ","); 10170 options = strsep(&number, ","); 10171 if (options) { 10172 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 10173 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 10174 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 10175 return -1; 10176 } 10177 } 10178 10179 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 10180 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 10181 } 10182 10183 return 0; 10184 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10204 of file pbx.c.
References ast_say_phonetic_str(), and ast_channel::language.
10205 { 10206 int res = 0; 10207 10208 if (data) 10209 res = ast_say_phonetic_str(chan, data, "", chan->language); 10210 return res; 10211 }
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 9843 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
09844 { 09845 struct ast_var_t *variables; 09846 const char *var, *val; 09847 int total = 0; 09848 09849 if (!chan) 09850 return 0; 09851 09852 ast_str_reset(*buf); 09853 09854 ast_channel_lock(chan); 09855 09856 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 09857 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 09858 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 09859 ) { 09860 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 09861 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 09862 break; 09863 } else 09864 total++; 09865 } else 09866 break; 09867 } 09868 09869 ast_channel_unlock(chan); 09870 09871 return total; 09872 }
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 10004 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(), strsep(), and value.
Referenced by ast_compile_ael2(), and rpt_exec().
10005 { 10006 char *name, *value, *mydata; 10007 10008 if (ast_compat_app_set) { 10009 return pbx_builtin_setvar_multiple(chan, data); 10010 } 10011 10012 if (ast_strlen_zero(data)) { 10013 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10014 return 0; 10015 } 10016 10017 mydata = ast_strdupa(data); 10018 name = strsep(&mydata, "="); 10019 value = mydata; 10020 if (!value) { 10021 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10022 return 0; 10023 } 10024 10025 if (strchr(name, ' ')) { 10026 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10027 } 10028 10029 pbx_builtin_setvar_helper(chan, name, value); 10030 10031 return 0; 10032 }
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 9946 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, ast_channel::name, and ast_channel::uniqueid.
Referenced by __analog_ss_thread(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sig_pri_new_ast_channel(), 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().
09947 { 09948 struct ast_var_t *newvariable; 09949 struct varshead *headp; 09950 const char *nametail = name; 09951 09952 if (name[strlen(name) - 1] == ')') { 09953 char *function = ast_strdupa(name); 09954 09955 return ast_func_write(chan, function, value); 09956 } 09957 09958 if (chan) { 09959 ast_channel_lock(chan); 09960 headp = &chan->varshead; 09961 } else { 09962 ast_rwlock_wrlock(&globalslock); 09963 headp = &globals; 09964 } 09965 09966 /* For comparison purposes, we have to strip leading underscores */ 09967 if (*nametail == '_') { 09968 nametail++; 09969 if (*nametail == '_') 09970 nametail++; 09971 } 09972 09973 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 09974 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 09975 /* there is already such a variable, delete it */ 09976 AST_LIST_REMOVE_CURRENT(entries); 09977 ast_var_delete(newvariable); 09978 break; 09979 } 09980 } 09981 AST_LIST_TRAVERSE_SAFE_END; 09982 09983 if (value) { 09984 if (headp == &globals) 09985 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09986 newvariable = ast_var_assign(name, value); 09987 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09988 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 09989 "Channel: %s\r\n" 09990 "Variable: %s\r\n" 09991 "Value: %s\r\n" 09992 "Uniqueid: %s\r\n", 09993 chan ? chan->name : "none", name, value, 09994 chan ? chan->uniqueid : "none"); 09995 } 09996 09997 if (chan) 09998 ast_channel_unlock(chan); 09999 else 10000 ast_rwlock_unlock(&globalslock); 10001 return 0; 10002 }
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 10034 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, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), and set_queue_variables().
10035 { 10036 char *data; 10037 int x; 10038 AST_DECLARE_APP_ARGS(args, 10039 AST_APP_ARG(pair)[24]; 10040 ); 10041 AST_DECLARE_APP_ARGS(pair, 10042 AST_APP_ARG(name); 10043 AST_APP_ARG(value); 10044 ); 10045 10046 if (ast_strlen_zero(vdata)) { 10047 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10048 return 0; 10049 } 10050 10051 data = ast_strdupa(vdata); 10052 AST_STANDARD_APP_ARGS(args, data); 10053 10054 for (x = 0; x < args.argc; x++) { 10055 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10056 if (pair.argc == 2) { 10057 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10058 if (strchr(pair.name, ' ')) 10059 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); 10060 } else if (!chan) { 10061 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10062 } else { 10063 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10064 } 10065 } 10066 10067 return 0; 10068 }
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 10122 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().
10123 { 10124 int res; 10125 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10126 return 0; 10127 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10128 return res; 10129 } else { /* Strings are true */ 10130 return 1; 10131 } 10132 }
static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
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 |
0 | success | |
-1 | failure |
c | Channel |
app | Application |
data | Data for execution |
Definition at line 1402 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), app, 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, LOG_WARNING, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
01405 { 01406 int res; 01407 struct ast_module_user *u = NULL; 01408 const char *saved_c_appl; 01409 const char *saved_c_data; 01410 01411 if (c->cdr && !ast_check_hangup(c)) 01412 ast_cdr_setapp(c->cdr, app->name, data); 01413 01414 /* save channel values */ 01415 saved_c_appl= c->appl; 01416 saved_c_data= c->data; 01417 01418 c->appl = app->name; 01419 c->data = data; 01420 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01421 01422 if (app->module) 01423 u = __ast_module_user_add(app->module, c); 01424 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01425 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01426 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01427 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01428 app->name, (char *) data); 01429 } 01430 res = app->execute(c, S_OR(data, "")); 01431 if (app->module && u) 01432 __ast_module_user_remove(app->module, u); 01433 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01434 /* restore channel values */ 01435 c->appl = saved_c_appl; 01436 c->data = saved_c_data; 01437 return res; 01438 }
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 4185 of file pbx.c.
References ast_exten::app, app, ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_DIALPLAN, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, manager_event, ast_switch::name, ast_channel::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), ast_channel::uniqueid, and VERBOSITY_ATLEAST.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
04188 { 04189 struct ast_exten *e; 04190 struct ast_app *app; 04191 int res; 04192 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04193 char passdata[EXT_DATA_SIZE]; 04194 04195 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04196 04197 ast_rdlock_contexts(); 04198 if (found) 04199 *found = 0; 04200 04201 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04202 if (e) { 04203 if (found) 04204 *found = 1; 04205 if (matching_action) { 04206 ast_unlock_contexts(); 04207 return -1; /* success, we found it */ 04208 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04209 res = e->priority; 04210 ast_unlock_contexts(); 04211 return res; /* the priority we were looking for */ 04212 } else { /* spawn */ 04213 if (!e->cached_app) 04214 e->cached_app = pbx_findapp(e->app); 04215 app = e->cached_app; 04216 ast_unlock_contexts(); 04217 if (!app) { 04218 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04219 return -1; 04220 } 04221 if (c->context != context) 04222 ast_copy_string(c->context, context, sizeof(c->context)); 04223 if (c->exten != exten) 04224 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04225 c->priority = priority; 04226 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 04227 #ifdef CHANNEL_TRACE 04228 ast_channel_trace_update(c); 04229 #endif 04230 ast_debug(1, "Launching '%s'\n", app->name); 04231 if (VERBOSITY_ATLEAST(3)) { 04232 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04233 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04234 exten, context, priority, 04235 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04236 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04237 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04238 "in new stack"); 04239 } 04240 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04241 "Channel: %s\r\n" 04242 "Context: %s\r\n" 04243 "Extension: %s\r\n" 04244 "Priority: %d\r\n" 04245 "Application: %s\r\n" 04246 "AppData: %s\r\n" 04247 "Uniqueid: %s\r\n", 04248 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 04249 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04250 } 04251 } else if (q.swo) { /* not found here, but in another switch */ 04252 if (found) 04253 *found = 1; 04254 ast_unlock_contexts(); 04255 if (matching_action) { 04256 return -1; 04257 } else { 04258 if (!q.swo->exec) { 04259 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04260 res = -1; 04261 } 04262 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04263 } 04264 } else { /* not found anywhere, see what happened */ 04265 ast_unlock_contexts(); 04266 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04267 switch (q.status) { 04268 case STATUS_NO_CONTEXT: 04269 if (!matching_action && !combined_find_spawn) 04270 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04271 break; 04272 case STATUS_NO_EXTENSION: 04273 if (!matching_action && !combined_find_spawn) 04274 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04275 break; 04276 case STATUS_NO_PRIORITY: 04277 if (!matching_action && !combined_find_spawn) 04278 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04279 break; 04280 case STATUS_NO_LABEL: 04281 if (context && !combined_find_spawn) 04282 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04283 break; 04284 default: 04285 ast_debug(1, "Shouldn't happen!\n"); 04286 } 04287 04288 return (matching_action) ? 0 : -1; 04289 } 04290 }
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 | |||
) |
Definition at line 2698 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, strsep(), 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().
02702 { 02703 int x, res; 02704 struct ast_context *tmp = NULL; 02705 struct ast_exten *e = NULL, *eroot = NULL; 02706 struct ast_include *i = NULL; 02707 struct ast_sw *sw = NULL; 02708 struct ast_exten pattern = {NULL, }; 02709 struct scoreboard score = {0, }; 02710 struct ast_str *tmpdata = NULL; 02711 02712 pattern.label = label; 02713 pattern.priority = priority; 02714 #ifdef NEED_DEBUG_HERE 02715 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02716 #endif 02717 02718 /* Initialize status if appropriate */ 02719 if (q->stacklen == 0) { 02720 q->status = STATUS_NO_CONTEXT; 02721 q->swo = NULL; 02722 q->data = NULL; 02723 q->foundcontext = NULL; 02724 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02725 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02726 return NULL; 02727 } 02728 02729 /* Check first to see if we've already been checked */ 02730 for (x = 0; x < q->stacklen; x++) { 02731 if (!strcasecmp(q->incstack[x], context)) 02732 return NULL; 02733 } 02734 02735 if (bypass) { /* bypass means we only look there */ 02736 tmp = bypass; 02737 } else { /* look in contexts */ 02738 tmp = find_context(context); 02739 if (!tmp) { 02740 return NULL; 02741 } 02742 } 02743 02744 if (q->status < STATUS_NO_EXTENSION) 02745 q->status = STATUS_NO_EXTENSION; 02746 02747 /* Do a search for matching extension */ 02748 02749 eroot = NULL; 02750 score.total_specificity = 0; 02751 score.exten = 0; 02752 score.total_length = 0; 02753 if (!tmp->pattern_tree && tmp->root_table) { 02754 create_match_char_tree(tmp); 02755 #ifdef NEED_DEBUG 02756 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02757 log_match_char_tree(tmp->pattern_tree," "); 02758 #endif 02759 } 02760 #ifdef NEED_DEBUG 02761 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02762 log_match_char_tree(tmp->pattern_tree, ":: "); 02763 #endif 02764 02765 do { 02766 if (!ast_strlen_zero(overrideswitch)) { 02767 char *osw = ast_strdupa(overrideswitch), *name; 02768 struct ast_switch *asw; 02769 ast_switch_f *aswf = NULL; 02770 char *datap; 02771 int eval = 0; 02772 02773 name = strsep(&osw, "/"); 02774 asw = pbx_findswitch(name); 02775 02776 if (!asw) { 02777 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02778 break; 02779 } 02780 02781 if (osw && strchr(osw, '$')) { 02782 eval = 1; 02783 } 02784 02785 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02786 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02787 break; 02788 } else if (eval) { 02789 /* Substitute variables now */ 02790 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02791 datap = ast_str_buffer(tmpdata); 02792 } else { 02793 datap = osw; 02794 } 02795 02796 /* equivalent of extension_match_core() at the switch level */ 02797 if (action == E_CANMATCH) 02798 aswf = asw->canmatch; 02799 else if (action == E_MATCHMORE) 02800 aswf = asw->matchmore; 02801 else /* action == E_MATCH */ 02802 aswf = asw->exists; 02803 if (!aswf) { 02804 res = 0; 02805 } else { 02806 if (chan) { 02807 ast_autoservice_start(chan); 02808 } 02809 res = aswf(chan, context, exten, priority, callerid, datap); 02810 if (chan) { 02811 ast_autoservice_stop(chan); 02812 } 02813 } 02814 if (res) { /* Got a match */ 02815 q->swo = asw; 02816 q->data = datap; 02817 q->foundcontext = context; 02818 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02819 return NULL; 02820 } 02821 } 02822 } while (0); 02823 02824 if (extenpatternmatchnew) { 02825 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02826 eroot = score.exten; 02827 02828 if (score.last_char == '!' && action == E_MATCHMORE) { 02829 /* We match an extension ending in '!'. 02830 * The decision in this case is final and is NULL (no match). 02831 */ 02832 #ifdef NEED_DEBUG_HERE 02833 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02834 #endif 02835 return NULL; 02836 } 02837 02838 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02839 q->status = STATUS_SUCCESS; 02840 #ifdef NEED_DEBUG_HERE 02841 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02842 #endif 02843 return score.canmatch_exten; 02844 } 02845 02846 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02847 if (score.node) { 02848 struct ast_exten *z = trie_find_next_match(score.node); 02849 if (z) { 02850 #ifdef NEED_DEBUG_HERE 02851 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02852 #endif 02853 } else { 02854 if (score.canmatch_exten) { 02855 #ifdef NEED_DEBUG_HERE 02856 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02857 #endif 02858 return score.canmatch_exten; 02859 } else { 02860 #ifdef NEED_DEBUG_HERE 02861 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02862 #endif 02863 } 02864 } 02865 return z; 02866 } 02867 #ifdef NEED_DEBUG_HERE 02868 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02869 #endif 02870 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02871 } 02872 02873 if (eroot) { 02874 /* found entry, now look for the right priority */ 02875 if (q->status < STATUS_NO_PRIORITY) 02876 q->status = STATUS_NO_PRIORITY; 02877 e = NULL; 02878 if (action == E_FINDLABEL && label ) { 02879 if (q->status < STATUS_NO_LABEL) 02880 q->status = STATUS_NO_LABEL; 02881 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02882 } else { 02883 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02884 } 02885 if (e) { /* found a valid match */ 02886 q->status = STATUS_SUCCESS; 02887 q->foundcontext = context; 02888 #ifdef NEED_DEBUG_HERE 02889 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02890 #endif 02891 return e; 02892 } 02893 } 02894 } else { /* the old/current default exten pattern match algorithm */ 02895 02896 /* scan the list trying to match extension and CID */ 02897 eroot = NULL; 02898 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02899 int match = extension_match_core(eroot->exten, exten, action); 02900 /* 0 on fail, 1 on match, 2 on earlymatch */ 02901 02902 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02903 continue; /* keep trying */ 02904 if (match == 2 && action == E_MATCHMORE) { 02905 /* We match an extension ending in '!'. 02906 * The decision in this case is final and is NULL (no match). 02907 */ 02908 return NULL; 02909 } 02910 /* found entry, now look for the right priority */ 02911 if (q->status < STATUS_NO_PRIORITY) 02912 q->status = STATUS_NO_PRIORITY; 02913 e = NULL; 02914 if (action == E_FINDLABEL && label ) { 02915 if (q->status < STATUS_NO_LABEL) 02916 q->status = STATUS_NO_LABEL; 02917 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02918 } else { 02919 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02920 } 02921 if (e) { /* found a valid match */ 02922 q->status = STATUS_SUCCESS; 02923 q->foundcontext = context; 02924 return e; 02925 } 02926 } 02927 } 02928 02929 /* Check alternative switches */ 02930 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02931 struct ast_switch *asw = pbx_findswitch(sw->name); 02932 ast_switch_f *aswf = NULL; 02933 char *datap; 02934 02935 if (!asw) { 02936 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02937 continue; 02938 } 02939 02940 /* Substitute variables now */ 02941 if (sw->eval) { 02942 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02943 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02944 continue; 02945 } 02946 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02947 } 02948 02949 /* equivalent of extension_match_core() at the switch level */ 02950 if (action == E_CANMATCH) 02951 aswf = asw->canmatch; 02952 else if (action == E_MATCHMORE) 02953 aswf = asw->matchmore; 02954 else /* action == E_MATCH */ 02955 aswf = asw->exists; 02956 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02957 if (!aswf) 02958 res = 0; 02959 else { 02960 if (chan) 02961 ast_autoservice_start(chan); 02962 res = aswf(chan, context, exten, priority, callerid, datap); 02963 if (chan) 02964 ast_autoservice_stop(chan); 02965 } 02966 if (res) { /* Got a match */ 02967 q->swo = asw; 02968 q->data = datap; 02969 q->foundcontext = context; 02970 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02971 return NULL; 02972 } 02973 } 02974 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02975 /* Now try any includes we have in this context */ 02976 for (i = tmp->includes; i; i = i->next) { 02977 if (include_valid(i)) { 02978 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02979 #ifdef NEED_DEBUG_HERE 02980 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02981 #endif 02982 return e; 02983 } 02984 if (q->swo) 02985 return NULL; 02986 } 02987 } 02988 return NULL; 02989 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 1446 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_app::list, and ast_app::name.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
01447 { 01448 struct ast_app *tmp; 01449 01450 AST_RWLIST_RDLOCK(&apps); 01451 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01452 if (!strcasecmp(tmp->name, app)) 01453 break; 01454 } 01455 AST_RWLIST_UNLOCK(&apps); 01456 01457 return tmp; 01458 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 1460 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_switch::list, and ast_switch::name.
Referenced by pbx_find_extension().
01461 { 01462 struct ast_switch *asw; 01463 01464 AST_RWLIST_RDLOCK(&switches); 01465 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01466 if (!strcasecmp(asw->name, sw)) 01467 break; 01468 } 01469 AST_RWLIST_UNLOCK(&switches); 01470 01471 return asw; 01472 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 10552 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, strsep(), and ast_party_number::valid.
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
10553 { 10554 char *exten, *pri, *context; 10555 char *stringp; 10556 int ipri; 10557 int mode = 0; 10558 10559 if (ast_strlen_zero(goto_string)) { 10560 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 10561 return -1; 10562 } 10563 stringp = ast_strdupa(goto_string); 10564 context = strsep(&stringp, ","); /* guaranteed non-null */ 10565 exten = strsep(&stringp, ","); 10566 pri = strsep(&stringp, ","); 10567 if (!exten) { /* Only a priority in this one */ 10568 pri = context; 10569 exten = NULL; 10570 context = NULL; 10571 } else if (!pri) { /* Only an extension and priority in this one */ 10572 pri = exten; 10573 exten = context; 10574 context = NULL; 10575 } 10576 if (*pri == '+') { 10577 mode = 1; 10578 pri++; 10579 } else if (*pri == '-') { 10580 mode = -1; 10581 pri++; 10582 } 10583 if (sscanf(pri, "%30d", &ipri) != 1) { 10584 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 10585 exten ? exten : chan->exten, pri, 10586 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 10587 if (ipri < 1) { 10588 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 10589 return -1; 10590 } else 10591 mode = 0; 10592 } 10593 /* At this point we have a priority and maybe an extension and a context */ 10594 10595 if (mode) 10596 ipri = chan->priority + (ipri * mode); 10597 10598 if (async) 10599 ast_async_goto(chan, context, exten, ipri); 10600 else 10601 ast_explicit_goto(chan, context, exten, ipri); 10602 10603 return 0; 10604 10605 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 3119 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().
03120 { 03121 struct ast_str *str = ast_str_create(16); 03122 const char *cret; 03123 03124 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03125 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03126 *ret = cret ? workspace : NULL; 03127 ast_free(str); 03128 }
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 5397 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05398 { 05399 int oldval = autofallthrough; 05400 autofallthrough = newval; 05401 return oldval; 05402 }
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 5404 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05405 { 05406 int oldval = extenpatternmatchnew; 05407 extenpatternmatchnew = newval; 05408 return oldval; 05409 }
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 5411 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05412 { 05413 if (overrideswitch) { 05414 ast_free(overrideswitch); 05415 } 05416 if (!ast_strlen_zero(newval)) { 05417 overrideswitch = ast_strdup(newval); 05418 } else { 05419 overrideswitch = NULL; 05420 } 05421 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 4148 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
04149 { 04150 const char *tmp; 04151 04152 /* Nothing more to do */ 04153 if (!e->data) { 04154 *passdata = '\0'; 04155 return; 04156 } 04157 04158 /* No variables or expressions in e->data, so why scan it? */ 04159 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 04160 ast_copy_string(passdata, e->data, datalen); 04161 return; 04162 } 04163 04164 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 04165 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4136 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_find_extension(), pbx_load_config(), pbx_substitute_variables(), rotate_file(), rpt_do_lstats(), rpt_exec(), substituted(), and write_cdr().
04137 { 04138 size_t used; 04139 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04140 }
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 3940 of file pbx.c.
References 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().
03941 { 03942 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03943 char *cp4 = NULL; 03944 const char *tmp, *whereweare, *orig_cp2 = cp2; 03945 int length, offset, offset2, isfunction; 03946 char *workspace = NULL; 03947 char *ltmp = NULL, *var = NULL; 03948 char *nextvar, *nextexp, *nextthing; 03949 char *vars, *vare; 03950 int pos, brackets, needsub, len; 03951 03952 *cp2 = 0; /* just in case nothing ends up there */ 03953 whereweare=tmp=cp1; 03954 while (!ast_strlen_zero(whereweare) && count) { 03955 /* Assume we're copying the whole remaining string */ 03956 pos = strlen(whereweare); 03957 nextvar = NULL; 03958 nextexp = NULL; 03959 nextthing = strchr(whereweare, '$'); 03960 if (nextthing) { 03961 switch (nextthing[1]) { 03962 case '{': 03963 nextvar = nextthing; 03964 pos = nextvar - whereweare; 03965 break; 03966 case '[': 03967 nextexp = nextthing; 03968 pos = nextexp - whereweare; 03969 break; 03970 default: 03971 pos = 1; 03972 } 03973 } 03974 03975 if (pos) { 03976 /* Can't copy more than 'count' bytes */ 03977 if (pos > count) 03978 pos = count; 03979 03980 /* Copy that many bytes */ 03981 memcpy(cp2, whereweare, pos); 03982 03983 count -= pos; 03984 cp2 += pos; 03985 whereweare += pos; 03986 *cp2 = 0; 03987 } 03988 03989 if (nextvar) { 03990 /* We have a variable. Find the start and end, and determine 03991 if we are going to have to recursively call ourselves on the 03992 contents */ 03993 vars = vare = nextvar + 2; 03994 brackets = 1; 03995 needsub = 0; 03996 03997 /* Find the end of it */ 03998 while (brackets && *vare) { 03999 if ((vare[0] == '$') && (vare[1] == '{')) { 04000 needsub++; 04001 } else if (vare[0] == '{') { 04002 brackets++; 04003 } else if (vare[0] == '}') { 04004 brackets--; 04005 } else if ((vare[0] == '$') && (vare[1] == '[')) 04006 needsub++; 04007 vare++; 04008 } 04009 if (brackets) 04010 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04011 len = vare - vars - 1; 04012 04013 /* Skip totally over variable string */ 04014 whereweare += (len + 3); 04015 04016 if (!var) 04017 var = alloca(VAR_BUF_SIZE); 04018 04019 /* Store variable name (and truncate) */ 04020 ast_copy_string(var, vars, len + 1); 04021 04022 /* Substitute if necessary */ 04023 if (needsub) { 04024 size_t used; 04025 if (!ltmp) 04026 ltmp = alloca(VAR_BUF_SIZE); 04027 04028 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04029 vars = ltmp; 04030 } else { 04031 vars = var; 04032 } 04033 04034 if (!workspace) 04035 workspace = alloca(VAR_BUF_SIZE); 04036 04037 workspace[0] = '\0'; 04038 04039 parse_variable_name(vars, &offset, &offset2, &isfunction); 04040 if (isfunction) { 04041 /* Evaluate function */ 04042 if (c || !headp) 04043 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04044 else { 04045 struct varshead old; 04046 struct ast_channel *c = ast_dummy_channel_alloc(); 04047 if (c) { 04048 memcpy(&old, &c->varshead, sizeof(old)); 04049 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04050 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04051 /* Don't deallocate the varshead that was passed in */ 04052 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04053 c = ast_channel_unref(c); 04054 } else { 04055 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04056 } 04057 } 04058 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04059 } else { 04060 /* Retrieve variable value */ 04061 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04062 } 04063 if (cp4) { 04064 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04065 04066 length = strlen(cp4); 04067 if (length > count) 04068 length = count; 04069 memcpy(cp2, cp4, length); 04070 count -= length; 04071 cp2 += length; 04072 *cp2 = 0; 04073 } 04074 } else if (nextexp) { 04075 /* We have an expression. Find the start and end, and determine 04076 if we are going to have to recursively call ourselves on the 04077 contents */ 04078 vars = vare = nextexp + 2; 04079 brackets = 1; 04080 needsub = 0; 04081 04082 /* Find the end of it */ 04083 while (brackets && *vare) { 04084 if ((vare[0] == '$') && (vare[1] == '[')) { 04085 needsub++; 04086 brackets++; 04087 vare++; 04088 } else if (vare[0] == '[') { 04089 brackets++; 04090 } else if (vare[0] == ']') { 04091 brackets--; 04092 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04093 needsub++; 04094 vare++; 04095 } 04096 vare++; 04097 } 04098 if (brackets) 04099 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04100 len = vare - vars - 1; 04101 04102 /* Skip totally over expression */ 04103 whereweare += (len + 3); 04104 04105 if (!var) 04106 var = alloca(VAR_BUF_SIZE); 04107 04108 /* Store variable name (and truncate) */ 04109 ast_copy_string(var, vars, len + 1); 04110 04111 /* Substitute if necessary */ 04112 if (needsub) { 04113 size_t used; 04114 if (!ltmp) 04115 ltmp = alloca(VAR_BUF_SIZE); 04116 04117 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04118 vars = ltmp; 04119 } else { 04120 vars = var; 04121 } 04122 04123 length = ast_expr(vars, cp2, count, c); 04124 04125 if (length) { 04126 ast_debug(1, "Expression result is '%s'\n", cp2); 04127 count -= length; 04128 cp2 += length; 04129 *cp2 = 0; 04130 } 04131 } 04132 } 04133 *used = cp2 - orig_cp2; 04134 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4142 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by dundi_lookup_local(), and loopback_subst().
04143 { 04144 size_t used; 04145 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04146 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5315 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05316 { 05317 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05318 answer this channel and get it going. 05319 */ 05320 /* NOTE: 05321 The launcher of this function _MUST_ increment 'countcalls' 05322 before invoking the function; it will be decremented when the 05323 PBX has finished running on the channel 05324 */ 05325 struct ast_channel *c = data; 05326 05327 __ast_pbx_run(c, NULL); 05328 decrease_call_count(); 05329 05330 pthread_exit(NULL); 05331 05332 return NULL; 05333 }
static void print_app_docs | ( | struct ast_app * | aa, | |
int | fd | |||
) | [static] |
Definition at line 5927 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_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().
05928 { 05929 /* Maximum number of characters added by terminal coloring is 22 */ 05930 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 05931 char seealsotitle[40]; 05932 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 05933 char *seealso = NULL; 05934 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 05935 05936 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 05937 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 05938 05939 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 05940 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 05941 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 05942 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 05943 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 05944 05945 #ifdef AST_XML_DOCS 05946 if (aa->docsrc == AST_XML_DOC) { 05947 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 05948 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 05949 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 05950 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 05951 05952 if (!synopsis || !description || !arguments || !seealso) { 05953 goto return_cleanup; 05954 } 05955 } else 05956 #endif 05957 { 05958 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05959 synopsis = ast_malloc(synopsis_size); 05960 05961 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05962 description = ast_malloc(description_size); 05963 05964 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05965 arguments = ast_malloc(arguments_size); 05966 05967 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05968 seealso = ast_malloc(seealso_size); 05969 05970 if (!synopsis || !description || !arguments || !seealso) { 05971 goto return_cleanup; 05972 } 05973 05974 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 05975 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 05976 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 05977 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 05978 } 05979 05980 /* Handle the syntax the same for both XML and raw docs */ 05981 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05982 if (!(syntax = ast_malloc(syntax_size))) { 05983 goto return_cleanup; 05984 } 05985 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 05986 05987 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 05988 infotitle, syntitle, synopsis, destitle, description, 05989 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 05990 05991 return_cleanup: 05992 ast_free(description); 05993 ast_free(arguments); 05994 ast_free(synopsis); 05995 ast_free(seealso); 05996 ast_free(syntax); 05997 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 6353 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().
06354 { 06355 int prio = ast_get_extension_priority(e); 06356 if (prio == PRIORITY_HINT) { 06357 snprintf(buf, buflen, "hint: %s", 06358 ast_get_extension_app(e)); 06359 } else { 06360 snprintf(buf, buflen, "%d. %s(%s)", 06361 prio, ast_get_extension_app(e), 06362 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06363 } 06364 }
static int raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason, | |||
int | priority | |||
) | [static] |
Definition at line 3279 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 pbx_builtin_raise_exception(), and pbx_builtin_waitexten().
03280 { 03281 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03282 struct pbx_exception *exception = NULL; 03283 03284 if (!ds) { 03285 ds = ast_datastore_alloc(&exception_store_info, NULL); 03286 if (!ds) 03287 return -1; 03288 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03289 ast_datastore_free(ds); 03290 return -1; 03291 } 03292 ds->data = exception; 03293 ast_channel_datastore_add(chan, ds); 03294 } else 03295 exception = ds->data; 03296 03297 ast_string_field_set(exception, reason, reason); 03298 ast_string_field_set(exception, context, chan->context); 03299 ast_string_field_set(exception, exten, chan->exten); 03300 exception->priority = chan->priority; 03301 set_ext_pri(chan, "e", priority); 03302 return 0; 03303 }
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 4891 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().
04892 { 04893 ast_channel_lock(c); 04894 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04895 c->priority = pri; 04896 ast_channel_unlock(c); 04897 }
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 6518 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().
06519 { 06520 struct ast_context *c = NULL; 06521 int res = 0, old_total_exten = dpc->total_exten; 06522 06523 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 06524 06525 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 06526 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 06527 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 06528 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 06529 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 06530 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 06531 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 06532 ast_rdlock_contexts(); 06533 06534 /* walk all contexts ... */ 06535 while ( (c = ast_walk_contexts(c)) ) { 06536 int context_info_printed = 0; 06537 06538 if (context && strcmp(ast_get_context_name(c), context)) 06539 continue; /* skip this one, name doesn't match */ 06540 06541 dpc->context_existence = 1; 06542 06543 if (!c->pattern_tree) 06544 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 06545 06546 ast_rdlock_context(c); 06547 06548 dpc->total_context++; 06549 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06550 ast_get_context_name(c), ast_get_context_registrar(c)); 06551 context_info_printed = 1; 06552 06553 if (c->pattern_tree) 06554 { 06555 cli_match_char_tree(c->pattern_tree, " ", fd); 06556 } else { 06557 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 06558 } 06559 06560 ast_unlock_context(c); 06561 06562 /* if we print something in context, make an empty line */ 06563 if (context_info_printed) 06564 ast_cli(fd, "\n"); 06565 } 06566 ast_unlock_contexts(); 06567 06568 return (dpc->total_exten == old_total_exten) ? -1 : res; 06569 }
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 6367 of file pbx.c.
References ast_cli(), ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), buf2, ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
06368 { 06369 struct ast_context *c = NULL; 06370 int res = 0, old_total_exten = dpc->total_exten; 06371 06372 ast_rdlock_contexts(); 06373 06374 /* walk all contexts ... */ 06375 while ( (c = ast_walk_contexts(c)) ) { 06376 struct ast_exten *e; 06377 struct ast_include *i; 06378 struct ast_ignorepat *ip; 06379 char buf[256], buf2[256]; 06380 int context_info_printed = 0; 06381 06382 if (context && strcmp(ast_get_context_name(c), context)) 06383 continue; /* skip this one, name doesn't match */ 06384 06385 dpc->context_existence = 1; 06386 06387 ast_rdlock_context(c); 06388 06389 /* are we looking for exten too? if yes, we print context 06390 * only if we find our extension. 06391 * Otherwise print context even if empty ? 06392 * XXX i am not sure how the rinclude is handled. 06393 * I think it ought to go inside. 06394 */ 06395 if (!exten) { 06396 dpc->total_context++; 06397 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06398 ast_get_context_name(c), ast_get_context_registrar(c)); 06399 context_info_printed = 1; 06400 } 06401 06402 /* walk extensions ... */ 06403 e = NULL; 06404 while ( (e = ast_walk_context_extensions(c, e)) ) { 06405 struct ast_exten *p; 06406 06407 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06408 continue; /* skip, extension match failed */ 06409 06410 dpc->extension_existence = 1; 06411 06412 /* may we print context info? */ 06413 if (!context_info_printed) { 06414 dpc->total_context++; 06415 if (rinclude) { /* TODO Print more info about rinclude */ 06416 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06417 ast_get_context_name(c), ast_get_context_registrar(c)); 06418 } else { 06419 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06420 ast_get_context_name(c), ast_get_context_registrar(c)); 06421 } 06422 context_info_printed = 1; 06423 } 06424 dpc->total_prio++; 06425 06426 /* write extension name and first peer */ 06427 if (e->matchcid) 06428 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06429 else 06430 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06431 06432 print_ext(e, buf2, sizeof(buf2)); 06433 06434 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06435 ast_get_extension_registrar(e)); 06436 06437 dpc->total_exten++; 06438 /* walk next extension peers */ 06439 p = e; /* skip the first one, we already got it */ 06440 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06441 const char *el = ast_get_extension_label(p); 06442 dpc->total_prio++; 06443 if (el) 06444 snprintf(buf, sizeof(buf), " [%s]", el); 06445 else 06446 buf[0] = '\0'; 06447 print_ext(p, buf2, sizeof(buf2)); 06448 06449 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 06450 ast_get_extension_registrar(p)); 06451 } 06452 } 06453 06454 /* walk included and write info ... */ 06455 i = NULL; 06456 while ( (i = ast_walk_context_includes(c, i)) ) { 06457 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 06458 if (exten) { 06459 /* Check all includes for the requested extension */ 06460 if (includecount >= AST_PBX_MAX_STACK) { 06461 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 06462 } else { 06463 int dupe = 0; 06464 int x; 06465 for (x = 0; x < includecount; x++) { 06466 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 06467 dupe++; 06468 break; 06469 } 06470 } 06471 if (!dupe) { 06472 includes[includecount] = ast_get_include_name(i); 06473 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 06474 } else { 06475 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 06476 } 06477 } 06478 } else { 06479 ast_cli(fd, " Include => %-45s [%s]\n", 06480 buf, ast_get_include_registrar(i)); 06481 } 06482 } 06483 06484 /* walk ignore patterns and write info ... */ 06485 ip = NULL; 06486 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06487 const char *ipname = ast_get_ignorepat_name(ip); 06488 char ignorepat[AST_MAX_EXTENSION]; 06489 snprintf(buf, sizeof(buf), "'%s'", ipname); 06490 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06491 if (!exten || ast_extension_match(ignorepat, exten)) { 06492 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 06493 buf, ast_get_ignorepat_registrar(ip)); 06494 } 06495 } 06496 if (!rinclude) { 06497 struct ast_sw *sw = NULL; 06498 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06499 snprintf(buf, sizeof(buf), "'%s/%s'", 06500 ast_get_switch_name(sw), 06501 ast_get_switch_data(sw)); 06502 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 06503 buf, ast_get_switch_registrar(sw)); 06504 } 06505 } 06506 06507 ast_unlock_context(c); 06508 06509 /* if we print something in context, make an empty line */ 06510 if (context_info_printed) 06511 ast_cli(fd, "\n"); 06512 } 06513 ast_unlock_contexts(); 06514 06515 return (dpc->total_exten == old_total_exten) ? -1 : res; 06516 }
static int statecbs_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 10664 of file pbx.c.
References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
10665 { 10666 const struct ast_state_cb *state_cb = obj; 10667 ast_state_cb_type change_cb = arg; 10668 10669 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; 10670 }
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 3029 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
03030 { 03031 char *ret = workspace; 03032 int lr; /* length of the input string after the copy */ 03033 03034 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 03035 03036 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 03037 03038 /* Quick check if no need to do anything */ 03039 if (offset == 0 && length >= lr) /* take the whole string */ 03040 return ret; 03041 03042 if (offset < 0) { /* translate negative offset into positive ones */ 03043 offset = lr + offset; 03044 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03045 offset = 0; 03046 } 03047 03048 /* too large offset result in empty string so we know what to return */ 03049 if (offset >= lr) 03050 return ret + lr; /* the final '\0' */ 03051 03052 ret += offset; /* move to the start position */ 03053 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 03054 ret[length] = '\0'; 03055 else if (length < 0) { 03056 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 03057 ret[lr + length - offset] = '\0'; 03058 else 03059 ret[0] = '\0'; 03060 } 03061 03062 return ret; 03063 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static] |
Definition at line 1656 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().
01657 { 01658 struct match_char *m3; 01659 struct match_char *m4; 01660 struct ast_exten *e3; 01661 01662 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01663 return node->exten; 01664 } 01665 01666 if (node && node->x[0] == '!' && !node->x[1]) { 01667 return node->exten; 01668 } 01669 01670 if (!node || !node->next_char) { 01671 return NULL; 01672 } 01673 01674 m3 = node->next_char; 01675 01676 if (m3->exten) { 01677 return m3->exten; 01678 } 01679 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01680 if (m4->exten) { 01681 return m4->exten; 01682 } 01683 } 01684 for (m4 = m3; m4; m4 = m4->alt_char) { 01685 e3 = trie_find_next_match(m3); 01686 if (e3) { 01687 return e3; 01688 } 01689 } 01690 01691 return NULL; 01692 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 7125 of file pbx.c.
References app, ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), and context.
Referenced by ast_unregister_application().
07126 { 07127 struct ast_context *context = NULL; 07128 struct ast_exten *eroot = NULL, *e = NULL; 07129 07130 ast_rdlock_contexts(); 07131 while ((context = ast_walk_contexts(context))) { 07132 while ((eroot = ast_walk_context_extensions(context, eroot))) { 07133 while ((e = ast_walk_extension_priorities(eroot, e))) { 07134 if (e->cached_app == app) 07135 e->cached_app = NULL; 07136 } 07137 } 07138 } 07139 ast_unlock_contexts(); 07140 07141 return; 07142 }
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 1561 of file pbx.c.
References ast_log(), exten, scoreboard::exten, scoreboard::last_char, LOG_NOTICE, scoreboard::node, scoreboard::total_length, and scoreboard::total_specificity.
Referenced by new_find_extension().
01562 { 01563 /* if this extension is marked as deleted, then skip this -- if it never shows 01564 on the scoreboard, it will never be found, nor will halt the traversal. */ 01565 if (deleted) 01566 return; 01567 board->total_specificity = spec; 01568 board->total_length = length; 01569 board->exten = exten; 01570 board->last_char = last; 01571 board->node = node; 01572 #ifdef NEED_DEBUG_HERE 01573 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01574 #endif 01575 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
const void * | data | |||
) | [static] |
Definition at line 9286 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().
09287 { 09288 int res; 09289 struct ast_frame *f; 09290 double waitsec; 09291 int waittime; 09292 09293 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 09294 waitsec = -1; 09295 if (waitsec > -1) { 09296 waittime = waitsec * 1000.0; 09297 ast_safe_sleep(chan, waittime); 09298 } else do { 09299 res = ast_waitfor(chan, -1); 09300 if (res < 0) 09301 return; 09302 f = ast_read(chan); 09303 if (f) 09304 ast_frfree(f); 09305 } while(f); 09306 }
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[] [static] |
ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock for the ast_context list.
Definition at line 1199 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 1204 of file pbx.c.
Referenced by ast_merge_contexts_and_delete(), and handle_statechange().
struct ast_context* contexts [static] |
Definition at line 1190 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 1191 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), find_context(), and find_context_locked().
int countcalls [static] |
Definition at line 1148 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
const char* const days[] [static] |
struct ast_event_sub* device_state_sub [static] |
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
Initial value:
{ .name = "EXCEPTION", .read = acf_exception_read, }
Definition at line 3331 of file pbx.c.
Referenced by load_pbx().
struct ast_datastore_info exception_store_info [static] |
Initial value:
{ .type = "EXCEPTION", .destroy = exception_store_free, }
Definition at line 3263 of file pbx.c.
Referenced by acf_exception_read(), and raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1141 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] |
ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [static] |
Definition at line 1137 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 1219 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(), and hints_data_provider_get().
struct ast_data_handler hints_data_provider [static] |
Initial value:
{ .version = AST_DATA_HANDLER_VERSION, .get = hints_data_provider_get }
ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 1147 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
const char* const months[] [static] |
char* overrideswitch = NULL [static] |
Definition at line 1142 of file pbx.c.
Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().
struct ast_cli_entry pbx_cli[] [static] |
struct ast_data_entry pbx_data_providers[] [static] |
Initial value:
{ AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider), }
Definition at line 10275 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] |
struct ao2_container* statecbs [static] |
Definition at line 1221 of file pbx.c.
Referenced by ast_extension_state_add_destroy(), ast_extension_state_del(), ast_pbx_init(), and handle_statechange().
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] |
Initial value:
{ .name = "TESTTIME", .write = testtime_write, }
Definition at line 9518 of file pbx.c.
Referenced by load_pbx().
int totalcalls [static] |
Definition at line 1149 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] |