#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 786 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 791 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_DIALTONE (1 << 1) |
#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 9144 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().
09145 { 09146 struct ast_context *tmp, *tmpl=NULL; 09147 struct ast_exten *exten_item, *prio_item; 09148 09149 for (tmp = list; tmp; ) { 09150 struct ast_context *next = NULL; /* next starting point */ 09151 /* The following code used to skip forward to the next 09152 context with matching registrar, but this didn't 09153 make sense; individual priorities registrar'd to 09154 the matching registrar could occur in any context! */ 09155 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 09156 if (con) { 09157 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 09158 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 09159 if ( !strcasecmp(tmp->name, con->name) ) { 09160 break; /* found it */ 09161 } 09162 } 09163 } 09164 09165 if (!tmp) /* not found, we are done */ 09166 break; 09167 ast_wrlock_context(tmp); 09168 09169 if (registrar) { 09170 /* then search thru and remove any extens that match registrar. */ 09171 struct ast_hashtab_iter *exten_iter; 09172 struct ast_hashtab_iter *prio_iter; 09173 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 09174 struct ast_include *i, *pi = NULL, *ni = NULL; 09175 struct ast_sw *sw = NULL; 09176 09177 /* remove any ignorepats whose registrar matches */ 09178 for (ip = tmp->ignorepats; ip; ip = ipn) { 09179 ipn = ip->next; 09180 if (!strcmp(ip->registrar, registrar)) { 09181 if (ipl) { 09182 ipl->next = ip->next; 09183 ast_free(ip); 09184 continue; /* don't change ipl */ 09185 } else { 09186 tmp->ignorepats = ip->next; 09187 ast_free(ip); 09188 continue; /* don't change ipl */ 09189 } 09190 } 09191 ipl = ip; 09192 } 09193 /* remove any includes whose registrar matches */ 09194 for (i = tmp->includes; i; i = ni) { 09195 ni = i->next; 09196 if (strcmp(i->registrar, registrar) == 0) { 09197 /* remove from list */ 09198 if (pi) { 09199 pi->next = i->next; 09200 /* free include */ 09201 ast_free(i); 09202 continue; /* don't change pi */ 09203 } else { 09204 tmp->includes = i->next; 09205 /* free include */ 09206 ast_free(i); 09207 continue; /* don't change pi */ 09208 } 09209 } 09210 pi = i; 09211 } 09212 /* remove any switches whose registrar matches */ 09213 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 09214 if (strcmp(sw->registrar,registrar) == 0) { 09215 AST_LIST_REMOVE_CURRENT(list); 09216 ast_free(sw); 09217 } 09218 } 09219 AST_LIST_TRAVERSE_SAFE_END; 09220 09221 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 09222 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 09223 while ((exten_item=ast_hashtab_next(exten_iter))) { 09224 int end_traversal = 1; 09225 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 09226 while ((prio_item=ast_hashtab_next(prio_iter))) { 09227 char extension[AST_MAX_EXTENSION]; 09228 char cidmatch[AST_MAX_EXTENSION]; 09229 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 09230 continue; 09231 } 09232 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 09233 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 09234 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 09235 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 09236 if (prio_item->cidmatch) { 09237 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 09238 } 09239 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1); 09240 } 09241 /* Explanation: 09242 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 09243 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 09244 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 09245 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 09246 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 09247 * free the iterator 09248 */ 09249 if (end_traversal) { 09250 ast_hashtab_end_traversal(prio_iter); 09251 } else { 09252 ast_free(prio_iter); 09253 } 09254 } 09255 ast_hashtab_end_traversal(exten_iter); 09256 } 09257 09258 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 09259 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 09260 another registrar. It's not empty if there are any extensions */ 09261 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 09262 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09263 ast_hashtab_remove_this_object(contexttab, tmp); 09264 09265 next = tmp->next; 09266 if (tmpl) 09267 tmpl->next = next; 09268 else 09269 contexts = next; 09270 /* Okay, now we're safe to let it go -- in a sense, we were 09271 ready to let it go as soon as we locked it. */ 09272 ast_unlock_context(tmp); 09273 __ast_internal_context_destroy(tmp); 09274 } else { 09275 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 09276 tmp->refcount, tmp->root); 09277 ast_unlock_context(tmp); 09278 next = tmp->next; 09279 tmpl = tmp; 09280 } 09281 } else if (con) { 09282 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 09283 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09284 ast_hashtab_remove_this_object(contexttab, tmp); 09285 09286 next = tmp->next; 09287 if (tmpl) 09288 tmpl->next = next; 09289 else 09290 contexts = next; 09291 /* Okay, now we're safe to let it go -- in a sense, we were 09292 ready to let it go as soon as we locked it. */ 09293 ast_unlock_context(tmp); 09294 __ast_internal_context_destroy(tmp); 09295 } 09296 09297 /* if we have a specific match, we are done, otherwise continue */ 09298 tmp = con ? NULL : next; 09299 } 09300 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3591 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().
03592 { 03593 struct ast_custom_function *cur; 03594 char tmps[80]; 03595 03596 if (!acf) { 03597 return -1; 03598 } 03599 03600 acf->mod = mod; 03601 #ifdef AST_XML_DOCS 03602 acf->docsrc = AST_STATIC_DOC; 03603 #endif 03604 03605 if (acf_retrieve_docs(acf)) { 03606 return -1; 03607 } 03608 03609 AST_RWLIST_WRLOCK(&acf_root); 03610 03611 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03612 if (!strcmp(acf->name, cur->name)) { 03613 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03614 AST_RWLIST_UNLOCK(&acf_root); 03615 return -1; 03616 } 03617 } 03618 03619 /* Store in alphabetical order */ 03620 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03621 if (strcasecmp(acf->name, cur->name) < 0) { 03622 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03623 break; 03624 } 03625 } 03626 AST_RWLIST_TRAVERSE_SAFE_END; 03627 03628 if (!cur) { 03629 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03630 } 03631 03632 AST_RWLIST_UNLOCK(&acf_root); 03633 03634 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03635 03636 return 0; 03637 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 10549 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().
10550 { 10551 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 10552 10553 if (!chan) 10554 return -2; 10555 10556 if (context == NULL) 10557 context = chan->context; 10558 if (exten == NULL) 10559 exten = chan->exten; 10560 10561 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 10562 if (ast_exists_extension(chan, context, exten, priority, 10563 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 10564 return goto_func(chan, context, exten, priority); 10565 else { 10566 return AST_PBX_GOTO_FAILED; 10567 } 10568 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 9097 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().
09098 { 09099 struct ast_include *tmpi; 09100 struct ast_sw *sw; 09101 struct ast_exten *e, *el, *en; 09102 struct ast_ignorepat *ipi; 09103 struct ast_context *tmp = con; 09104 09105 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 09106 struct ast_include *tmpil = tmpi; 09107 tmpi = tmpi->next; 09108 ast_free(tmpil); 09109 } 09110 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 09111 struct ast_ignorepat *ipl = ipi; 09112 ipi = ipi->next; 09113 ast_free(ipl); 09114 } 09115 if (tmp->registrar) 09116 ast_free(tmp->registrar); 09117 09118 /* destroy the hash tabs */ 09119 if (tmp->root_table) { 09120 ast_hashtab_destroy(tmp->root_table, 0); 09121 } 09122 /* and destroy the pattern tree */ 09123 if (tmp->pattern_tree) 09124 destroy_pattern_tree(tmp->pattern_tree); 09125 09126 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 09127 ast_free(sw); 09128 for (e = tmp->root; e;) { 09129 for (en = e->peer; en;) { 09130 el = en; 09131 en = en->peer; 09132 destroy_exten(el); 09133 } 09134 el = e; 09135 e = e->next; 09136 destroy_exten(el); 09137 } 09138 tmp->root = NULL; 09139 ast_rwlock_destroy(&tmp->lock); 09140 ast_free(tmp); 09141 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 4950 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().
04952 { 04953 int found = 0; /* set if we find at least one match */ 04954 int res = 0; 04955 int autoloopflag; 04956 int error = 0; /* set an error conditions */ 04957 04958 /* A little initial setup here */ 04959 if (c->pbx) { 04960 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 04961 /* XXX and now what ? */ 04962 ast_free(c->pbx); 04963 } 04964 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 04965 return -1; 04966 /* Set reasonable defaults */ 04967 c->pbx->rtimeoutms = 10000; 04968 c->pbx->dtimeoutms = 5000; 04969 04970 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 04971 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 04972 04973 /* Start by trying whatever the channel is set to */ 04974 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 04975 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04976 /* If not successful fall back to 's' */ 04977 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); 04978 /* XXX the original code used the existing priority in the call to 04979 * ast_exists_extension(), and reset it to 1 afterwards. 04980 * I believe the correct thing is to set it to 1 immediately. 04981 */ 04982 set_ext_pri(c, "s", 1); 04983 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 04984 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04985 /* JK02: And finally back to default if everything else failed */ 04986 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); 04987 ast_copy_string(c->context, "default", sizeof(c->context)); 04988 } 04989 } 04990 ast_channel_lock(c); 04991 if (c->cdr) { 04992 /* allow CDR variables that have been collected after channel was created to be visible during call */ 04993 ast_cdr_update(c); 04994 } 04995 ast_channel_unlock(c); 04996 for (;;) { 04997 char dst_exten[256]; /* buffer to accumulate digits */ 04998 int pos = 0; /* XXX should check bounds */ 04999 int digit = 0; 05000 int invalid = 0; 05001 int timeout = 0; 05002 05003 /* loop on priorities in this context/exten */ 05004 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05005 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05006 &found, 1))) { 05007 if (!ast_check_hangup(c)) { 05008 ++c->priority; 05009 continue; 05010 } 05011 05012 /* Check softhangup flags. */ 05013 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05014 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05015 continue; 05016 } 05017 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05018 if (ast_exists_extension(c, c->context, "T", 1, 05019 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05020 set_ext_pri(c, "T", 1); 05021 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05022 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05023 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05024 continue; 05025 } else if (ast_exists_extension(c, c->context, "e", 1, 05026 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05027 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05028 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05029 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05030 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05031 continue; 05032 } 05033 05034 /* Call timed out with no special extension to jump to. */ 05035 error = 1; 05036 break; 05037 } 05038 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 05039 c->exten, c->priority); 05040 error = 1; 05041 break; 05042 } /* end while - from here on we can use 'break' to go out */ 05043 if (found && res) { 05044 /* Something bad happened, or a hangup has been requested. */ 05045 if (strchr("0123456789ABCDEF*#", res)) { 05046 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 05047 pos = 0; 05048 dst_exten[pos++] = digit = res; 05049 dst_exten[pos] = '\0'; 05050 } else if (res == AST_PBX_INCOMPLETE) { 05051 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05052 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05053 05054 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 05055 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 05056 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05057 invalid = 1; 05058 } else { 05059 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 05060 digit = 1; 05061 pos = strlen(dst_exten); 05062 } 05063 } else { 05064 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05065 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05066 05067 if ((res == AST_PBX_ERROR) 05068 && ast_exists_extension(c, c->context, "e", 1, 05069 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05070 /* if we are already on the 'e' exten, don't jump to it again */ 05071 if (!strcmp(c->exten, "e")) { 05072 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); 05073 error = 1; 05074 } else { 05075 raise_exception(c, "ERROR", 1); 05076 continue; 05077 } 05078 } 05079 05080 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05081 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05082 continue; 05083 } 05084 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05085 if (ast_exists_extension(c, c->context, "T", 1, 05086 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05087 set_ext_pri(c, "T", 1); 05088 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05089 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05090 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05091 continue; 05092 } else if (ast_exists_extension(c, c->context, "e", 1, 05093 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05094 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05095 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05096 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05097 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05098 continue; 05099 } 05100 /* Call timed out with no special extension to jump to. */ 05101 } 05102 ast_channel_lock(c); 05103 if (c->cdr) { 05104 ast_cdr_update(c); 05105 } 05106 ast_channel_unlock(c); 05107 error = 1; 05108 break; 05109 } 05110 } 05111 if (error) 05112 break; 05113 05114 /*!\note 05115 * We get here on a failure of some kind: non-existing extension or 05116 * hangup. We have options, here. We can either catch the failure 05117 * and continue, or we can drop out entirely. */ 05118 05119 if (invalid 05120 || (ast_strlen_zero(dst_exten) && 05121 !ast_exists_extension(c, c->context, c->exten, 1, 05122 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) { 05123 /*!\note 05124 * If there is no match at priority 1, it is not a valid extension anymore. 05125 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 05126 * neither exist. 05127 */ 05128 if (ast_exists_extension(c, c->context, "i", 1, 05129 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05130 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 05131 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 05132 set_ext_pri(c, "i", 1); 05133 } else if (ast_exists_extension(c, c->context, "e", 1, 05134 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05135 raise_exception(c, "INVALID", 1); 05136 } else { 05137 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 05138 c->name, c->exten, c->context); 05139 error = 1; /* we know what to do with it */ 05140 break; 05141 } 05142 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05143 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 05144 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05145 } else { /* keypress received, get more digits for a full extension */ 05146 int waittime = 0; 05147 if (digit) 05148 waittime = c->pbx->dtimeoutms; 05149 else if (!autofallthrough) 05150 waittime = c->pbx->rtimeoutms; 05151 if (!waittime) { 05152 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 05153 if (!status) 05154 status = "UNKNOWN"; 05155 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 05156 if (!strcasecmp(status, "CONGESTION")) 05157 res = pbx_builtin_congestion(c, "10"); 05158 else if (!strcasecmp(status, "CHANUNAVAIL")) 05159 res = pbx_builtin_congestion(c, "10"); 05160 else if (!strcasecmp(status, "BUSY")) 05161 res = pbx_builtin_busy(c, "10"); 05162 error = 1; /* XXX disable message */ 05163 break; /* exit from the 'for' loop */ 05164 } 05165 05166 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 05167 break; 05168 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 05169 timeout = 1; 05170 if (!timeout 05171 && ast_exists_extension(c, c->context, dst_exten, 1, 05172 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 05173 set_ext_pri(c, dst_exten, 1); 05174 } else { 05175 /* No such extension */ 05176 if (!timeout && !ast_strlen_zero(dst_exten)) { 05177 /* An invalid extension */ 05178 if (ast_exists_extension(c, c->context, "i", 1, 05179 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05180 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 05181 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 05182 set_ext_pri(c, "i", 1); 05183 } else if (ast_exists_extension(c, c->context, "e", 1, 05184 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05185 raise_exception(c, "INVALID", 1); 05186 } else { 05187 ast_log(LOG_WARNING, 05188 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", 05189 dst_exten, c->context); 05190 found = 1; /* XXX disable message */ 05191 break; 05192 } 05193 } else { 05194 /* A simple timeout */ 05195 if (ast_exists_extension(c, c->context, "t", 1, 05196 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05197 ast_verb(3, "Timeout on %s\n", c->name); 05198 set_ext_pri(c, "t", 1); 05199 } else if (ast_exists_extension(c, c->context, "e", 1, 05200 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05201 raise_exception(c, "RESPONSETIMEOUT", 1); 05202 } else { 05203 ast_log(LOG_WARNING, 05204 "Timeout, but no rule 't' or 'e' in context '%s'\n", 05205 c->context); 05206 found = 1; /* XXX disable message */ 05207 break; 05208 } 05209 } 05210 } 05211 ast_channel_lock(c); 05212 if (c->cdr) { 05213 ast_verb(2, "CDR updated on %s\n",c->name); 05214 ast_cdr_update(c); 05215 } 05216 ast_channel_unlock(c); 05217 } 05218 } 05219 05220 if (!found && !error) { 05221 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 05222 } 05223 05224 if (!args || !args->no_hangup_chan) { 05225 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 05226 } 05227 05228 if ((!args || !args->no_hangup_chan) 05229 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 05230 && ast_exists_extension(c, c->context, "h", 1, 05231 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05232 set_ext_pri(c, "h", 1); 05233 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 05234 ast_cdr_end(c->cdr); 05235 } 05236 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05237 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05238 &found, 1)) == 0) { 05239 c->priority++; 05240 } 05241 if (found && res) { 05242 /* Something bad happened, or a hangup has been requested. */ 05243 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05244 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05245 } 05246 } 05247 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 05248 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 05249 pbx_destroy(c->pbx); 05250 c->pbx = NULL; 05251 05252 if (!args || !args->no_hangup_chan) { 05253 ast_hangup(c); 05254 } 05255 05256 return 0; 05257 }
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 2469 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02470 { 02471 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02472 02473 #ifdef NEED_DEBUG_HERE 02474 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02475 #endif 02476 02477 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 02478 #ifdef NEED_DEBUG_HERE 02479 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02480 #endif 02481 return 1; 02482 } 02483 02484 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02485 int ld = strlen(data), lp = strlen(pattern); 02486 02487 if (lp < ld) { /* pattern too short, cannot match */ 02488 #ifdef NEED_DEBUG_HERE 02489 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02490 #endif 02491 return 0; 02492 } 02493 /* depending on the mode, accept full or partial match or both */ 02494 if (mode == E_MATCH) { 02495 #ifdef NEED_DEBUG_HERE 02496 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 02497 #endif 02498 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 02499 } 02500 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 02501 #ifdef NEED_DEBUG_HERE 02502 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02503 #endif 02504 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02505 } else { 02506 #ifdef NEED_DEBUG_HERE 02507 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02508 #endif 02509 return 0; 02510 } 02511 } 02512 pattern++; /* skip leading _ */ 02513 /* 02514 * XXX below we stop at '/' which is a separator for the CID info. However we should 02515 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02516 */ 02517 while (*data && *pattern && *pattern != '/') { 02518 const char *end; 02519 02520 if (*data == '-') { /* skip '-' in data (just a separator) */ 02521 data++; 02522 continue; 02523 } 02524 switch (toupper(*pattern)) { 02525 case '[': /* a range */ 02526 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 02527 if (end == NULL) { 02528 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02529 return 0; /* unconditional failure */ 02530 } 02531 for (pattern++; pattern != end; pattern++) { 02532 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02533 if (*data >= pattern[0] && *data <= pattern[2]) 02534 break; /* match found */ 02535 else { 02536 pattern += 2; /* skip a total of 3 chars */ 02537 continue; 02538 } 02539 } else if (*data == pattern[0]) 02540 break; /* match found */ 02541 } 02542 if (pattern == end) { 02543 #ifdef NEED_DEBUG_HERE 02544 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 02545 #endif 02546 return 0; 02547 } 02548 pattern = end; /* skip and continue */ 02549 break; 02550 case 'N': 02551 if (*data < '2' || *data > '9') { 02552 #ifdef NEED_DEBUG_HERE 02553 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 02554 #endif 02555 return 0; 02556 } 02557 break; 02558 case 'X': 02559 if (*data < '0' || *data > '9') { 02560 #ifdef NEED_DEBUG_HERE 02561 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 02562 #endif 02563 return 0; 02564 } 02565 break; 02566 case 'Z': 02567 if (*data < '1' || *data > '9') { 02568 #ifdef NEED_DEBUG_HERE 02569 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 02570 #endif 02571 return 0; 02572 } 02573 break; 02574 case '.': /* Must match, even with more digits */ 02575 #ifdef NEED_DEBUG_HERE 02576 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02577 #endif 02578 return 1; 02579 case '!': /* Early match */ 02580 #ifdef NEED_DEBUG_HERE 02581 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02582 #endif 02583 return 2; 02584 case ' ': 02585 case '-': /* Ignore these in patterns */ 02586 data--; /* compensate the final data++ */ 02587 break; 02588 default: 02589 if (*data != *pattern) { 02590 #ifdef NEED_DEBUG_HERE 02591 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02592 #endif 02593 return 0; 02594 } 02595 } 02596 data++; 02597 pattern++; 02598 } 02599 if (*data) /* data longer than pattern, no match */ { 02600 #ifdef NEED_DEBUG_HERE 02601 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02602 #endif 02603 return 0; 02604 } 02605 02606 /* 02607 * match so far, but ran off the end of the data. 02608 * Depending on what is next, determine match or not. 02609 */ 02610 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02611 #ifdef NEED_DEBUG_HERE 02612 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02613 #endif 02614 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02615 } else if (*pattern == '!') { /* early match */ 02616 #ifdef NEED_DEBUG_HERE 02617 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02618 #endif 02619 return 2; 02620 } else { /* partial match */ 02621 #ifdef NEED_DEBUG_HERE 02622 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02623 #endif 02624 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02625 } 02626 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 3328 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.
03329 { 03330 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03331 struct pbx_exception *exception = NULL; 03332 if (!ds || !ds->data) 03333 return -1; 03334 exception = ds->data; 03335 if (!strcasecmp(data, "REASON")) 03336 ast_copy_string(buf, exception->reason, buflen); 03337 else if (!strcasecmp(data, "CONTEXT")) 03338 ast_copy_string(buf, exception->context, buflen); 03339 else if (!strncasecmp(data, "EXTEN", 5)) 03340 ast_copy_string(buf, exception->exten, buflen); 03341 else if (!strcasecmp(data, "PRIORITY")) 03342 snprintf(buf, buflen, "%d", exception->priority); 03343 else 03344 return -1; 03345 return 0; 03346 }
static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3546 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().
03547 { 03548 #ifdef AST_XML_DOCS 03549 char *tmpxml; 03550 03551 /* Let's try to find it in the Documentation XML */ 03552 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03553 return 0; 03554 } 03555 03556 if (ast_string_field_init(acf, 128)) { 03557 return -1; 03558 } 03559 03560 /* load synopsis */ 03561 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); 03562 ast_string_field_set(acf, synopsis, tmpxml); 03563 ast_free(tmpxml); 03564 03565 /* load description */ 03566 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); 03567 ast_string_field_set(acf, desc, tmpxml); 03568 ast_free(tmpxml); 03569 03570 /* load syntax */ 03571 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod)); 03572 ast_string_field_set(acf, syntax, tmpxml); 03573 ast_free(tmpxml); 03574 03575 /* load arguments */ 03576 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod)); 03577 ast_string_field_set(acf, arguments, tmpxml); 03578 ast_free(tmpxml); 03579 03580 /* load seealso */ 03581 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod)); 03582 ast_string_field_set(acf, seealso, tmpxml); 03583 ast_free(tmpxml); 03584 03585 acf->docsrc = AST_XML_DOC; 03586 #endif 03587 03588 return 0; 03589 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static] |
Definition at line 2147 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().
02148 { 02149 struct match_char *m1 = NULL; 02150 struct match_char *m2 = NULL; 02151 struct match_char **m0; 02152 const char *pos; 02153 int already; 02154 int pattern = 0; 02155 int idx_cur; 02156 int idx_next; 02157 char extenbuf[512]; 02158 struct pattern_node pat_node[2]; 02159 02160 if (e1->matchcid) { 02161 if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) { 02162 ast_log(LOG_ERROR, 02163 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", 02164 e1->exten, e1->cidmatch); 02165 return NULL; 02166 } 02167 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */ 02168 } else { 02169 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 02170 } 02171 02172 #ifdef NEED_DEBUG 02173 ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf); 02174 #endif 02175 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 02176 m0 = &con->pattern_tree; 02177 already = 1; 02178 02179 pos = extenbuf; 02180 if (*pos == '_') { 02181 pattern = 1; 02182 ++pos; 02183 } 02184 idx_cur = 0; 02185 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf); 02186 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) { 02187 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node); 02188 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf); 02189 02190 /* See about adding node to tree. */ 02191 m2 = NULL; 02192 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern)) 02193 && m2->next_char) { 02194 if (!pat_node[idx_next].buf[0]) { 02195 /* 02196 * This is the end of the pattern, but not the end of the tree. 02197 * Mark this node with the exten... a shorter pattern might win 02198 * if the longer one doesn't match. 02199 */ 02200 if (findonly) { 02201 return m2; 02202 } 02203 if (m2->exten) { 02204 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02205 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02206 } 02207 m2->exten = e1; 02208 m2->deleted = 0; 02209 } 02210 m1 = m2->next_char; /* m1 points to the node to compare against */ 02211 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02212 } else { /* not already OR not m2 OR nor m2->next_char */ 02213 if (m2) { 02214 if (findonly) { 02215 return m2; 02216 } 02217 m1 = m2; /* while m0 stays the same */ 02218 } else { 02219 if (findonly) { 02220 return m1; 02221 } 02222 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0); 02223 if (!m1) { /* m1 is the node just added */ 02224 return NULL; 02225 } 02226 m0 = &m1->next_char; 02227 } 02228 if (!pat_node[idx_next].buf[0]) { 02229 if (m2 && m2->exten) { 02230 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02231 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02232 } 02233 m1->deleted = 0; 02234 m1->exten = e1; 02235 } 02236 02237 /* The 'already' variable is a mini-optimization designed to make it so that we 02238 * don't have to call already_in_tree when we know it will return false. 02239 */ 02240 already = 0; 02241 } 02242 } 02243 return m1; 02244 }
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 1949 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().
01950 { 01951 struct match_char *m; 01952 01953 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) { 01954 return NULL; 01955 } 01956 01957 /* strcpy is safe here since we know its size and have allocated 01958 * just enough space for when we allocated m 01959 */ 01960 strcpy(m->x, pattern->buf); 01961 01962 /* the specificity scores are the same as used in the old 01963 pattern matcher. */ 01964 m->is_pattern = is_pattern; 01965 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') { 01966 m->specificity = 0x0832; 01967 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') { 01968 m->specificity = 0x0931; 01969 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') { 01970 m->specificity = 0x0a30; 01971 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') { 01972 m->specificity = 0x18000; 01973 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') { 01974 m->specificity = 0x28000; 01975 } else { 01976 m->specificity = pattern->specif; 01977 } 01978 01979 if (!con->pattern_tree) { 01980 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01981 } else { 01982 if (already) { /* switch to the new regime (traversing vs appending)*/ 01983 insert_in_next_chars_alt_char_list(nextcharptr, m); 01984 } else { 01985 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01986 } 01987 } 01988 01989 return m; 01990 }
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 8300 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().
08302 { 08303 struct ast_exten *ep; 08304 struct ast_exten *eh=e; 08305 int repeated_label = 0; /* Track if this label is a repeat, assume no. */ 08306 08307 for (ep = NULL; e ; ep = e, e = e->peer) { 08308 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) { 08309 ast_log(LOG_WARNING, "Extension '%s', priority %d in '%s', label '%s' already in use at " 08310 "priority %d\n", tmp->exten, tmp->priority, con->name, tmp->label, e->priority); 08311 repeated_label = 1; 08312 } 08313 if (e->priority >= tmp->priority) { 08314 break; 08315 } 08316 } 08317 08318 if (repeated_label) { /* Discard the label since it's a repeat. */ 08319 tmp->label = NULL; 08320 } 08321 08322 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 08323 ast_hashtab_insert_safe(eh->peer_table, tmp); 08324 08325 if (tmp->label) { 08326 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08327 } 08328 ep->peer = tmp; 08329 return 0; /* success */ 08330 } 08331 if (e->priority == tmp->priority) { 08332 /* Can't have something exactly the same. Is this a 08333 replacement? If so, replace, otherwise, bonk. */ 08334 if (!replace) { 08335 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 08336 if (tmp->datad) { 08337 tmp->datad(tmp->data); 08338 /* if you free this, null it out */ 08339 tmp->data = NULL; 08340 } 08341 08342 ast_free(tmp); 08343 return -1; 08344 } 08345 /* we are replacing e, so copy the link fields and then update 08346 * whoever pointed to e to point to us 08347 */ 08348 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 08349 tmp->peer = e->peer; /* always meaningful */ 08350 if (ep) { /* We're in the peer list, just insert ourselves */ 08351 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 08352 08353 if (e->label) { 08354 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 08355 } 08356 08357 ast_hashtab_insert_safe(eh->peer_table,tmp); 08358 if (tmp->label) { 08359 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 08360 } 08361 08362 ep->peer = tmp; 08363 } else if (el) { /* We're the first extension. Take over e's functions */ 08364 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08365 tmp->peer_table = e->peer_table; 08366 tmp->peer_label_table = e->peer_label_table; 08367 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 08368 ast_hashtab_insert_safe(tmp->peer_table,tmp); 08369 if (e->label) { 08370 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08371 } 08372 if (tmp->label) { 08373 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08374 } 08375 08376 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08377 ast_hashtab_insert_safe(con->root_table, tmp); 08378 el->next = tmp; 08379 /* The pattern trie points to this exten; replace the pointer, 08380 and all will be well */ 08381 if (x) { /* if the trie isn't formed yet, don't sweat this */ 08382 if (x->exten) { /* this test for safety purposes */ 08383 x->exten = tmp; /* replace what would become a bad pointer */ 08384 } else { 08385 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08386 } 08387 } 08388 } else { /* We're the very first extension. */ 08389 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08390 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08391 ast_hashtab_insert_safe(con->root_table, tmp); 08392 tmp->peer_table = e->peer_table; 08393 tmp->peer_label_table = e->peer_label_table; 08394 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 08395 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08396 if (e->label) { 08397 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08398 } 08399 if (tmp->label) { 08400 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08401 } 08402 08403 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08404 ast_hashtab_insert_safe(con->root_table, tmp); 08405 con->root = tmp; 08406 /* The pattern trie points to this exten; replace the pointer, 08407 and all will be well */ 08408 if (x) { /* if the trie isn't formed yet; no problem */ 08409 if (x->exten) { /* this test for safety purposes */ 08410 x->exten = tmp; /* replace what would become a bad pointer */ 08411 } else { 08412 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08413 } 08414 } 08415 } 08416 if (tmp->priority == PRIORITY_HINT) 08417 ast_change_hint(e,tmp); 08418 /* Destroy the old one */ 08419 if (e->datad) 08420 e->datad(e->data); 08421 ast_free(e); 08422 } else { /* Slip ourselves in just before e */ 08423 tmp->peer = e; 08424 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 08425 if (ep) { /* Easy enough, we're just in the peer list */ 08426 if (tmp->label) { 08427 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08428 } 08429 ast_hashtab_insert_safe(eh->peer_table, tmp); 08430 ep->peer = tmp; 08431 } else { /* we are the first in some peer list, so link in the ext list */ 08432 tmp->peer_table = e->peer_table; 08433 tmp->peer_label_table = e->peer_label_table; 08434 e->peer_table = 0; 08435 e->peer_label_table = 0; 08436 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08437 if (tmp->label) { 08438 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08439 } 08440 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08441 ast_hashtab_insert_safe(con->root_table, tmp); 08442 if (el) 08443 el->next = tmp; /* in the middle... */ 08444 else 08445 con->root = tmp; /* ... or at the head */ 08446 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 08447 } 08448 /* And immediately return success. */ 08449 if (tmp->priority == PRIORITY_HINT) { 08450 ast_add_hint(tmp); 08451 } 08452 } 08453 return 0; 08454 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat, | |||
int | is_pattern | |||
) | [static] |
Definition at line 1887 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01888 { 01889 struct match_char *t; 01890 01891 if (!current) { 01892 return 0; 01893 } 01894 01895 for (t = current; t; t = t->alt_char) { 01896 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01897 return t; 01898 } 01899 } 01900 01901 return 0; 01902 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5405 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05406 { 05407 return countcalls; 05408 }
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 8135 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().
08138 { 08139 int ret = -1; 08140 struct ast_context *c; 08141 08142 c = find_context_locked(context); 08143 if (c) { 08144 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08145 application, data, datad, registrar); 08146 ast_unlock_contexts(); 08147 } 08148 08149 return ret; 08150 }
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 8481 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), and pbx_load_users().
08485 { 08486 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08487 application, data, datad, registrar, 1); 08488 }
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 8497 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().
08501 { 08502 /* 08503 * Sort extensions (or patterns) according to the rules indicated above. 08504 * These are implemented by the function ext_cmp()). 08505 * All priorities for the same ext/pattern/cid are kept in a list, 08506 * using the 'peer' field as a link field.. 08507 */ 08508 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 08509 int res; 08510 int length; 08511 char *p; 08512 char expand_buf[VAR_BUF_SIZE]; 08513 struct ast_exten dummy_exten = {0}; 08514 char dummy_name[1024]; 08515 08516 if (ast_strlen_zero(extension)) { 08517 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", 08518 con->name); 08519 return -1; 08520 } 08521 08522 /* If we are adding a hint evalulate in variables and global variables */ 08523 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 08524 struct ast_channel *c = ast_dummy_channel_alloc(); 08525 08526 if (c) { 08527 ast_copy_string(c->exten, extension, sizeof(c->exten)); 08528 ast_copy_string(c->context, con->name, sizeof(c->context)); 08529 } 08530 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 08531 application = expand_buf; 08532 if (c) { 08533 ast_channel_unref(c); 08534 } 08535 } 08536 08537 length = sizeof(struct ast_exten); 08538 length += strlen(extension) + 1; 08539 length += strlen(application) + 1; 08540 if (label) 08541 length += strlen(label) + 1; 08542 if (callerid) 08543 length += strlen(callerid) + 1; 08544 else 08545 length ++; /* just the '\0' */ 08546 08547 /* Be optimistic: Build the extension structure first */ 08548 if (!(tmp = ast_calloc(1, length))) 08549 return -1; 08550 08551 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 08552 label = 0; 08553 08554 /* use p as dst in assignments, as the fields are const char * */ 08555 p = tmp->stuff; 08556 if (label) { 08557 tmp->label = p; 08558 strcpy(p, label); 08559 p += strlen(label) + 1; 08560 } 08561 tmp->exten = p; 08562 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 08563 tmp->priority = priority; 08564 tmp->cidmatch = p; /* but use p for assignments below */ 08565 08566 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 08567 if (callerid) { 08568 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 08569 tmp->matchcid = 1; 08570 } else { 08571 *p++ = '\0'; 08572 tmp->matchcid = 0; 08573 } 08574 tmp->app = p; 08575 strcpy(p, application); 08576 tmp->parent = con; 08577 tmp->data = data; 08578 tmp->datad = datad; 08579 tmp->registrar = registrar; 08580 08581 if (lock_context) { 08582 ast_wrlock_context(con); 08583 } 08584 08585 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 08586 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 08587 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 08588 dummy_exten.exten = dummy_name; 08589 dummy_exten.matchcid = 0; 08590 dummy_exten.cidmatch = 0; 08591 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 08592 if (!tmp2) { 08593 /* hmmm, not in the trie; */ 08594 add_exten_to_pattern_tree(con, tmp, 0); 08595 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 08596 } 08597 } 08598 res = 0; /* some compilers will think it is uninitialized otherwise */ 08599 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 08600 res = ext_cmp(e->exten, tmp->exten); 08601 if (res == 0) { /* extension match, now look at cidmatch */ 08602 if (!e->matchcid && !tmp->matchcid) 08603 res = 0; 08604 else if (tmp->matchcid && !e->matchcid) 08605 res = 1; 08606 else if (e->matchcid && !tmp->matchcid) 08607 res = -1; 08608 else 08609 res = ext_cmp(e->cidmatch, tmp->cidmatch); 08610 } 08611 if (res >= 0) 08612 break; 08613 } 08614 if (e && res == 0) { /* exact match, insert in the priority chain */ 08615 res = add_priority(con, tmp, el, e, replace); 08616 if (lock_context) { 08617 ast_unlock_context(con); 08618 } 08619 if (res < 0) { 08620 errno = EEXIST; /* XXX do we care ? */ 08621 return 0; /* XXX should we return -1 maybe ? */ 08622 } 08623 } else { 08624 /* 08625 * not an exact match, this is the first entry with this pattern, 08626 * so insert in the main list right before 'e' (if any) 08627 */ 08628 tmp->next = e; 08629 if (el) { /* there is another exten already in this context */ 08630 el->next = tmp; 08631 tmp->peer_table = ast_hashtab_create(13, 08632 hashtab_compare_exten_numbers, 08633 ast_hashtab_resize_java, 08634 ast_hashtab_newsize_java, 08635 hashtab_hash_priority, 08636 0); 08637 tmp->peer_label_table = ast_hashtab_create(7, 08638 hashtab_compare_exten_labels, 08639 ast_hashtab_resize_java, 08640 ast_hashtab_newsize_java, 08641 hashtab_hash_labels, 08642 0); 08643 if (label) { 08644 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08645 } 08646 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08647 } else { /* this is the first exten in this context */ 08648 if (!con->root_table) 08649 con->root_table = ast_hashtab_create(27, 08650 hashtab_compare_extens, 08651 ast_hashtab_resize_java, 08652 ast_hashtab_newsize_java, 08653 hashtab_hash_extens, 08654 0); 08655 con->root = tmp; 08656 con->root->peer_table = ast_hashtab_create(13, 08657 hashtab_compare_exten_numbers, 08658 ast_hashtab_resize_java, 08659 ast_hashtab_newsize_java, 08660 hashtab_hash_priority, 08661 0); 08662 con->root->peer_label_table = ast_hashtab_create(7, 08663 hashtab_compare_exten_labels, 08664 ast_hashtab_resize_java, 08665 ast_hashtab_newsize_java, 08666 hashtab_hash_labels, 08667 0); 08668 if (label) { 08669 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 08670 } 08671 ast_hashtab_insert_safe(con->root->peer_table, tmp); 08672 08673 } 08674 ast_hashtab_insert_safe(con->root_table, tmp); 08675 if (lock_context) { 08676 ast_unlock_context(con); 08677 } 08678 if (tmp->priority == PRIORITY_HINT) { 08679 ast_add_hint(tmp); 08680 } 08681 } 08682 if (option_debug) { 08683 if (tmp->matchcid) { 08684 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 08685 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 08686 } else { 08687 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 08688 tmp->exten, tmp->priority, con->name, con); 08689 } 08690 } 08691 08692 if (tmp->matchcid) { 08693 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 08694 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 08695 } else { 08696 ast_verb(3, "Added extension '%s' priority %d to %s\n", 08697 tmp->exten, tmp->priority, con->name); 08698 } 08699 08700 return 0; 08701 }
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 8115 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
08118 { 08119 int ret = -1; 08120 struct ast_context *c; 08121 08122 c = find_context(context); 08123 if (c) { 08124 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 08125 application, data, datad, registrar, 1); 08126 } 08127 08128 return ret; 08129 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 4751 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().
04752 { 04753 struct ast_hint *hint_new; 04754 struct ast_hint *hint_found; 04755 04756 if (!e) { 04757 return -1; 04758 } 04759 04760 /* 04761 * We must create the hint we wish to add before determining if 04762 * it is already in the hints container to avoid possible 04763 * deadlock when getting the current extension state. 04764 */ 04765 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint); 04766 if (!hint_new) { 04767 return -1; 04768 } 04769 04770 /* Initialize new hint. */ 04771 hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); 04772 if (!hint_new->callbacks) { 04773 ao2_ref(hint_new, -1); 04774 return -1; 04775 } 04776 hint_new->exten = e; 04777 hint_new->laststate = ast_extension_state2(e); 04778 04779 /* Prevent multiple add hints from adding the same hint at the same time. */ 04780 ao2_lock(hints); 04781 04782 /* Search if hint exists, do nothing */ 04783 hint_found = ao2_find(hints, e, 0); 04784 if (hint_found) { 04785 ao2_ref(hint_found, -1); 04786 ao2_unlock(hints); 04787 ao2_ref(hint_new, -1); 04788 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", 04789 ast_get_extension_name(e), ast_get_extension_app(e)); 04790 return -1; 04791 } 04792 04793 /* Add new hint to the hints container */ 04794 ast_debug(2, "HINTS: Adding hint %s: %s\n", 04795 ast_get_extension_name(e), ast_get_extension_app(e)); 04796 ao2_link(hints, hint_new); 04797 04798 ao2_unlock(hints); 04799 ao2_ref(hint_new, -1); 04800 04801 return 0; 04802 }
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 8175 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().
08176 { 08177 int res = 0; 08178 struct ast_channel *tmpchan; 08179 struct { 08180 char *accountcode; 08181 char *exten; 08182 char *context; 08183 char *linkedid; 08184 char *name; 08185 struct ast_cdr *cdr; 08186 int amaflags; 08187 int state; 08188 format_t readformat; 08189 format_t writeformat; 08190 } tmpvars = { 0, }; 08191 08192 ast_channel_lock(chan); 08193 if (chan->pbx) { /* This channel is currently in the PBX */ 08194 ast_explicit_goto(chan, context, exten, priority + 1); 08195 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08196 ast_channel_unlock(chan); 08197 return res; 08198 } 08199 08200 /* In order to do it when the channel doesn't really exist within 08201 * the PBX, we have to make a new channel, masquerade, and start the PBX 08202 * at the new location */ 08203 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08204 tmpvars.exten = ast_strdupa(chan->exten); 08205 tmpvars.context = ast_strdupa(chan->context); 08206 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08207 tmpvars.name = ast_strdupa(chan->name); 08208 tmpvars.amaflags = chan->amaflags; 08209 tmpvars.state = chan->_state; 08210 tmpvars.writeformat = chan->writeformat; 08211 tmpvars.readformat = chan->readformat; 08212 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08213 08214 ast_channel_unlock(chan); 08215 08216 /* Do not hold any channel locks while calling channel_alloc() since the function 08217 * locks the channel container when linking the new channel in. */ 08218 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08219 ast_cdr_discard(tmpvars.cdr); 08220 return -1; 08221 } 08222 08223 /* copy the cdr info over */ 08224 if (tmpvars.cdr) { 08225 ast_cdr_discard(tmpchan->cdr); 08226 tmpchan->cdr = tmpvars.cdr; 08227 tmpvars.cdr = NULL; 08228 } 08229 08230 /* Make formats okay */ 08231 tmpchan->readformat = tmpvars.readformat; 08232 tmpchan->writeformat = tmpvars.writeformat; 08233 08234 /* Setup proper location. Never hold another channel lock while calling this function. */ 08235 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08236 08237 /* Masquerade into tmp channel */ 08238 if (ast_channel_masquerade(tmpchan, chan)) { 08239 /* Failed to set up the masquerade. It's probably chan_local 08240 * in the middle of optimizing itself out. Sad. :( */ 08241 ast_hangup(tmpchan); 08242 tmpchan = NULL; 08243 res = -1; 08244 } else { 08245 ast_do_masquerade(tmpchan); 08246 /* Start the PBX going on our stolen channel */ 08247 if (ast_pbx_start(tmpchan)) { 08248 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08249 ast_hangup(tmpchan); 08250 res = -1; 08251 } 08252 } 08253 08254 return res; 08255 }
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 8257 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08258 { 08259 struct ast_channel *chan; 08260 int res = -1; 08261 08262 if ((chan = ast_channel_get_by_name(channame))) { 08263 res = ast_async_goto(chan, context, exten, priority); 08264 chan = ast_channel_unref(chan); 08265 } 08266 08267 return res; 08268 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10575 of file pbx.c.
References __ast_goto_if_exists().
10576 { 10577 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10578 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10640 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10641 { 10642 return pbx_parseable_goto(chan, goto_string, 1); 10643 }
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 7758 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().
07759 { 07760 char *info; 07761 int j, num_fields, last_sep = -1; 07762 07763 /* Check for empty just in case */ 07764 if (ast_strlen_zero(info_in)) { 07765 return 0; 07766 } 07767 07768 /* make a copy just in case we were passed a static string */ 07769 info = ast_strdupa(info_in); 07770 07771 /* count the number of fields in the timespec */ 07772 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07773 if (info[j] == ',') { 07774 last_sep = j; 07775 num_fields++; 07776 } 07777 } 07778 07779 /* save the timezone, if it is specified */ 07780 if (num_fields == 5) { 07781 i->timezone = ast_strdup(info + last_sep + 1); 07782 } else { 07783 i->timezone = NULL; 07784 } 07785 07786 /* Assume everything except time */ 07787 i->monthmask = 0xfff; /* 12 bits */ 07788 i->daymask = 0x7fffffffU; /* 31 bits */ 07789 i->dowmask = 0x7f; /* 7 bits */ 07790 /* on each call, use strsep() to move info to the next argument */ 07791 get_timerange(i, strsep(&info, "|,")); 07792 if (info) 07793 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07794 if (info) 07795 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07796 if (info) 07797 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07798 return 1; 07799 }
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 4892 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
04893 { 04894 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04895 }
Change hint for an extension.
Definition at line 4805 of file pbx.c.
References ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_hint::exten, hints, and OBJ_UNLINK.
04806 { 04807 struct ast_hint *hint; 04808 04809 if (!oe || !ne) { 04810 return -1; 04811 } 04812 04813 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */ 04814 04815 /* 04816 * Unlink the hint from the hints container as the extension 04817 * name (which is the hash value) could change. 04818 */ 04819 hint = ao2_find(hints, oe, OBJ_UNLINK); 04820 if (!hint) { 04821 ao2_unlock(hints); 04822 return -1; 04823 } 04824 04825 /* Update the hint and put it back in the hints container. */ 04826 ao2_lock(hint); 04827 hint->exten = ne; 04828 ao2_unlock(hint); 04829 ao2_link(hints, hint); 04830 04831 ao2_unlock(hints); 04832 ao2_ref(hint, -1); 04833 04834 return 0; 04835 }
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 7801 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07802 { 07803 return ast_check_timing2(i, ast_tvnow()); 07804 }
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 7806 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().
07807 { 07808 struct ast_tm tm; 07809 07810 ast_localtime(&tv, &tm, i->timezone); 07811 07812 /* If it's not the right month, return */ 07813 if (!(i->monthmask & (1 << tm.tm_mon))) 07814 return 0; 07815 07816 /* If it's not that time of the month.... */ 07817 /* Warning, tm_mday has range 1..31! */ 07818 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07819 return 0; 07820 07821 /* If it's not the right day of the week */ 07822 if (!(i->dowmask & (1 << tm.tm_wday))) 07823 return 0; 07824 07825 /* Sanity check the hour just to be safe */ 07826 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07827 ast_log(LOG_WARNING, "Insane time...\n"); 07828 return 0; 07829 } 07830 07831 /* Now the tough part, we calculate if it fits 07832 in the right time based on min/hour */ 07833 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)))) 07834 return 0; 07835 07836 /* If we got this far, then we're good */ 07837 return 1; 07838 }
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 10645 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().
10646 { 10647 struct ast_app *app = NULL; 10648 int which = 0; 10649 char *ret = NULL; 10650 size_t wordlen = strlen(word); 10651 10652 AST_RWLIST_RDLOCK(&apps); 10653 AST_RWLIST_TRAVERSE(&apps, app, list) { 10654 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10655 ret = ast_strdup(app->name); 10656 break; 10657 } 10658 } 10659 AST_RWLIST_UNLOCK(&apps); 10660 10661 return ret; 10662 }
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 8042 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08043 { 08044 int ret = -1; 08045 struct ast_context *c; 08046 08047 c = find_context_locked(context); 08048 if (c) { 08049 ret = ast_context_add_ignorepat2(c, value, registrar); 08050 ast_unlock_contexts(); 08051 } 08052 return ret; 08053 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 8055 of file pbx.c.
References ast_calloc, ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().
08056 { 08057 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08058 int length; 08059 char *pattern; 08060 length = sizeof(struct ast_ignorepat); 08061 length += strlen(value) + 1; 08062 if (!(ignorepat = ast_calloc(1, length))) 08063 return -1; 08064 /* The cast to char * is because we need to write the initial value. 08065 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08066 * sees the cast as dereferencing a type-punned pointer and warns about 08067 * it. This is the workaround (we're telling gcc, yes, that's really 08068 * what we wanted to do). 08069 */ 08070 pattern = (char *) ignorepat->pattern; 08071 strcpy(pattern, value); 08072 ignorepat->next = NULL; 08073 ignorepat->registrar = registrar; 08074 ast_wrlock_context(con); 08075 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08076 ignorepatl = ignorepatc; 08077 if (!strcasecmp(ignorepatc->pattern, value)) { 08078 /* Already there */ 08079 ast_unlock_context(con); 08080 ast_free(ignorepat); 08081 errno = EEXIST; 08082 return -1; 08083 } 08084 } 08085 if (ignorepatl) 08086 ignorepatl->next = ignorepat; 08087 else 08088 con->ignorepats = ignorepat; 08089 ast_unlock_context(con); 08090 return 0; 08091 08092 }
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 7586 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07587 { 07588 int ret = -1; 07589 struct ast_context *c; 07590 07591 c = find_context_locked(context); 07592 if (c) { 07593 ret = ast_context_add_include2(c, include, registrar); 07594 ast_unlock_contexts(); 07595 } 07596 return ret; 07597 }
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 7855 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().
07857 { 07858 struct ast_include *new_include; 07859 char *c; 07860 struct ast_include *i, *il = NULL; /* include, include_last */ 07861 int length; 07862 char *p; 07863 07864 length = sizeof(struct ast_include); 07865 length += 2 * (strlen(value) + 1); 07866 07867 /* allocate new include structure ... */ 07868 if (!(new_include = ast_calloc(1, length))) 07869 return -1; 07870 /* Fill in this structure. Use 'p' for assignments, as the fields 07871 * in the structure are 'const char *' 07872 */ 07873 p = new_include->stuff; 07874 new_include->name = p; 07875 strcpy(p, value); 07876 p += strlen(value) + 1; 07877 new_include->rname = p; 07878 strcpy(p, value); 07879 /* Strip off timing info, and process if it is there */ 07880 if ( (c = strchr(p, ',')) ) { 07881 *c++ = '\0'; 07882 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07883 } 07884 new_include->next = NULL; 07885 new_include->registrar = registrar; 07886 07887 ast_wrlock_context(con); 07888 07889 /* ... go to last include and check if context is already included too... */ 07890 for (i = con->includes; i; i = i->next) { 07891 if (!strcasecmp(i->name, new_include->name)) { 07892 ast_destroy_timing(&(new_include->timing)); 07893 ast_free(new_include); 07894 ast_unlock_context(con); 07895 errno = EEXIST; 07896 return -1; 07897 } 07898 il = i; 07899 } 07900 07901 /* ... include new context into context list, unlock, return */ 07902 if (il) 07903 il->next = new_include; 07904 else 07905 con->includes = new_include; 07906 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07907 07908 ast_unlock_context(con); 07909 07910 return 0; 07911 }
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 7918 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07919 { 07920 int ret = -1; 07921 struct ast_context *c; 07922 07923 c = find_context_locked(context); 07924 if (c) { /* found, add switch to this context */ 07925 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07926 ast_unlock_contexts(); 07927 } 07928 return ret; 07929 }
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 7938 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().
07940 { 07941 struct ast_sw *new_sw; 07942 struct ast_sw *i; 07943 int length; 07944 char *p; 07945 07946 length = sizeof(struct ast_sw); 07947 length += strlen(value) + 1; 07948 if (data) 07949 length += strlen(data); 07950 length++; 07951 07952 /* allocate new sw structure ... */ 07953 if (!(new_sw = ast_calloc(1, length))) 07954 return -1; 07955 /* ... fill in this structure ... */ 07956 p = new_sw->stuff; 07957 new_sw->name = p; 07958 strcpy(new_sw->name, value); 07959 p += strlen(value) + 1; 07960 new_sw->data = p; 07961 if (data) { 07962 strcpy(new_sw->data, data); 07963 p += strlen(data) + 1; 07964 } else { 07965 strcpy(new_sw->data, ""); 07966 p++; 07967 } 07968 new_sw->eval = eval; 07969 new_sw->registrar = registrar; 07970 07971 /* ... try to lock this context ... */ 07972 ast_wrlock_context(con); 07973 07974 /* ... go to last sw and check if context is already swd too... */ 07975 AST_LIST_TRAVERSE(&con->alts, i, list) { 07976 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07977 ast_free(new_sw); 07978 ast_unlock_context(con); 07979 errno = EEXIST; 07980 return -1; 07981 } 07982 } 07983 07984 /* ... sw new context into context list, unlock, return */ 07985 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07986 07987 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07988 07989 ast_unlock_context(con); 07990 07991 return 0; 07992 }
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 9302 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().
09303 { 09304 ast_wrlock_contexts(); 09305 __ast_context_destroy(contexts, contexts_table, con,registrar); 09306 ast_unlock_contexts(); 09307 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2673 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().
02674 { 02675 struct ast_context *tmp; 02676 struct fake_context item; 02677 02678 if (!name) { 02679 return NULL; 02680 } 02681 ast_rdlock_contexts(); 02682 if (contexts_table) { 02683 ast_copy_string(item.name, name, sizeof(item.name)); 02684 tmp = ast_hashtab_lookup(contexts_table, &item); 02685 } else { 02686 tmp = NULL; 02687 while ((tmp = ast_walk_contexts(tmp))) { 02688 if (!strcasecmp(name, tmp->name)) { 02689 break; 02690 } 02691 } 02692 } 02693 ast_unlock_contexts(); 02694 return tmp; 02695 }
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 7185 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().
07186 { 07187 struct ast_context *tmp, **local_contexts; 07188 struct fake_context search; 07189 int length = sizeof(struct ast_context) + strlen(name) + 1; 07190 07191 if (!contexts_table) { 07192 /* Protect creation of contexts_table from reentrancy. */ 07193 ast_wrlock_contexts(); 07194 if (!contexts_table) { 07195 contexts_table = ast_hashtab_create(17, 07196 ast_hashtab_compare_contexts, 07197 ast_hashtab_resize_java, 07198 ast_hashtab_newsize_java, 07199 ast_hashtab_hash_contexts, 07200 0); 07201 } 07202 ast_unlock_contexts(); 07203 } 07204 07205 ast_copy_string(search.name, name, sizeof(search.name)); 07206 if (!extcontexts) { 07207 ast_rdlock_contexts(); 07208 local_contexts = &contexts; 07209 tmp = ast_hashtab_lookup(contexts_table, &search); 07210 ast_unlock_contexts(); 07211 if (tmp) { 07212 tmp->refcount++; 07213 return tmp; 07214 } 07215 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07216 local_contexts = extcontexts; 07217 tmp = ast_hashtab_lookup(exttable, &search); 07218 if (tmp) { 07219 tmp->refcount++; 07220 return tmp; 07221 } 07222 } 07223 07224 if ((tmp = ast_calloc(1, length))) { 07225 ast_rwlock_init(&tmp->lock); 07226 ast_mutex_init(&tmp->macrolock); 07227 strcpy(tmp->name, name); 07228 tmp->root = NULL; 07229 tmp->root_table = NULL; 07230 tmp->registrar = ast_strdup(registrar); 07231 tmp->includes = NULL; 07232 tmp->ignorepats = NULL; 07233 tmp->refcount = 1; 07234 } else { 07235 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07236 return NULL; 07237 } 07238 07239 if (!extcontexts) { 07240 ast_wrlock_contexts(); 07241 tmp->next = *local_contexts; 07242 *local_contexts = tmp; 07243 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07244 ast_unlock_contexts(); 07245 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07246 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07247 } else { 07248 tmp->next = *local_contexts; 07249 if (exttable) 07250 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07251 07252 *local_contexts = tmp; 07253 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07254 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07255 } 07256 return tmp; 07257 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 5783 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05784 { 05785 struct ast_context *c; 05786 int ret = -1; 05787 05788 c = find_context_locked(context); 05789 if (c) { 05790 ast_unlock_contexts(); 05791 05792 /* if we found context, lock macrolock */ 05793 ret = ast_mutex_lock(&c->macrolock); 05794 } 05795 05796 return ret; 05797 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
Definition at line 5588 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().
05589 { 05590 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05591 }
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 5618 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
05619 { 05620 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05621 }
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 5593 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().
05594 { 05595 int ret = -1; /* default error return */ 05596 struct ast_context *c; 05597 05598 c = find_context_locked(context); 05599 if (c) { /* ... remove extension ... */ 05600 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 05601 matchcallerid, registrar, 0); 05602 ast_unlock_contexts(); 05603 } 05604 05605 return ret; 05606 }
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 5623 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().
05624 { 05625 struct ast_exten *exten, *prev_exten = NULL; 05626 struct ast_exten *peer; 05627 struct ast_exten ex, *exten2, *exten3; 05628 char dummy_name[1024]; 05629 struct ast_exten *previous_peer = NULL; 05630 struct ast_exten *next_peer = NULL; 05631 int found = 0; 05632 05633 if (!already_locked) 05634 ast_wrlock_context(con); 05635 05636 /* Handle this is in the new world */ 05637 05638 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05639 * peers, not just those matching the callerid. */ 05640 #ifdef NEED_DEBUG 05641 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05642 #endif 05643 #ifdef CONTEXT_DEBUG 05644 check_contexts(__FILE__, __LINE__); 05645 #endif 05646 /* find this particular extension */ 05647 ex.exten = dummy_name; 05648 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05649 ex.cidmatch = callerid; 05650 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05651 exten = ast_hashtab_lookup(con->root_table, &ex); 05652 if (exten) { 05653 if (priority == 0) { 05654 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05655 if (!exten2) 05656 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); 05657 if (con->pattern_tree) { 05658 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05659 05660 if (x->exten) { /* this test for safety purposes */ 05661 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05662 x->exten = 0; /* get rid of what will become a bad pointer */ 05663 } else { 05664 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05665 } 05666 } 05667 } else { 05668 ex.priority = priority; 05669 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05670 if (exten2) { 05671 05672 if (exten2->label) { /* if this exten has a label, remove that, too */ 05673 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05674 if (!exten3) 05675 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); 05676 } 05677 05678 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05679 if (!exten3) 05680 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); 05681 if (exten2 == exten && exten2->peer) { 05682 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05683 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05684 } 05685 if (ast_hashtab_size(exten->peer_table) == 0) { 05686 /* well, if the last priority of an exten is to be removed, 05687 then, the extension is removed, too! */ 05688 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05689 if (!exten3) 05690 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05691 if (con->pattern_tree) { 05692 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05693 if (x->exten) { /* this test for safety purposes */ 05694 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05695 x->exten = 0; /* get rid of what will become a bad pointer */ 05696 } 05697 } 05698 } 05699 } else { 05700 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05701 priority, exten->exten, con->name); 05702 } 05703 } 05704 } else { 05705 /* hmmm? this exten is not in this pattern tree? */ 05706 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05707 extension, con->name); 05708 } 05709 #ifdef NEED_DEBUG 05710 if (con->pattern_tree) { 05711 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05712 log_match_char_tree(con->pattern_tree, " "); 05713 } 05714 #endif 05715 05716 /* scan the extension list to find first matching extension-registrar */ 05717 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05718 if (!strcmp(exten->exten, extension) && 05719 (!registrar || !strcmp(exten->registrar, registrar)) && 05720 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05721 break; 05722 } 05723 if (!exten) { 05724 /* we can't find right extension */ 05725 if (!already_locked) 05726 ast_unlock_context(con); 05727 return -1; 05728 } 05729 05730 /* scan the priority list to remove extension with exten->priority == priority */ 05731 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05732 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))); 05733 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05734 if ((priority == 0 || peer->priority == priority) && 05735 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05736 (!registrar || !strcmp(peer->registrar, registrar) )) { 05737 found = 1; 05738 05739 /* we are first priority extension? */ 05740 if (!previous_peer) { 05741 /* 05742 * We are first in the priority chain, so must update the extension chain. 05743 * The next node is either the next priority or the next extension 05744 */ 05745 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05746 if (peer->peer) { 05747 /* move the peer_table and peer_label_table down to the next peer, if 05748 it is there */ 05749 peer->peer->peer_table = peer->peer_table; 05750 peer->peer->peer_label_table = peer->peer_label_table; 05751 peer->peer_table = NULL; 05752 peer->peer_label_table = NULL; 05753 } 05754 if (!prev_exten) { /* change the root... */ 05755 con->root = next_node; 05756 } else { 05757 prev_exten->next = next_node; /* unlink */ 05758 } 05759 if (peer->peer) { /* update the new head of the pri list */ 05760 peer->peer->next = peer->next; 05761 } 05762 } else { /* easy, we are not first priority in extension */ 05763 previous_peer->peer = peer->peer; 05764 } 05765 05766 /* now, free whole priority extension */ 05767 destroy_exten(peer); 05768 } else { 05769 previous_peer = peer; 05770 } 05771 } 05772 if (!already_locked) 05773 ast_unlock_context(con); 05774 return found ? 0 : -1; 05775 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7998 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07999 { 08000 int ret = -1; 08001 struct ast_context *c; 08002 08003 c = find_context_locked(context); 08004 if (c) { 08005 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08006 ast_unlock_contexts(); 08007 } 08008 return ret; 08009 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8011 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().
08012 { 08013 struct ast_ignorepat *ip, *ipl = NULL; 08014 08015 ast_wrlock_context(con); 08016 08017 for (ip = con->ignorepats; ip; ip = ip->next) { 08018 if (!strcmp(ip->pattern, ignorepat) && 08019 (!registrar || (registrar == ip->registrar))) { 08020 if (ipl) { 08021 ipl->next = ip->next; 08022 ast_free(ip); 08023 } else { 08024 con->ignorepats = ip->next; 08025 ast_free(ip); 08026 } 08027 ast_unlock_context(con); 08028 return 0; 08029 } 08030 ipl = ip; 08031 } 08032 08033 ast_unlock_context(con); 08034 errno = EINVAL; 08035 return -1; 08036 }
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 5481 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05482 { 05483 int ret = -1; 05484 struct ast_context *c; 05485 05486 c = find_context_locked(context); 05487 if (c) { 05488 /* found, remove include from this context ... */ 05489 ret = ast_context_remove_include2(c, include, registrar); 05490 ast_unlock_contexts(); 05491 } 05492 return ret; 05493 }
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 5504 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().
05505 { 05506 struct ast_include *i, *pi = NULL; 05507 int ret = -1; 05508 05509 ast_wrlock_context(con); 05510 05511 /* find our include */ 05512 for (i = con->includes; i; pi = i, i = i->next) { 05513 if (!strcmp(i->name, include) && 05514 (!registrar || !strcmp(i->registrar, registrar))) { 05515 /* remove from list */ 05516 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05517 if (pi) 05518 pi->next = i->next; 05519 else 05520 con->includes = i->next; 05521 /* free include and return */ 05522 ast_destroy_timing(&(i->timing)); 05523 ast_free(i); 05524 ret = 0; 05525 break; 05526 } 05527 } 05528 05529 ast_unlock_context(con); 05530 05531 return ret; 05532 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 5539 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05540 { 05541 int ret = -1; /* default error return */ 05542 struct ast_context *c; 05543 05544 c = find_context_locked(context); 05545 if (c) { 05546 /* remove switch from this context ... */ 05547 ret = ast_context_remove_switch2(c, sw, data, registrar); 05548 ast_unlock_contexts(); 05549 } 05550 return ret; 05551 }
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 5561 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().
05562 { 05563 struct ast_sw *i; 05564 int ret = -1; 05565 05566 ast_wrlock_context(con); 05567 05568 /* walk switches */ 05569 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05570 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05571 (!registrar || !strcmp(i->registrar, registrar))) { 05572 /* found, remove from list */ 05573 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05574 AST_LIST_REMOVE_CURRENT(list); 05575 ast_free(i); /* free switch and return */ 05576 ret = 0; 05577 break; 05578 } 05579 } 05580 AST_LIST_TRAVERSE_SAFE_END; 05581 05582 ast_unlock_context(con); 05583 05584 return ret; 05585 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5804 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05805 { 05806 struct ast_context *c; 05807 int ret = -1; 05808 05809 c = find_context_locked(context); 05810 if (c) { 05811 ast_unlock_contexts(); 05812 05813 /* if we found context, unlock macrolock */ 05814 ret = ast_mutex_unlock(&c->macrolock); 05815 } 05816 05817 return ret; 05818 }
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 10530 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().
10531 { 10532 struct ast_include *inc = NULL; 10533 int res = 0; 10534 10535 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10536 if (ast_context_find(inc->rname)) 10537 continue; 10538 10539 res = -1; 10540 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10541 ast_get_context_name(con), inc->rname); 10542 break; 10543 } 10544 10545 return res; 10546 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 3502 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().
03503 { 03504 struct ast_custom_function *acf = NULL; 03505 03506 AST_RWLIST_RDLOCK(&acf_root); 03507 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03508 if (!strcmp(name, acf->name)) 03509 break; 03510 } 03511 AST_RWLIST_UNLOCK(&acf_root); 03512 03513 return acf; 03514 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3516 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().
03517 { 03518 struct ast_custom_function *cur; 03519 03520 if (!acf) { 03521 return -1; 03522 } 03523 03524 AST_RWLIST_WRLOCK(&acf_root); 03525 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03526 #ifdef AST_XML_DOCS 03527 if (cur->docsrc == AST_XML_DOC) { 03528 ast_string_field_free_memory(acf); 03529 } 03530 #endif 03531 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03532 } 03533 AST_RWLIST_UNLOCK(&acf_root); 03534 03535 return cur ? 0 : -1; 03536 }
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 7840 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().
07841 { 07842 if (i->timezone) { 07843 ast_free(i->timezone); 07844 i->timezone = NULL; 07845 } 07846 return 0; 07847 }
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 4325 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().
04326 { 04327 switch (devstate) { 04328 case AST_DEVICE_ONHOLD: 04329 return AST_EXTENSION_ONHOLD; 04330 case AST_DEVICE_BUSY: 04331 return AST_EXTENSION_BUSY; 04332 case AST_DEVICE_UNKNOWN: 04333 return AST_EXTENSION_NOT_INUSE; 04334 case AST_DEVICE_UNAVAILABLE: 04335 case AST_DEVICE_INVALID: 04336 return AST_EXTENSION_UNAVAILABLE; 04337 case AST_DEVICE_RINGINUSE: 04338 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04339 case AST_DEVICE_RINGING: 04340 return AST_EXTENSION_RINGING; 04341 case AST_DEVICE_INUSE: 04342 return AST_EXTENSION_INUSE; 04343 case AST_DEVICE_NOT_INUSE: 04344 return AST_EXTENSION_NOT_INUSE; 04345 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04346 break; 04347 } 04348 04349 return AST_EXTENSION_NOT_INUSE; 04350 }
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 4877 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_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().
04878 { 04879 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04880 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8152 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().
08153 { 08154 if (!chan) 08155 return -1; 08156 08157 ast_channel_lock(chan); 08158 08159 if (!ast_strlen_zero(context)) 08160 ast_copy_string(chan->context, context, sizeof(chan->context)); 08161 if (!ast_strlen_zero(exten)) 08162 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08163 if (priority > -1) { 08164 chan->priority = priority; 08165 /* see flag description in channel.h for explanation */ 08166 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08167 chan->priority--; 08168 } 08169 08170 ast_channel_unlock(chan); 08171 08172 return 0; 08173 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2650 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().
02651 { 02652 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02653 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02654 return extension_match_core(pattern, data, needmore); 02655 }
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 2452 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02453 { 02454 return ext_cmp(a, b); 02455 }
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 2645 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().
02646 { 02647 return extension_match_core(pattern, data, E_MATCH); 02648 }
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 4395 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().
04396 { 04397 struct ast_exten *e; 04398 04399 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04400 return -1; /* No hint, return -1 */ 04401 } 04402 04403 if (e->exten[0] == '_') { 04404 /* Create this hint on-the-fly */ 04405 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04406 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04407 e->registrar); 04408 if (!(e = ast_hint_extension(c, context, exten))) { 04409 /* Improbable, but not impossible */ 04410 return -1; 04411 } 04412 } 04413 04414 return ast_extension_state2(e); /* Check all devices in the hint */ 04415 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4370 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().
04371 { 04372 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32); 04373 04374 if (!e || !hint_app) { 04375 return -1; 04376 } 04377 04378 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e)); 04379 return ast_extension_state3(hint_app); 04380 }
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 4383 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().
04384 { 04385 int i; 04386 04387 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04388 if (extension_states[i].extension_state == extension_state) 04389 return extension_states[i].text; 04390 } 04391 return "Unknown"; 04392 }
static int ast_extension_state3 | ( | struct ast_str * | hint_app | ) | [static] |
Definition at line 4352 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().
04353 { 04354 char *cur; 04355 char *rest; 04356 struct ast_devstate_aggregate agg; 04357 04358 /* One or more devices separated with a & character */ 04359 rest = ast_str_buffer(hint_app); 04360 04361 ast_devstate_aggregate_init(&agg); 04362 while ((cur = strsep(&rest, "&"))) { 04363 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04364 } 04365 04366 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04367 }
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 4616 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
04618 { 04619 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 04620 }
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 4529 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().
04531 { 04532 struct ast_hint *hint; 04533 struct ast_state_cb *state_cb; 04534 struct ast_exten *e; 04535 int id; 04536 04537 /* If there's no context and extension: add callback to statecbs list */ 04538 if (!context && !exten) { 04539 /* Prevent multiple adds from adding the same change_cb at the same time. */ 04540 ao2_lock(statecbs); 04541 04542 /* Remove any existing change_cb. */ 04543 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 04544 04545 /* Now insert the change_cb */ 04546 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04547 ao2_unlock(statecbs); 04548 return -1; 04549 } 04550 state_cb->id = 0; 04551 state_cb->change_cb = change_cb; 04552 state_cb->destroy_cb = destroy_cb; 04553 state_cb->data = data; 04554 ao2_link(statecbs, state_cb); 04555 04556 ao2_ref(state_cb, -1); 04557 ao2_unlock(statecbs); 04558 return 0; 04559 } 04560 04561 if (!context || !exten) 04562 return -1; 04563 04564 /* This callback type is for only one hint, so get the hint */ 04565 e = ast_hint_extension(NULL, context, exten); 04566 if (!e) { 04567 return -1; 04568 } 04569 04570 /* If this is a pattern, dynamically create a new extension for this 04571 * particular match. Note that this will only happen once for each 04572 * individual extension, because the pattern will no longer match first. 04573 */ 04574 if (e->exten[0] == '_') { 04575 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04576 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04577 e->registrar); 04578 e = ast_hint_extension(NULL, context, exten); 04579 if (!e || e->exten[0] == '_') { 04580 return -1; 04581 } 04582 } 04583 04584 /* Find the hint in the hints container */ 04585 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04586 hint = ao2_find(hints, e, 0); 04587 if (!hint) { 04588 ao2_unlock(hints); 04589 return -1; 04590 } 04591 04592 /* Now insert the callback in the callback list */ 04593 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04594 ao2_ref(hint, -1); 04595 ao2_unlock(hints); 04596 return -1; 04597 } 04598 do { 04599 id = stateid++; /* Unique ID for this callback */ 04600 /* Do not allow id to ever be -1 or 0. */ 04601 } while (id == -1 || id == 0); 04602 state_cb->id = id; 04603 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 04604 state_cb->destroy_cb = destroy_cb; 04605 state_cb->data = data; /* Data for the callback */ 04606 ao2_link(hint->callbacks, state_cb); 04607 04608 ao2_ref(state_cb, -1); 04609 ao2_ref(hint, -1); 04610 ao2_unlock(hints); 04611 04612 return id; 04613 }
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 4638 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().
04639 { 04640 struct ast_state_cb *p_cur; 04641 int ret = -1; 04642 04643 if (!id) { /* id == 0 is a callback without extension */ 04644 if (!change_cb) { 04645 return ret; 04646 } 04647 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 04648 if (p_cur) { 04649 ret = 0; 04650 ao2_ref(p_cur, -1); 04651 } 04652 } else { /* callback with extension, find the callback based on ID */ 04653 struct ast_hint *hint; 04654 04655 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04656 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04657 if (hint) { 04658 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04659 if (p_cur) { 04660 ret = 0; 04661 ao2_ref(p_cur, -1); 04662 } 04663 ao2_ref(hint, -1); 04664 } 04665 ao2_unlock(hints); 04666 } 04667 04668 return ret; 04669 }
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 4882 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().
04883 { 04884 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04885 }
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 4887 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
04888 { 04889 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04890 }
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 3660 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().
03661 { 03662 char *copy = ast_strdupa(function); 03663 char *args = func_args(copy); 03664 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03665 int res; 03666 struct ast_module_user *u = NULL; 03667 03668 if (acfptr == NULL) { 03669 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03670 } else if (!acfptr->read && !acfptr->read2) { 03671 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03672 } else if (acfptr->read) { 03673 if (acfptr->mod) { 03674 u = __ast_module_user_add(acfptr->mod, chan); 03675 } 03676 res = acfptr->read(chan, copy, args, workspace, len); 03677 if (acfptr->mod && u) { 03678 __ast_module_user_remove(acfptr->mod, u); 03679 } 03680 return res; 03681 } else { 03682 struct ast_str *str = ast_str_create(16); 03683 if (acfptr->mod) { 03684 u = __ast_module_user_add(acfptr->mod, chan); 03685 } 03686 res = acfptr->read2(chan, copy, args, &str, 0); 03687 if (acfptr->mod && u) { 03688 __ast_module_user_remove(acfptr->mod, u); 03689 } 03690 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03691 ast_free(str); 03692 return res; 03693 } 03694 return -1; 03695 }
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 3697 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().
03698 { 03699 char *copy = ast_strdupa(function); 03700 char *args = func_args(copy); 03701 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03702 int res; 03703 struct ast_module_user *u = NULL; 03704 03705 if (acfptr == NULL) { 03706 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03707 } else if (!acfptr->read && !acfptr->read2) { 03708 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03709 } else { 03710 if (acfptr->mod) { 03711 u = __ast_module_user_add(acfptr->mod, chan); 03712 } 03713 ast_str_reset(*str); 03714 if (acfptr->read2) { 03715 /* ast_str enabled */ 03716 res = acfptr->read2(chan, copy, args, str, maxlen); 03717 } else { 03718 /* Legacy function pointer, allocate buffer for result */ 03719 int maxsize = ast_str_size(*str); 03720 if (maxlen > -1) { 03721 if (maxlen == 0) { 03722 if (acfptr->read_max) { 03723 maxsize = acfptr->read_max; 03724 } else { 03725 maxsize = VAR_BUF_SIZE; 03726 } 03727 } else { 03728 maxsize = maxlen; 03729 } 03730 ast_str_make_space(str, maxsize); 03731 } 03732 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03733 } 03734 if (acfptr->mod && u) { 03735 __ast_module_user_remove(acfptr->mod, u); 03736 } 03737 return res; 03738 } 03739 return -1; 03740 }
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 3742 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().
03743 { 03744 char *copy = ast_strdupa(function); 03745 char *args = func_args(copy); 03746 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03747 03748 if (acfptr == NULL) 03749 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03750 else if (!acfptr->write) 03751 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03752 else { 03753 int res; 03754 struct ast_module_user *u = NULL; 03755 if (acfptr->mod) 03756 u = __ast_module_user_add(acfptr->mod, chan); 03757 res = acfptr->write(chan, copy, args, value); 03758 if (acfptr->mod && u) 03759 __ast_module_user_remove(acfptr->mod, u); 03760 return res; 03761 } 03762 03763 return -1; 03764 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10382 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().
10383 { 10384 return con ? con->name : NULL; 10385 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10420 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10421 { 10422 return c ? c->registrar : NULL; 10423 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10450 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().
10451 { 10452 return e ? e->app : NULL; 10453 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10455 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().
10456 { 10457 return e ? e->data : NULL; 10458 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10445 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10446 { 10447 return e ? e->cidmatch : NULL; 10448 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 10387 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 10397 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 10440 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10441 { 10442 return e ? e->matchcid : 0; 10443 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10392 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 10412 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 10425 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10426 { 10427 return e ? e->registrar : NULL; 10428 }
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 4839 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().
04840 { 04841 struct ast_exten *e = ast_hint_extension(c, context, exten); 04842 04843 if (e) { 04844 if (hint) 04845 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04846 if (name) { 04847 const char *tmp = ast_get_extension_app_data(e); 04848 if (tmp) 04849 ast_copy_string(name, tmp, namesize); 04850 } 04851 return -1; 04852 } 04853 return 0; 04854 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10407 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().
10408 { 10409 return ip ? ip->pattern : NULL; 10410 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10435 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().
10436 { 10437 return ip ? ip->registrar : NULL; 10438 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 10402 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().
10403 { 10404 return inc ? inc->name : NULL; 10405 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 10430 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().
10431 { 10432 return i ? i->registrar : NULL; 10433 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10465 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().
10466 { 10467 return sw ? sw->data : NULL; 10468 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10470 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10471 { 10472 return sw->eval; 10473 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10460 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().
10461 { 10462 return sw ? sw->name : NULL; 10463 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10475 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().
10476 { 10477 return sw ? sw->registrar : NULL; 10478 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10570 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10571 { 10572 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10573 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1081 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01082 { 01083 const struct ast_context *ac = ah_a; 01084 const struct ast_context *bc = ah_b; 01085 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01086 return 1; 01087 /* assume context names are registered in a string table! */ 01088 return strcmp(ac->name, bc->name); 01089 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1124 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().
01125 { 01126 const struct ast_context *ac = obj; 01127 return ast_hashtab_hash_string(ac->name); 01128 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
Definition at line 4316 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().
04317 { 04318 struct ast_exten *e; 04319 ast_rdlock_contexts(); 04320 e = ast_hint_extension_nolock(c, context, exten); 04321 ast_unlock_contexts(); 04322 return e; 04323 }
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 4310 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().
04311 { 04312 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04313 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04314 }
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 8094 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().
08095 { 08096 struct ast_context *con = ast_context_find(context); 08097 08098 if (con) { 08099 struct ast_ignorepat *pat; 08100 08101 for (pat = con->ignorepats; pat; pat = pat->next) { 08102 if (ast_extension_match(pat->pattern, pattern)) 08103 return 1; 08104 } 08105 } 08106 08107 return 0; 08108 }
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 4897 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(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_ss_thread(), readexten_exec(), and skinny_ss().
04898 { 04899 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04900 }
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 7391 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().
07392 { 07393 double ft; 07394 struct ast_context *tmp; 07395 struct ast_context *oldcontextslist; 07396 struct ast_hashtab *oldtable; 07397 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07398 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07399 struct store_hint *saved_hint; 07400 struct ast_hint *hint; 07401 struct ast_exten *exten; 07402 int length; 07403 struct ast_state_cb *thiscb; 07404 struct ast_hashtab_iter *iter; 07405 struct ao2_iterator i; 07406 struct timeval begintime; 07407 struct timeval writelocktime; 07408 struct timeval endlocktime; 07409 struct timeval enddeltime; 07410 07411 /* 07412 * It is very important that this function hold the hints 07413 * container lock _and_ the conlock during its operation; not 07414 * only do we need to ensure that the list of contexts and 07415 * extensions does not change, but also that no hint callbacks 07416 * (watchers) are added or removed during the merge/delete 07417 * process 07418 * 07419 * In addition, the locks _must_ be taken in this order, because 07420 * there are already other code paths that use this order 07421 */ 07422 07423 begintime = ast_tvnow(); 07424 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07425 ast_wrlock_contexts(); 07426 iter = ast_hashtab_start_traversal(contexts_table); 07427 while ((tmp = ast_hashtab_next(iter))) { 07428 context_merge(extcontexts, exttable, tmp, registrar); 07429 } 07430 ast_hashtab_end_traversal(iter); 07431 07432 ao2_lock(hints); 07433 writelocktime = ast_tvnow(); 07434 07435 /* preserve all watchers for hints */ 07436 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07437 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07438 if (ao2_container_count(hint->callbacks)) { 07439 ao2_lock(hint); 07440 if (!hint->exten) { 07441 /* The extension has already been destroyed. (Should never happen here) */ 07442 ao2_unlock(hint); 07443 continue; 07444 } 07445 07446 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07447 + sizeof(*saved_hint); 07448 if (!(saved_hint = ast_calloc(1, length))) { 07449 ao2_unlock(hint); 07450 continue; 07451 } 07452 07453 /* This removes all the callbacks from the hint into saved_hint. */ 07454 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07455 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07456 /* 07457 * We intentionally do not unref thiscb to account for the 07458 * non-ao2 reference in saved_hint->callbacks 07459 */ 07460 } 07461 07462 saved_hint->laststate = hint->laststate; 07463 saved_hint->context = saved_hint->data; 07464 strcpy(saved_hint->data, hint->exten->parent->name); 07465 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07466 strcpy(saved_hint->exten, hint->exten->exten); 07467 ao2_unlock(hint); 07468 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07469 } 07470 } 07471 ao2_iterator_destroy(&i); 07472 07473 /* save the old table and list */ 07474 oldtable = contexts_table; 07475 oldcontextslist = contexts; 07476 07477 /* move in the new table and list */ 07478 contexts_table = exttable; 07479 contexts = *extcontexts; 07480 07481 /* 07482 * Restore the watchers for hints that can be found; notify 07483 * those that cannot be restored. 07484 */ 07485 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07486 struct pbx_find_info q = { .stacklen = 0 }; 07487 07488 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07489 PRIORITY_HINT, NULL, "", E_MATCH); 07490 /* 07491 * If this is a pattern, dynamically create a new extension for this 07492 * particular match. Note that this will only happen once for each 07493 * individual extension, because the pattern will no longer match first. 07494 */ 07495 if (exten && exten->exten[0] == '_') { 07496 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07497 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07498 exten->registrar); 07499 /* rwlocks are not recursive locks */ 07500 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07501 saved_hint->exten); 07502 } 07503 07504 /* Find the hint in the hints container */ 07505 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07506 if (!hint) { 07507 /* 07508 * Notify watchers of this removed hint later when we aren't 07509 * encumberd by so many locks. 07510 */ 07511 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07512 } else { 07513 ao2_lock(hint); 07514 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07515 ao2_link(hint->callbacks, thiscb); 07516 /* Ref that we added when putting into saved_hint->callbacks */ 07517 ao2_ref(thiscb, -1); 07518 } 07519 hint->laststate = saved_hint->laststate; 07520 ao2_unlock(hint); 07521 ao2_ref(hint, -1); 07522 ast_free(saved_hint); 07523 } 07524 } 07525 07526 ao2_unlock(hints); 07527 ast_unlock_contexts(); 07528 07529 /* 07530 * Notify watchers of all removed hints with the same lock 07531 * environment as handle_statechange(). 07532 */ 07533 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 07534 /* this hint has been removed, notify the watchers */ 07535 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07536 thiscb->change_cb(saved_hint->context, saved_hint->exten, 07537 AST_EXTENSION_REMOVED, thiscb->data); 07538 /* Ref that we added when putting into saved_hint->callbacks */ 07539 ao2_ref(thiscb, -1); 07540 } 07541 ast_free(saved_hint); 07542 } 07543 07544 ast_mutex_unlock(&context_merge_lock); 07545 endlocktime = ast_tvnow(); 07546 07547 /* 07548 * The old list and hashtab no longer are relevant, delete them 07549 * while the rest of asterisk is now freely using the new stuff 07550 * instead. 07551 */ 07552 07553 ast_hashtab_destroy(oldtable, NULL); 07554 07555 for (tmp = oldcontextslist; tmp; ) { 07556 struct ast_context *next; /* next starting point */ 07557 07558 next = tmp->next; 07559 __ast_internal_context_destroy(tmp); 07560 tmp = next; 07561 } 07562 enddeltime = ast_tvnow(); 07563 07564 ft = ast_tvdiff_us(writelocktime, begintime); 07565 ft /= 1000000.0; 07566 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07567 07568 ft = ast_tvdiff_us(endlocktime, writelocktime); 07569 ft /= 1000000.0; 07570 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07571 07572 ft = ast_tvdiff_us(enddeltime, endlocktime); 07573 ft /= 1000000.0; 07574 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07575 07576 ft = ast_tvdiff_us(enddeltime, begintime); 07577 ft /= 1000000.0; 07578 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07579 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10635 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().
10636 { 10637 return pbx_parseable_goto(chan, goto_string, 0); 10638 }
int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 10700 of file pbx.c.
References ao2_container_alloc, HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hints, statecbs, and statecbs_cmp().
Referenced by main().
10701 { 10702 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 10703 statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); 10704 10705 return (hints && statecbs) ? 0 : -1; 10706 }
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 8971 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().
08972 { 08973 struct ast_channel *chan; 08974 struct app_tmp *tmp; 08975 int res = -1, cdr_res = -1; 08976 struct outgoing_helper oh; 08977 08978 memset(&oh, 0, sizeof(oh)); 08979 oh.vars = vars; 08980 oh.account = account; 08981 08982 if (locked_channel) 08983 *locked_channel = NULL; 08984 if (ast_strlen_zero(app)) { 08985 res = -1; 08986 goto outgoing_app_cleanup; 08987 } 08988 if (synchronous) { 08989 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08990 if (chan) { 08991 ast_set_variables(chan, vars); 08992 if (account) 08993 ast_cdr_setaccount(chan, account); 08994 if (chan->_state == AST_STATE_UP) { 08995 res = 0; 08996 ast_verb(4, "Channel %s was answered.\n", chan->name); 08997 tmp = ast_calloc(1, sizeof(*tmp)); 08998 if (!tmp || ast_string_field_init(tmp, 252)) { 08999 if (tmp) { 09000 ast_free(tmp); 09001 } 09002 res = -1; 09003 } else { 09004 ast_string_field_set(tmp, app, app); 09005 ast_string_field_set(tmp, data, appdata); 09006 tmp->chan = chan; 09007 if (synchronous > 1) { 09008 if (locked_channel) 09009 ast_channel_unlock(chan); 09010 ast_pbx_run_app(tmp); 09011 } else { 09012 if (locked_channel) 09013 ast_channel_lock(chan); 09014 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09015 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09016 ast_string_field_free_memory(tmp); 09017 ast_free(tmp); 09018 if (locked_channel) 09019 ast_channel_unlock(chan); 09020 ast_hangup(chan); 09021 res = -1; 09022 } else { 09023 if (locked_channel) 09024 *locked_channel = chan; 09025 } 09026 } 09027 } 09028 } else { 09029 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09030 if (chan->cdr) { /* update the cdr */ 09031 /* here we update the status of the call, which sould be busy. 09032 * if that fails then we set the status to failed */ 09033 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09034 ast_cdr_failed(chan->cdr); 09035 } 09036 ast_hangup(chan); 09037 } 09038 } 09039 09040 if (res < 0) { /* the call failed for some reason */ 09041 if (*reason == 0) { /* if the call failed (not busy or no answer) 09042 * update the cdr with the failed message */ 09043 cdr_res = ast_pbx_outgoing_cdr_failed(); 09044 if (cdr_res != 0) { 09045 res = cdr_res; 09046 goto outgoing_app_cleanup; 09047 } 09048 } 09049 } 09050 09051 } else { 09052 struct async_stat *as; 09053 if (!(as = ast_calloc(1, sizeof(*as)))) { 09054 res = -1; 09055 goto outgoing_app_cleanup; 09056 } 09057 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09058 if (!chan) { 09059 ast_free(as); 09060 res = -1; 09061 goto outgoing_app_cleanup; 09062 } 09063 as->chan = chan; 09064 ast_copy_string(as->app, app, sizeof(as->app)); 09065 if (appdata) 09066 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09067 as->timeout = timeout; 09068 ast_set_variables(chan, vars); 09069 if (account) 09070 ast_cdr_setaccount(chan, account); 09071 /* Start a new thread, and get something handling this channel. */ 09072 if (locked_channel) 09073 ast_channel_lock(chan); 09074 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09075 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09076 ast_free(as); 09077 if (locked_channel) 09078 ast_channel_unlock(chan); 09079 ast_hangup(chan); 09080 res = -1; 09081 goto outgoing_app_cleanup; 09082 } else { 09083 if (locked_channel) 09084 *locked_channel = chan; 09085 } 09086 res = 0; 09087 } 09088 outgoing_app_cleanup: 09089 ast_variables_destroy(vars); 09090 return res; 09091 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 8775 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().
08776 { 08777 /* allocate a channel */ 08778 struct ast_channel *chan = ast_dummy_channel_alloc(); 08779 08780 if (!chan) 08781 return -1; /* failure */ 08782 08783 chan->cdr = ast_cdr_alloc(); 08784 if (!chan->cdr) { 08785 /* allocation of the cdr failed */ 08786 chan = ast_channel_unref(chan); /* free the channel */ 08787 return -1; /* return failure */ 08788 } 08789 08790 /* allocation of the cdr was successful */ 08791 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 08792 ast_cdr_start(chan->cdr); /* record the start and stop time */ 08793 ast_cdr_end(chan->cdr); 08794 ast_cdr_failed(chan->cdr); /* set the status to failed */ 08795 ast_cdr_detach(chan->cdr); /* post and free the record */ 08796 chan->cdr = NULL; 08797 chan = ast_channel_unref(chan); /* free the channel */ 08798 08799 return 0; /* success */ 08800 }
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 8802 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().
08803 { 08804 struct ast_channel *chan; 08805 struct async_stat *as; 08806 int res = -1, cdr_res = -1; 08807 struct outgoing_helper oh; 08808 08809 if (synchronous) { 08810 oh.context = context; 08811 oh.exten = exten; 08812 oh.priority = priority; 08813 oh.cid_num = cid_num; 08814 oh.cid_name = cid_name; 08815 oh.account = account; 08816 oh.vars = vars; 08817 oh.parent_channel = NULL; 08818 08819 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08820 if (channel) { 08821 *channel = chan; 08822 if (chan) 08823 ast_channel_lock(chan); 08824 } 08825 if (chan) { 08826 if (chan->_state == AST_STATE_UP) { 08827 res = 0; 08828 ast_verb(4, "Channel %s was answered.\n", chan->name); 08829 08830 if (synchronous > 1) { 08831 if (channel) 08832 ast_channel_unlock(chan); 08833 if (ast_pbx_run(chan)) { 08834 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08835 if (channel) 08836 *channel = NULL; 08837 ast_hangup(chan); 08838 chan = NULL; 08839 res = -1; 08840 } 08841 } else { 08842 if (ast_pbx_start(chan)) { 08843 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 08844 if (channel) { 08845 *channel = NULL; 08846 ast_channel_unlock(chan); 08847 } 08848 ast_hangup(chan); 08849 res = -1; 08850 } 08851 chan = NULL; 08852 } 08853 } else { 08854 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08855 08856 if (chan->cdr) { /* update the cdr */ 08857 /* here we update the status of the call, which sould be busy. 08858 * if that fails then we set the status to failed */ 08859 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08860 ast_cdr_failed(chan->cdr); 08861 } 08862 08863 if (channel) { 08864 *channel = NULL; 08865 ast_channel_unlock(chan); 08866 } 08867 ast_hangup(chan); 08868 chan = NULL; 08869 } 08870 } 08871 08872 if (res < 0) { /* the call failed for some reason */ 08873 if (*reason == 0) { /* if the call failed (not busy or no answer) 08874 * update the cdr with the failed message */ 08875 cdr_res = ast_pbx_outgoing_cdr_failed(); 08876 if (cdr_res != 0) { 08877 res = cdr_res; 08878 goto outgoing_exten_cleanup; 08879 } 08880 } 08881 08882 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08883 /* check if "failed" exists */ 08884 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08885 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 08886 if (chan) { 08887 char failed_reason[4] = ""; 08888 if (!ast_strlen_zero(context)) 08889 ast_copy_string(chan->context, context, sizeof(chan->context)); 08890 set_ext_pri(chan, "failed", 1); 08891 ast_set_variables(chan, vars); 08892 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08893 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08894 if (account) 08895 ast_cdr_setaccount(chan, account); 08896 if (ast_pbx_run(chan)) { 08897 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08898 ast_hangup(chan); 08899 } 08900 chan = NULL; 08901 } 08902 } 08903 } 08904 } else { 08905 if (!(as = ast_calloc(1, sizeof(*as)))) { 08906 res = -1; 08907 goto outgoing_exten_cleanup; 08908 } 08909 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 08910 if (channel) { 08911 *channel = chan; 08912 if (chan) 08913 ast_channel_lock(chan); 08914 } 08915 if (!chan) { 08916 ast_free(as); 08917 res = -1; 08918 goto outgoing_exten_cleanup; 08919 } 08920 as->chan = chan; 08921 ast_copy_string(as->context, context, sizeof(as->context)); 08922 set_ext_pri(as->chan, exten, priority); 08923 as->timeout = timeout; 08924 ast_set_variables(chan, vars); 08925 if (account) 08926 ast_cdr_setaccount(chan, account); 08927 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08928 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08929 ast_free(as); 08930 if (channel) { 08931 *channel = NULL; 08932 ast_channel_unlock(chan); 08933 } 08934 ast_hangup(chan); 08935 res = -1; 08936 goto outgoing_exten_cleanup; 08937 } 08938 res = 0; 08939 } 08940 outgoing_exten_cleanup: 08941 ast_variables_destroy(vars); 08942 return res; 08943 }
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 5400 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().
05401 { 05402 return ast_pbx_run_args(c, NULL); 05403 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 8955 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().
08956 { 08957 struct app_tmp *tmp = data; 08958 struct ast_app *app; 08959 app = pbx_findapp(tmp->app); 08960 if (app) { 08961 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 08962 pbx_exec(tmp->chan, app, tmp->data); 08963 } else 08964 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 08965 ast_hangup(tmp->chan); 08966 ast_string_field_free_memory(tmp); 08967 ast_free(tmp); 08968 return NULL; 08969 }
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 5380 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().
05381 { 05382 enum ast_pbx_result res = AST_PBX_SUCCESS; 05383 05384 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05385 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05386 return AST_PBX_FAILED; 05387 } 05388 05389 if (increase_call_count(c)) { 05390 return AST_PBX_CALL_LIMIT; 05391 } 05392 05393 res = __ast_pbx_run(c, args); 05394 05395 decrease_call_count(); 05396 05397 return res; 05398 }
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 5353 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), skinny_new(), and unistim_new().
05354 { 05355 pthread_t t; 05356 05357 if (!c) { 05358 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05359 return AST_PBX_FAILED; 05360 } 05361 05362 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05363 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05364 return AST_PBX_FAILED; 05365 } 05366 05367 if (increase_call_count(c)) 05368 return AST_PBX_CALL_LIMIT; 05369 05370 /* Start a new thread, and get something handling this channel. */ 05371 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05372 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05373 decrease_call_count(); 05374 return AST_PBX_FAILED; 05375 } 05376 05377 return AST_PBX_SUCCESS; 05378 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5410 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05411 { 05412 return totalcalls; 05413 }
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 10369 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().
10370 { 10371 return ast_rwlock_rdlock(&con->lock); 10372 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10351 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().
10352 { 10353 return ast_mutex_lock(&conlock); 10354 }
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 5821 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().
05822 { 05823 struct ast_app *tmp, *cur = NULL; 05824 char tmps[80]; 05825 int length, res; 05826 #ifdef AST_XML_DOCS 05827 char *tmpxml; 05828 #endif 05829 05830 AST_RWLIST_WRLOCK(&apps); 05831 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 05832 if (!(res = strcasecmp(app, tmp->name))) { 05833 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 05834 AST_RWLIST_UNLOCK(&apps); 05835 return -1; 05836 } else if (res < 0) 05837 break; 05838 } 05839 05840 length = sizeof(*tmp) + strlen(app) + 1; 05841 05842 if (!(tmp = ast_calloc(1, length))) { 05843 AST_RWLIST_UNLOCK(&apps); 05844 return -1; 05845 } 05846 05847 if (ast_string_field_init(tmp, 128)) { 05848 AST_RWLIST_UNLOCK(&apps); 05849 ast_free(tmp); 05850 return -1; 05851 } 05852 05853 strcpy(tmp->name, app); 05854 tmp->execute = execute; 05855 tmp->module = mod; 05856 05857 #ifdef AST_XML_DOCS 05858 /* Try to lookup the docs in our XML documentation database */ 05859 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05860 /* load synopsis */ 05861 tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module)); 05862 ast_string_field_set(tmp, synopsis, tmpxml); 05863 ast_free(tmpxml); 05864 05865 /* load description */ 05866 tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); 05867 ast_string_field_set(tmp, description, tmpxml); 05868 ast_free(tmpxml); 05869 05870 /* load syntax */ 05871 tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module)); 05872 ast_string_field_set(tmp, syntax, tmpxml); 05873 ast_free(tmpxml); 05874 05875 /* load arguments */ 05876 tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module)); 05877 ast_string_field_set(tmp, arguments, tmpxml); 05878 ast_free(tmpxml); 05879 05880 /* load seealso */ 05881 tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module)); 05882 ast_string_field_set(tmp, seealso, tmpxml); 05883 ast_free(tmpxml); 05884 tmp->docsrc = AST_XML_DOC; 05885 } else { 05886 #endif 05887 ast_string_field_set(tmp, synopsis, synopsis); 05888 ast_string_field_set(tmp, description, description); 05889 #ifdef AST_XML_DOCS 05890 tmp->docsrc = AST_STATIC_DOC; 05891 } 05892 #endif 05893 05894 /* Store in alphabetical order */ 05895 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 05896 if (strcasecmp(tmp->name, cur->name) < 0) { 05897 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 05898 break; 05899 } 05900 } 05901 AST_RWLIST_TRAVERSE_SAFE_END; 05902 if (!cur) 05903 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 05904 05905 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 05906 05907 AST_RWLIST_UNLOCK(&apps); 05908 05909 return 0; 05910 }
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 5916 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().
05917 { 05918 struct ast_switch *tmp; 05919 05920 AST_RWLIST_WRLOCK(&switches); 05921 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05922 if (!strcasecmp(tmp->name, sw->name)) { 05923 AST_RWLIST_UNLOCK(&switches); 05924 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05925 return -1; 05926 } 05927 } 05928 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05929 AST_RWLIST_UNLOCK(&switches); 05930 05931 return 0; 05932 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 4718 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().
04719 { 04720 /* Cleanup the Notifys if hint is removed */ 04721 struct ast_hint *hint; 04722 04723 if (!e) { 04724 return -1; 04725 } 04726 04727 hint = ao2_find(hints, e, OBJ_UNLINK); 04728 if (!hint) { 04729 return -1; 04730 } 04731 04732 /* 04733 * The extension is being destroyed so we must save some 04734 * information to notify that the extension is deactivated. 04735 */ 04736 ao2_lock(hint); 04737 ast_copy_string(hint->context_name, 04738 ast_get_context_name(ast_get_extension_context(hint->exten)), 04739 sizeof(hint->context_name)); 04740 ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten), 04741 sizeof(hint->exten_name)); 04742 hint->exten = NULL; 04743 ao2_unlock(hint); 04744 04745 ao2_ref(hint, -1); 04746 04747 return 0; 04748 }
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 4902 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().
04903 { 04904 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04905 }
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 4857 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().
04858 { 04859 struct ast_exten *e = ast_hint_extension(c, context, exten); 04860 04861 if (!e) { 04862 return 0; 04863 } 04864 04865 if (hint) { 04866 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 04867 } 04868 if (name) { 04869 const char *tmp = ast_get_extension_app_data(e); 04870 if (tmp) { 04871 ast_str_set(name, namesize, "%s", tmp); 04872 } 04873 } 04874 return -1; 04875 }
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 3147 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().
03148 { 03149 const char not_found = '\0'; 03150 char *tmpvar; 03151 const char *ret; 03152 const char *s; /* the result */ 03153 int offset, length; 03154 int i, need_substring; 03155 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03156 char workspace[20]; 03157 03158 if (c) { 03159 ast_channel_lock(c); 03160 places[0] = &c->varshead; 03161 } 03162 /* 03163 * Make a copy of var because parse_variable_name() modifies the string. 03164 * Then if called directly, we might need to run substring() on the result; 03165 * remember this for later in 'need_substring', 'offset' and 'length' 03166 */ 03167 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03168 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03169 03170 /* 03171 * Look first into predefined variables, then into variable lists. 03172 * Variable 's' points to the result, according to the following rules: 03173 * s == ¬_found (set at the beginning) means that we did not find a 03174 * matching variable and need to look into more places. 03175 * If s != ¬_found, s is a valid result string as follows: 03176 * s = NULL if the variable does not have a value; 03177 * you typically do this when looking for an unset predefined variable. 03178 * s = workspace if the result has been assembled there; 03179 * typically done when the result is built e.g. with an snprintf(), 03180 * so we don't need to do an additional copy. 03181 * s != workspace in case we have a string, that needs to be copied 03182 * (the ast_copy_string is done once for all at the end). 03183 * Typically done when the result is already available in some string. 03184 */ 03185 s = ¬_found; /* default value */ 03186 if (c) { /* This group requires a valid channel */ 03187 /* Names with common parts are looked up a piece at a time using strncmp. */ 03188 if (!strncmp(var, "CALL", 4)) { 03189 if (!strncmp(var + 4, "ING", 3)) { 03190 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03191 ast_str_set(str, maxlen, "%d", 03192 ast_party_id_presentation(&c->caller.id)); 03193 s = ast_str_buffer(*str); 03194 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03195 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03196 s = ast_str_buffer(*str); 03197 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03198 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03199 s = ast_str_buffer(*str); 03200 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03201 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03202 s = ast_str_buffer(*str); 03203 } 03204 } 03205 } else if (!strcmp(var, "HINT")) { 03206 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03207 } else if (!strcmp(var, "HINTNAME")) { 03208 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03209 } else if (!strcmp(var, "EXTEN")) { 03210 s = c->exten; 03211 } else if (!strcmp(var, "CONTEXT")) { 03212 s = c->context; 03213 } else if (!strcmp(var, "PRIORITY")) { 03214 ast_str_set(str, maxlen, "%d", c->priority); 03215 s = ast_str_buffer(*str); 03216 } else if (!strcmp(var, "CHANNEL")) { 03217 s = c->name; 03218 } else if (!strcmp(var, "UNIQUEID")) { 03219 s = c->uniqueid; 03220 } else if (!strcmp(var, "HANGUPCAUSE")) { 03221 ast_str_set(str, maxlen, "%d", c->hangupcause); 03222 s = ast_str_buffer(*str); 03223 } 03224 } 03225 if (s == ¬_found) { /* look for more */ 03226 if (!strcmp(var, "EPOCH")) { 03227 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03228 s = ast_str_buffer(*str); 03229 } else if (!strcmp(var, "SYSTEMNAME")) { 03230 s = ast_config_AST_SYSTEM_NAME; 03231 } else if (!strcmp(var, "ENTITYID")) { 03232 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03233 s = workspace; 03234 } 03235 } 03236 /* if not found, look into chanvars or global vars */ 03237 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03238 struct ast_var_t *variables; 03239 if (!places[i]) 03240 continue; 03241 if (places[i] == &globals) 03242 ast_rwlock_rdlock(&globalslock); 03243 AST_LIST_TRAVERSE(places[i], variables, entries) { 03244 if (!strcasecmp(ast_var_name(variables), var)) { 03245 s = ast_var_value(variables); 03246 break; 03247 } 03248 } 03249 if (places[i] == &globals) 03250 ast_rwlock_unlock(&globalslock); 03251 } 03252 if (s == ¬_found || s == NULL) { 03253 ast_debug(5, "Result of '%s' is NULL\n", var); 03254 ret = NULL; 03255 } else { 03256 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03257 if (s != ast_str_buffer(*str)) { 03258 ast_str_set(str, maxlen, "%s", s); 03259 } 03260 ret = ast_str_buffer(*str); 03261 if (need_substring) { 03262 ret = ast_str_substring(*str, offset, length); 03263 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03264 } 03265 } 03266 03267 if (c) { 03268 ast_channel_unlock(c); 03269 } 03270 return ret; 03271 }
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 3945 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().
03946 { 03947 size_t used; 03948 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 03949 }
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 3766 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().
03767 { 03768 /* Substitutes variables into buf, based on string templ */ 03769 char *cp4 = NULL; 03770 const char *tmp, *whereweare; 03771 int orig_size = 0; 03772 int offset, offset2, isfunction; 03773 const char *nextvar, *nextexp, *nextthing; 03774 const char *vars, *vare; 03775 char *finalvars; 03776 int pos, brackets, needsub, len; 03777 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03778 03779 ast_str_reset(*buf); 03780 whereweare = tmp = templ; 03781 while (!ast_strlen_zero(whereweare)) { 03782 /* reset our buffer */ 03783 ast_str_reset(substr3); 03784 03785 /* Assume we're copying the whole remaining string */ 03786 pos = strlen(whereweare); 03787 nextvar = NULL; 03788 nextexp = NULL; 03789 nextthing = strchr(whereweare, '$'); 03790 if (nextthing) { 03791 switch (nextthing[1]) { 03792 case '{': 03793 nextvar = nextthing; 03794 pos = nextvar - whereweare; 03795 break; 03796 case '[': 03797 nextexp = nextthing; 03798 pos = nextexp - whereweare; 03799 break; 03800 default: 03801 pos = 1; 03802 } 03803 } 03804 03805 if (pos) { 03806 /* Copy that many bytes */ 03807 ast_str_append_substr(buf, maxlen, whereweare, pos); 03808 03809 templ += pos; 03810 whereweare += pos; 03811 } 03812 03813 if (nextvar) { 03814 /* We have a variable. Find the start and end, and determine 03815 if we are going to have to recursively call ourselves on the 03816 contents */ 03817 vars = vare = nextvar + 2; 03818 brackets = 1; 03819 needsub = 0; 03820 03821 /* Find the end of it */ 03822 while (brackets && *vare) { 03823 if ((vare[0] == '$') && (vare[1] == '{')) { 03824 needsub++; 03825 } else if (vare[0] == '{') { 03826 brackets++; 03827 } else if (vare[0] == '}') { 03828 brackets--; 03829 } else if ((vare[0] == '$') && (vare[1] == '[')) 03830 needsub++; 03831 vare++; 03832 } 03833 if (brackets) 03834 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03835 len = vare - vars - 1; 03836 03837 /* Skip totally over variable string */ 03838 whereweare += (len + 3); 03839 03840 /* Store variable name (and truncate) */ 03841 ast_str_set_substr(&substr1, 0, vars, len); 03842 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03843 03844 /* Substitute if necessary */ 03845 if (needsub) { 03846 size_t used; 03847 if (!substr2) { 03848 substr2 = ast_str_create(16); 03849 } 03850 03851 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03852 finalvars = ast_str_buffer(substr2); 03853 } else { 03854 finalvars = ast_str_buffer(substr1); 03855 } 03856 03857 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03858 if (isfunction) { 03859 /* Evaluate function */ 03860 if (c || !headp) { 03861 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03862 } else { 03863 struct varshead old; 03864 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03865 if (bogus) { 03866 memcpy(&old, &bogus->varshead, sizeof(old)); 03867 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03868 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03869 /* Don't deallocate the varshead that was passed in */ 03870 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03871 ast_channel_unref(bogus); 03872 } else { 03873 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03874 } 03875 } 03876 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03877 } else { 03878 /* Retrieve variable value */ 03879 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 03880 cp4 = ast_str_buffer(substr3); 03881 } 03882 if (cp4) { 03883 ast_str_substring(substr3, offset, offset2); 03884 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03885 } 03886 } else if (nextexp) { 03887 /* We have an expression. Find the start and end, and determine 03888 if we are going to have to recursively call ourselves on the 03889 contents */ 03890 vars = vare = nextexp + 2; 03891 brackets = 1; 03892 needsub = 0; 03893 03894 /* Find the end of it */ 03895 while (brackets && *vare) { 03896 if ((vare[0] == '$') && (vare[1] == '[')) { 03897 needsub++; 03898 brackets++; 03899 vare++; 03900 } else if (vare[0] == '[') { 03901 brackets++; 03902 } else if (vare[0] == ']') { 03903 brackets--; 03904 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03905 needsub++; 03906 vare++; 03907 } 03908 vare++; 03909 } 03910 if (brackets) 03911 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03912 len = vare - vars - 1; 03913 03914 /* Skip totally over expression */ 03915 whereweare += (len + 3); 03916 03917 /* Store variable name (and truncate) */ 03918 ast_str_set_substr(&substr1, 0, vars, len); 03919 03920 /* Substitute if necessary */ 03921 if (needsub) { 03922 size_t used; 03923 if (!substr2) { 03924 substr2 = ast_str_create(16); 03925 } 03926 03927 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03928 finalvars = ast_str_buffer(substr2); 03929 } else { 03930 finalvars = ast_str_buffer(substr1); 03931 } 03932 03933 if (ast_str_expr(&substr3, 0, c, finalvars)) { 03934 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 03935 } 03936 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03937 } 03938 } 03939 *used = ast_str_strlen(*buf) - orig_size; 03940 ast_free(substr1); 03941 ast_free(substr2); 03942 ast_free(substr3); 03943 }
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 3951 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().
03952 { 03953 size_t used; 03954 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 03955 }
static const char* ast_str_substring | ( | struct ast_str * | value, | |
int | offset, | |||
int | length | |||
) | [static] |
Definition at line 3082 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().
03083 { 03084 int lr; /* length of the input string after the copy */ 03085 03086 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 03087 03088 /* Quick check if no need to do anything */ 03089 if (offset == 0 && length >= lr) /* take the whole string */ 03090 return ast_str_buffer(value); 03091 03092 if (offset < 0) { /* translate negative offset into positive ones */ 03093 offset = lr + offset; 03094 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03095 offset = 0; 03096 } 03097 03098 /* too large offset result in empty string so we know what to return */ 03099 if (offset >= lr) { 03100 ast_str_reset(value); 03101 return ast_str_buffer(value); 03102 } 03103 03104 if (offset > 0) { 03105 /* Go ahead and chop off the beginning */ 03106 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 03107 lr -= offset; 03108 } 03109 03110 if (length >= 0 && length < lr) { /* truncate if necessary */ 03111 char *tmp = ast_str_buffer(value); 03112 tmp[length] = '\0'; 03113 ast_str_update(value); 03114 } else if (length < 0) { 03115 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 03116 char *tmp = ast_str_buffer(value); 03117 tmp[lr + length] = '\0'; 03118 ast_str_update(value); 03119 } else { 03120 ast_str_reset(value); 03121 } 03122 } else { 03123 /* Nothing to do, but update the buffer length */ 03124 ast_str_update(value); 03125 } 03126 03127 return ast_str_buffer(value); 03128 }
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 10374 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().
10375 { 10376 return ast_rwlock_unlock(&con->lock); 10377 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10356 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().
10357 { 10358 return ast_mutex_unlock(&conlock); 10359 }
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 7164 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().
07165 { 07166 struct ast_app *tmp; 07167 07168 AST_RWLIST_WRLOCK(&apps); 07169 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 07170 if (!strcasecmp(app, tmp->name)) { 07171 unreference_cached_app(tmp); 07172 AST_RWLIST_REMOVE_CURRENT(list); 07173 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 07174 ast_string_field_free_memory(tmp); 07175 ast_free(tmp); 07176 break; 07177 } 07178 } 07179 AST_RWLIST_TRAVERSE_SAFE_END; 07180 AST_RWLIST_UNLOCK(&apps); 07181 07182 return tmp ? 0 : -1; 07183 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 5934 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().
05935 { 05936 AST_RWLIST_WRLOCK(&switches); 05937 AST_RWLIST_REMOVE(&switches, sw, list); 05938 AST_RWLIST_UNLOCK(&switches); 05939 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 10488 of file pbx.c.
References exten, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), context_used(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
10490 { 10491 if (!exten) 10492 return con ? con->root : NULL; 10493 else 10494 return exten->next; 10495 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 10521 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10523 { 10524 if (!ip) 10525 return con ? con->ignorepats : NULL; 10526 else 10527 return ip->next; 10528 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 10512 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), context_used(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
10514 { 10515 if (!inc) 10516 return con ? con->includes : NULL; 10517 else 10518 return inc->next; 10519 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 10497 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(), context_used(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10499 { 10500 if (!sw) 10501 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10502 else 10503 return AST_LIST_NEXT(sw, list); 10504 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 10483 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 10506 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 10364 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().
10365 { 10366 return ast_rwlock_wrlock(&con->lock); 10367 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10346 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().
10347 { 10348 return ast_mutex_lock(&conlock); 10349 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 8714 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().
08715 { 08716 struct async_stat *as = data; 08717 struct ast_channel *chan = as->chan; 08718 int timeout = as->timeout; 08719 int res; 08720 struct ast_frame *f; 08721 struct ast_app *app; 08722 08723 while (timeout && (chan->_state != AST_STATE_UP)) { 08724 res = ast_waitfor(chan, timeout); 08725 if (res < 1) 08726 break; 08727 if (timeout > -1) 08728 timeout = res; 08729 f = ast_read(chan); 08730 if (!f) 08731 break; 08732 if (f->frametype == AST_FRAME_CONTROL) { 08733 if ((f->subclass.integer == AST_CONTROL_BUSY) || 08734 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 08735 ast_frfree(f); 08736 break; 08737 } 08738 } 08739 ast_frfree(f); 08740 } 08741 if (chan->_state == AST_STATE_UP) { 08742 if (!ast_strlen_zero(as->app)) { 08743 app = pbx_findapp(as->app); 08744 if (app) { 08745 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 08746 pbx_exec(chan, app, as->appdata); 08747 } else 08748 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 08749 } else { 08750 if (!ast_strlen_zero(as->context)) 08751 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 08752 if (!ast_strlen_zero(as->exten)) 08753 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 08754 if (as->priority > 0) 08755 chan->priority = as->priority; 08756 /* Run the PBX */ 08757 if (ast_pbx_run(chan)) { 08758 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 08759 } else { 08760 /* PBX will have taken care of this */ 08761 chan = NULL; 08762 } 08763 } 08764 } 08765 ast_free(as); 08766 if (chan) 08767 ast_hangup(chan); 08768 return NULL; 08769 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1624 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().
01625 { 01626 char extenstr[40]; 01627 struct ast_str *my_prefix = ast_str_alloca(1024); 01628 01629 extenstr[0] = '\0'; 01630 01631 if (node->exten) { 01632 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01633 } 01634 01635 if (strlen(node->x) > 1) { 01636 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01637 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01638 node->exten ? node->exten->exten : "", extenstr); 01639 } else { 01640 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01641 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01642 node->exten ? node->exten->exten : "", extenstr); 01643 } 01644 01645 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01646 01647 if (node->next_char) 01648 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01649 01650 if (node->alt_char) 01651 cli_match_char_tree(node->alt_char, prefix, fd); 01652 }
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 4923 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.
04924 { 04925 int digit; 04926 04927 buf[pos] = '\0'; /* make sure it is properly terminated */ 04928 while (ast_matchmore_extension(c, c->context, buf, 1, 04929 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04930 /* As long as we're willing to wait, and as long as it's not defined, 04931 keep reading digits until we can't possibly get a right answer anymore. */ 04932 digit = ast_waitfordigit(c, waittime); 04933 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04934 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 04935 } else { 04936 if (!digit) /* No entry */ 04937 break; 04938 if (digit < 0) /* Error, maybe a hangup */ 04939 return -1; 04940 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 04941 buf[pos++] = digit; 04942 buf[pos] = '\0'; 04943 } 04944 waittime = c->pbx->dtimeoutms; 04945 } 04946 } 04947 return 0; 04948 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 1072 of file pbx.c.
Referenced by get_pattern_node().
01073 { 01074 const unsigned char *ac = a; 01075 const unsigned char *bc = b; 01076 01077 return *ac - *bc; 01078 }
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 6121 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().
06122 { 06123 struct ast_hint *hint; 06124 char *ret = NULL; 06125 int which = 0; 06126 int wordlen; 06127 struct ao2_iterator i; 06128 06129 if (pos != 3) 06130 return NULL; 06131 06132 wordlen = strlen(word); 06133 06134 /* walk through all hints */ 06135 i = ao2_iterator_init(hints, 0); 06136 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06137 ao2_lock(hint); 06138 if (!hint->exten) { 06139 /* The extension has already been destroyed */ 06140 ao2_unlock(hint); 06141 continue; 06142 } 06143 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 06144 ret = ast_strdup(ast_get_extension_name(hint->exten)); 06145 ao2_unlock(hint); 06146 ao2_ref(hint, -1); 06147 break; 06148 } 06149 ao2_unlock(hint); 06150 } 06151 ao2_iterator_destroy(&i); 06152 06153 return ret; 06154 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 6331 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().
06333 { 06334 struct ast_context *c = NULL; 06335 char *ret = NULL; 06336 int which = 0; 06337 int wordlen; 06338 06339 /* we are do completion of [exten@]context on second position only */ 06340 if (pos != 2) 06341 return NULL; 06342 06343 ast_rdlock_contexts(); 06344 06345 wordlen = strlen(word); 06346 06347 /* walk through all contexts and return the n-th match */ 06348 while ( (c = ast_walk_contexts(c)) ) { 06349 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06350 ret = ast_strdup(ast_get_context_name(c)); 06351 break; 06352 } 06353 } 06354 06355 ast_unlock_contexts(); 06356 06357 return ret; 06358 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7305 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().
07306 { 07307 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 07308 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 07309 struct ast_hashtab_iter *exten_iter; 07310 struct ast_hashtab_iter *prio_iter; 07311 int insert_count = 0; 07312 int first = 1; 07313 07314 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 07315 the current registrar, and copy them to the new context. If the new context does not 07316 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 07317 only create the empty matching context if the old one meets the criteria */ 07318 07319 if (context->root_table) { 07320 exten_iter = ast_hashtab_start_traversal(context->root_table); 07321 while ((exten_item=ast_hashtab_next(exten_iter))) { 07322 if (new) { 07323 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 07324 } else { 07325 new_exten_item = NULL; 07326 } 07327 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07328 while ((prio_item=ast_hashtab_next(prio_iter))) { 07329 int res1; 07330 char *dupdstr; 07331 07332 if (new_exten_item) { 07333 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 07334 } else { 07335 new_prio_item = NULL; 07336 } 07337 if (strcmp(prio_item->registrar,registrar) == 0) { 07338 continue; 07339 } 07340 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 07341 if (!new) { 07342 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 */ 07343 } 07344 07345 /* copy in the includes, switches, and ignorepats */ 07346 if (first) { /* but, only need to do this once */ 07347 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07348 first = 0; 07349 } 07350 07351 if (!new) { 07352 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07353 ast_hashtab_end_traversal(prio_iter); 07354 ast_hashtab_end_traversal(exten_iter); 07355 return; /* no sense continuing. */ 07356 } 07357 /* we will not replace existing entries in the new context with stuff from the old context. 07358 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07359 07360 dupdstr = ast_strdup(prio_item->data); 07361 07362 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07363 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07364 if (!res1 && new_exten_item && new_prio_item){ 07365 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07366 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07367 } else { 07368 /* 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, 07369 and no double frees take place, either! */ 07370 insert_count++; 07371 } 07372 } 07373 ast_hashtab_end_traversal(prio_iter); 07374 } 07375 ast_hashtab_end_traversal(exten_iter); 07376 } 07377 07378 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07379 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07380 /* we could have given it the registrar of the other module who incremented the refcount, 07381 but that's not available, so we give it the registrar we know about */ 07382 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07383 07384 /* copy in the includes, switches, and ignorepats */ 07385 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07386 } 07387 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7272 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().
07273 { 07274 struct ast_include *i; 07275 struct ast_ignorepat *ip; 07276 struct ast_sw *sw; 07277 07278 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); 07279 /* copy in the includes, switches, and ignorepats */ 07280 /* walk through includes */ 07281 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 07282 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 07283 continue; /* not mine */ 07284 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 07285 } 07286 07287 /* walk through switches */ 07288 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 07289 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 07290 continue; /* not mine */ 07291 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)); 07292 } 07293 07294 /* walk thru ignorepats ... */ 07295 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 07296 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 07297 continue; /* not mine */ 07298 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 07299 } 07300 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2246 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().
02247 { 02248 struct ast_hashtab_iter *t1; 02249 struct ast_exten *e1; 02250 #ifdef NEED_DEBUG 02251 int biggest_bucket, resizes, numobjs, numbucks; 02252 02253 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02254 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02255 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02256 numobjs, numbucks, biggest_bucket, resizes); 02257 #endif 02258 t1 = ast_hashtab_start_traversal(con->root_table); 02259 while ((e1 = ast_hashtab_next(t1))) { 02260 if (e1->exten) { 02261 add_exten_to_pattern_tree(con, e1, 0); 02262 } else { 02263 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02264 } 02265 } 02266 ast_hashtab_end_traversal(t1); 02267 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 5311 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().
05312 { 05313 ast_mutex_lock(&maxcalllock); 05314 if (countcalls > 0) 05315 countcalls--; 05316 ast_mutex_unlock(&maxcalllock); 05317 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 5319 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().
05320 { 05321 if (e->priority == PRIORITY_HINT) 05322 ast_remove_hint(e); 05323 05324 if (e->peer_table) 05325 ast_hashtab_destroy(e->peer_table,0); 05326 if (e->peer_label_table) 05327 ast_hashtab_destroy(e->peer_label_table, 0); 05328 if (e->datad) 05329 e->datad(e->data); 05330 ast_free(e); 05331 }
static void destroy_hint | ( | void * | obj | ) | [static] |
Definition at line 4688 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().
04689 { 04690 struct ast_hint *hint = obj; 04691 04692 if (hint->callbacks) { 04693 struct ast_state_cb *state_cb; 04694 const char *context_name; 04695 const char *exten_name; 04696 04697 if (hint->exten) { 04698 context_name = ast_get_context_name(ast_get_extension_context(hint->exten)); 04699 exten_name = ast_get_extension_name(hint->exten); 04700 hint->exten = NULL; 04701 } else { 04702 /* The extension has already been destroyed */ 04703 context_name = hint->context_name; 04704 exten_name = hint->exten_name; 04705 } 04706 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 04707 /* Notify with -1 and remove all callbacks */ 04708 /* NOTE: The casts will not be needed for v1.10 and later */ 04709 state_cb->change_cb((char *) context_name, (char *) exten_name, 04710 AST_EXTENSION_DEACTIVATED, state_cb->data); 04711 ao2_ref(state_cb, -1); 04712 } 04713 ao2_ref(hint->callbacks, -1); 04714 } 04715 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2269 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().
02270 { 02271 /* destroy all the alternates */ 02272 if (pattern_tree->alt_char) { 02273 destroy_pattern_tree(pattern_tree->alt_char); 02274 pattern_tree->alt_char = 0; 02275 } 02276 /* destroy all the nexts */ 02277 if (pattern_tree->next_char) { 02278 destroy_pattern_tree(pattern_tree->next_char); 02279 pattern_tree->next_char = 0; 02280 } 02281 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02282 ast_free(pattern_tree); 02283 }
static void destroy_state_cb | ( | void * | doomed | ) | [static] |
Definition at line 4519 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().
04520 { 04521 struct ast_state_cb *state_cb = doomed; 04522 04523 if (state_cb->destroy_cb) { 04524 state_cb->destroy_cb(state_cb->id, state_cb->data); 04525 } 04526 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 10241 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.
10242 { 10243 const char *device; 10244 struct statechange *sc; 10245 10246 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 10247 if (ast_strlen_zero(device)) { 10248 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 10249 return; 10250 } 10251 10252 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 10253 return; 10254 strcpy(sc->dev, device); 10255 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 10256 ast_free(sc); 10257 } 10258 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3273 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03274 { 03275 struct pbx_exception *exception = data; 03276 ast_string_field_free_memory(exception); 03277 ast_free(exception); 03278 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 2419 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02420 { 02421 /* make sure non-patterns come first. 02422 * If a is not a pattern, it either comes first or 02423 * we do a more complex pattern comparison. 02424 */ 02425 int ret = 0; 02426 02427 if (a[0] != '_') 02428 return (b[0] == '_') ? -1 : strcmp(a, b); 02429 02430 /* Now we know a is a pattern; if b is not, a comes first */ 02431 if (b[0] != '_') 02432 return 1; 02433 02434 /* ok we need full pattern sorting routine. 02435 * skip past the underscores */ 02436 ++a; ++b; 02437 do { 02438 unsigned char bitwise[2][32] = { { 0, } }; 02439 ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]); 02440 if (ret == 0) { 02441 /* Are the classes different, even though they score the same? */ 02442 ret = memcmp(bitwise[0], bitwise[1], 32); 02443 } 02444 } while (!ret && a && b); 02445 if (ret == 0) { 02446 return 0; 02447 } else { 02448 return (ret > 0) ? 1 : -1; 02449 } 02450 }
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 2339 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
02340 { 02341 int c, cmin = 0xff, count = 0; 02342 const char *end; 02343 02344 /* load value and advance pointer */ 02345 c = *(*p)++; 02346 02347 /* always return unless we have a set of chars */ 02348 switch (toupper(c)) { 02349 default: /* ordinary character */ 02350 bitwise[c / 8] = 1 << (c % 8); 02351 return 0x0100 | (c & 0xff); 02352 02353 case 'N': /* 2..9 */ 02354 bitwise[6] = 0xfc; 02355 bitwise[7] = 0x03; 02356 return 0x0800 | '2'; 02357 02358 case 'X': /* 0..9 */ 02359 bitwise[6] = 0xff; 02360 bitwise[7] = 0x03; 02361 return 0x0A00 | '0'; 02362 02363 case 'Z': /* 1..9 */ 02364 bitwise[6] = 0xfe; 02365 bitwise[7] = 0x03; 02366 return 0x0900 | '1'; 02367 02368 case '.': /* wildcard */ 02369 return 0x18000; 02370 02371 case '!': /* earlymatch */ 02372 return 0x28000; /* less specific than NULL */ 02373 02374 case '\0': /* empty string */ 02375 *p = NULL; 02376 return 0x30000; 02377 02378 case '[': /* pattern */ 02379 break; 02380 } 02381 /* locate end of set */ 02382 end = strchr(*p, ']'); 02383 02384 if (end == NULL) { 02385 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02386 return 0x40000; /* XXX make this entry go last... */ 02387 } 02388 02389 for (; *p < end ; (*p)++) { 02390 unsigned char c1, c2; /* first-last char in range */ 02391 c1 = (unsigned char)((*p)[0]); 02392 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02393 c2 = (unsigned char)((*p)[2]); 02394 *p += 2; /* skip a total of 3 chars */ 02395 } else { /* individual character */ 02396 c2 = c1; 02397 } 02398 if (c1 < cmin) { 02399 cmin = c1; 02400 } 02401 for (; c1 <= c2; c1++) { 02402 unsigned char mask = 1 << (c1 % 8); 02403 /*!\note If two patterns score the same, the one with the lowest 02404 * ascii values will compare as coming first. */ 02405 /* Flag the character as included (used) and count it. */ 02406 if (!(bitwise[ c1 / 8 ] & mask)) { 02407 bitwise[ c1 / 8 ] |= mask; 02408 count += 0x100; 02409 } 02410 } 02411 } 02412 (*p)++; 02413 return count == 0 ? 0x30000 : (count | cmin); 02414 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 8271 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
08272 { 08273 int count = 0; 08274 int insquares = 0; 08275 08276 while (*src && (count < len - 1)) { 08277 if (*src == '[') { 08278 insquares = 1; 08279 } else if (*src == ']') { 08280 insquares = 0; 08281 } else if (*src == ' ' && !insquares) { 08282 src++; 08283 continue; 08284 } 08285 *dst = *src; 08286 dst++; 08287 src++; 08288 count++; 08289 } 08290 *dst = '\0'; 08291 08292 return count; 08293 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2632 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().
02633 { 02634 int i; 02635 static int prof_id = -2; /* marker for 'unallocated' id */ 02636 if (prof_id == -2) { 02637 prof_id = ast_add_profile("ext_match", 0); 02638 } 02639 ast_mark(prof_id, 1); 02640 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode); 02641 ast_mark(prof_id, 0); 02642 return i; 02643 }
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 5445 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05446 { 05447 struct fake_context item; 05448 05449 ast_copy_string(item.name, context, sizeof(item.name)); 05450 05451 return ast_hashtab_lookup(contexts_table, &item); 05452 }
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 5459 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().
05460 { 05461 struct ast_context *c; 05462 struct fake_context item; 05463 05464 ast_copy_string(item.name, context, sizeof(item.name)); 05465 05466 ast_rdlock_contexts(); 05467 c = ast_hashtab_lookup(contexts_table, &item); 05468 if (!c) { 05469 ast_unlock_contexts(); 05470 } 05471 05472 return c; 05473 }
static int find_hint_by_cb_id | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Remove a watcher from the callback list.
Definition at line 4623 of file pbx.c.
References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.
Referenced by ast_extension_state_del().
04624 { 04625 struct ast_state_cb *state_cb; 04626 const struct ast_hint *hint = obj; 04627 int *id = arg; 04628 04629 if ((state_cb = ao2_find(hint->callbacks, id, 0))) { 04630 ao2_ref(state_cb, -1); 04631 return CMP_MATCH | CMP_STOP; 04632 } 04633 04634 return 0; 04635 }
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 3642 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03643 { 03644 char *args = strchr(function, '('); 03645 03646 if (!args) { 03647 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 03648 } else { 03649 char *p; 03650 *args++ = '\0'; 03651 if ((p = strrchr(args, ')'))) { 03652 *p = '\0'; 03653 } else { 03654 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 03655 } 03656 } 03657 return args; 03658 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static] |
Definition at line 1654 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, and match_char::next_char.
01655 { 01656 /* find the exten at the end of the rope */ 01657 struct match_char *node2 = node; 01658 01659 for (node2 = node; node2; node2 = node2->next_char) { 01660 if (node2->exten) { 01661 #ifdef NEED_DEBUG_HERE 01662 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01663 #endif 01664 return node2->exten; 01665 } 01666 } 01667 #ifdef NEED_DEBUG_HERE 01668 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01669 #endif 01670 return 0; 01671 }
static const char* get_pattern_node | ( | struct pattern_node * | node, | |
const char * | src, | |||
int | pattern, | |||
const char * | extenbuf | |||
) | [static] |
Definition at line 2003 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().
02004 { 02005 #define INC_DST_OVERFLOW_CHECK \ 02006 do { \ 02007 if (dst - node->buf < sizeof(node->buf) - 1) { \ 02008 ++dst; \ 02009 } else { \ 02010 overflow = 1; \ 02011 } \ 02012 } while (0) 02013 02014 node->specif = 0; 02015 node->buf[0] = '\0'; 02016 while (*src) { 02017 if (*src == '[' && pattern) { 02018 char *dst = node->buf; 02019 const char *src_next; 02020 int length; 02021 int overflow = 0; 02022 02023 /* get past the '[' */ 02024 ++src; 02025 for (;;) { 02026 if (*src == '\\') { 02027 /* Escaped character. */ 02028 ++src; 02029 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') { 02030 *dst = *src++; 02031 INC_DST_OVERFLOW_CHECK; 02032 } 02033 } else if (*src == '-') { 02034 unsigned char first; 02035 unsigned char last; 02036 02037 src_next = src; 02038 first = *(src_next - 1); 02039 last = *++src_next; 02040 02041 if (last == '\\') { 02042 /* Escaped character. */ 02043 last = *++src_next; 02044 } 02045 02046 /* Possible char range. */ 02047 if (node->buf[0] && last) { 02048 /* Expand the char range. */ 02049 while (++first <= last) { 02050 *dst = first; 02051 INC_DST_OVERFLOW_CHECK; 02052 } 02053 src = src_next + 1; 02054 } else { 02055 /* 02056 * There was no left or right char for the range. 02057 * It is just a '-'. 02058 */ 02059 *dst = *src++; 02060 INC_DST_OVERFLOW_CHECK; 02061 } 02062 } else if (*src == '\0') { 02063 ast_log(LOG_WARNING, 02064 "A matching ']' was not found for '[' in exten pattern '%s'\n", 02065 extenbuf); 02066 break; 02067 } else if (*src == ']') { 02068 ++src; 02069 break; 02070 } else { 02071 *dst = *src++; 02072 INC_DST_OVERFLOW_CHECK; 02073 } 02074 } 02075 /* null terminate the exploded range */ 02076 *dst = '\0'; 02077 02078 if (overflow) { 02079 ast_log(LOG_ERROR, 02080 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n", 02081 extenbuf); 02082 node->buf[0] = '\0'; 02083 continue; 02084 } 02085 02086 /* Sort the characters in character set. */ 02087 length = strlen(node->buf); 02088 if (!length) { 02089 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n", 02090 extenbuf); 02091 node->buf[0] = '\0'; 02092 continue; 02093 } 02094 qsort(node->buf, length, 1, compare_char); 02095 02096 /* Remove duplicate characters from character set. */ 02097 dst = node->buf; 02098 src_next = node->buf; 02099 while (*src_next++) { 02100 if (*dst != *src_next) { 02101 *++dst = *src_next; 02102 } 02103 } 02104 02105 length = strlen(node->buf); 02106 length <<= 8; 02107 node->specif = length | (unsigned char) node->buf[0]; 02108 break; 02109 } else if (*src == '-') { 02110 /* Skip dashes in all extensions. */ 02111 ++src; 02112 } else { 02113 if (*src == '\\') { 02114 /* 02115 * XXX The escape character here does not remove any special 02116 * meaning to characters except the '[', '\\', and '-' 02117 * characters since they are special only in this function. 02118 */ 02119 node->buf[0] = *++src; 02120 if (!node->buf[0]) { 02121 break; 02122 } 02123 } else { 02124 node->buf[0] = *src; 02125 if (pattern) { 02126 /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02127 if (node->buf[0] == 'n') { 02128 node->buf[0] = 'N'; 02129 } else if (node->buf[0] == 'x') { 02130 node->buf[0] = 'X'; 02131 } else if (node->buf[0] == 'z') { 02132 node->buf[0] = 'Z'; 02133 } 02134 } 02135 } 02136 node->buf[1] = '\0'; 02137 node->specif = 1; 02138 ++src; 02139 break; 02140 } 02141 } 02142 return src; 02143 02144 #undef INC_DST_OVERFLOW_CHECK 02145 }
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 7626 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and strsep().
Referenced by ast_build_timing().
07627 { 07628 int start, end; /* start and ending position */ 07629 unsigned int mask = 0; 07630 char *part; 07631 07632 /* Check for whole range */ 07633 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 07634 return (1 << max) - 1; 07635 } 07636 07637 while ((part = strsep(&src, "&"))) { 07638 /* Get start and ending position */ 07639 char *endpart = strchr(part, '-'); 07640 if (endpart) { 07641 *endpart++ = '\0'; 07642 } 07643 /* Find the start */ 07644 if ((start = lookup_name(part, names, max)) < 0) { 07645 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 07646 continue; 07647 } 07648 if (endpart) { /* find end of range */ 07649 if ((end = lookup_name(endpart, names, max)) < 0) { 07650 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 07651 continue; 07652 } 07653 } else { 07654 end = start; 07655 } 07656 /* Fill the mask. Remember that ranges are cyclic */ 07657 mask |= (1 << end); /* initialize with last element */ 07658 while (start != end) { 07659 mask |= (1 << start); 07660 if (++start >= max) { 07661 start = 0; 07662 } 07663 } 07664 } 07665 return mask; 07666 }
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 7669 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, ast_timing::minmask, and strsep().
Referenced by ast_build_timing().
07670 { 07671 char *endpart, *part; 07672 int x; 07673 int st_h, st_m; 07674 int endh, endm; 07675 int minute_start, minute_end; 07676 07677 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 07678 memset(i->minmask, 0, sizeof(i->minmask)); 07679 07680 /* 1-minute per bit */ 07681 /* Star is all times */ 07682 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 07683 /* 48, because each hour takes 2 integers; 30 bits each */ 07684 for (x = 0; x < 48; x++) { 07685 i->minmask[x] = 0x3fffffff; /* 30 bits */ 07686 } 07687 return; 07688 } 07689 /* Otherwise expect a range */ 07690 while ((part = strsep(×, "&"))) { 07691 if (!(endpart = strchr(part, '-'))) { 07692 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07693 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 07694 continue; 07695 } 07696 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 07697 continue; 07698 } 07699 *endpart++ = '\0'; 07700 /* why skip non digits? Mostly to skip spaces */ 07701 while (*endpart && !isdigit(*endpart)) { 07702 endpart++; 07703 } 07704 if (!*endpart) { 07705 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 07706 continue; 07707 } 07708 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07709 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 07710 continue; 07711 } 07712 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 07713 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 07714 continue; 07715 } 07716 minute_start = st_h * 60 + st_m; 07717 minute_end = endh * 60 + endm; 07718 /* Go through the time and enable each appropriate bit */ 07719 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 07720 i->minmask[x / 30] |= (1 << (x % 30)); 07721 } 07722 /* Do the last one */ 07723 i->minmask[x / 30] |= (1 << (x % 30)); 07724 } 07725 /* All done */ 07726 return; 07727 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 6658 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.
06659 { 06660 char *exten = NULL, *context = NULL; 06661 /* Variables used for different counters */ 06662 struct dialplan_counters counters; 06663 const char *incstack[AST_PBX_MAX_STACK]; 06664 06665 switch (cmd) { 06666 case CLI_INIT: 06667 e->command = "dialplan debug"; 06668 e->usage = 06669 "Usage: dialplan debug [context]\n" 06670 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 06671 return NULL; 06672 case CLI_GENERATE: 06673 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06674 } 06675 06676 memset(&counters, 0, sizeof(counters)); 06677 06678 if (a->argc != 2 && a->argc != 3) 06679 return CLI_SHOWUSAGE; 06680 06681 /* we obtain [exten@]context? if yes, split them ... */ 06682 /* note: we ignore the exten totally here .... */ 06683 if (a->argc == 3) { 06684 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06685 context = ast_strdupa(a->argv[2]); 06686 exten = strsep(&context, "@"); 06687 /* change empty strings to NULL */ 06688 if (ast_strlen_zero(exten)) 06689 exten = NULL; 06690 } else { /* no '@' char, only context given */ 06691 context = ast_strdupa(a->argv[2]); 06692 } 06693 if (ast_strlen_zero(context)) 06694 context = NULL; 06695 } 06696 /* else Show complete dial plan, context and exten are NULL */ 06697 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06698 06699 /* check for input failure and throw some error messages */ 06700 if (context && !counters.context_existence) { 06701 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06702 return CLI_FAILURE; 06703 } 06704 06705 06706 ast_cli(a->fd,"-= %d %s. =-\n", 06707 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06708 06709 /* everything ok */ 06710 return CLI_SUCCESS; 06711 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7028 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.
07029 { 07030 struct ast_channel *chan; 07031 const char *chan_name, *var_name, *var_value; 07032 07033 switch (cmd) { 07034 case CLI_INIT: 07035 e->command = "dialplan set chanvar"; 07036 e->usage = 07037 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 07038 " Set channel variable <varname> to <value>\n"; 07039 return NULL; 07040 case CLI_GENERATE: 07041 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07042 } 07043 07044 if (a->argc != e->args + 3) 07045 return CLI_SHOWUSAGE; 07046 07047 chan_name = a->argv[e->args]; 07048 var_name = a->argv[e->args + 1]; 07049 var_value = a->argv[e->args + 2]; 07050 07051 if (!(chan = ast_channel_get_by_name(chan_name))) { 07052 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 07053 return CLI_FAILURE; 07054 } 07055 07056 pbx_builtin_setvar_helper(chan, var_name, var_value); 07057 07058 chan = ast_channel_unref(chan); 07059 07060 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 07061 07062 return CLI_SUCCESS; 07063 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7065 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.
07066 { 07067 int oldval = 0; 07068 07069 switch (cmd) { 07070 case CLI_INIT: 07071 e->command = "dialplan set extenpatternmatchnew true"; 07072 e->usage = 07073 "Usage: dialplan set extenpatternmatchnew true|false\n" 07074 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07075 return NULL; 07076 case CLI_GENERATE: 07077 return NULL; 07078 } 07079 07080 if (a->argc != 4) 07081 return CLI_SHOWUSAGE; 07082 07083 oldval = pbx_set_extenpatternmatchnew(1); 07084 07085 if (oldval) 07086 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07087 else 07088 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07089 07090 return CLI_SUCCESS; 07091 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7006 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.
07007 { 07008 switch (cmd) { 07009 case CLI_INIT: 07010 e->command = "dialplan set global"; 07011 e->usage = 07012 "Usage: dialplan set global <name> <value>\n" 07013 " Set global dialplan variable <name> to <value>\n"; 07014 return NULL; 07015 case CLI_GENERATE: 07016 return NULL; 07017 } 07018 07019 if (a->argc != e->args + 2) 07020 return CLI_SHOWUSAGE; 07021 07022 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 07023 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 07024 07025 return CLI_SUCCESS; 07026 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6020 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.
06021 { 06022 struct ast_app *aa; 06023 int app, no_registered_app = 1; 06024 06025 switch (cmd) { 06026 case CLI_INIT: 06027 e->command = "core show application"; 06028 e->usage = 06029 "Usage: core show application <application> [<application> [<application> [...]]]\n" 06030 " Describes a particular application.\n"; 06031 return NULL; 06032 case CLI_GENERATE: 06033 /* 06034 * There is a possibility to show informations about more than one 06035 * application at one time. You can type 'show application Dial Echo' and 06036 * you will see informations about these two applications ... 06037 */ 06038 return ast_complete_applications(a->line, a->word, a->n); 06039 } 06040 06041 if (a->argc < 4) { 06042 return CLI_SHOWUSAGE; 06043 } 06044 06045 AST_RWLIST_RDLOCK(&apps); 06046 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06047 /* Check for each app that was supplied as an argument */ 06048 for (app = 3; app < a->argc; app++) { 06049 if (strcasecmp(aa->name, a->argv[app])) { 06050 continue; 06051 } 06052 06053 /* We found it! */ 06054 no_registered_app = 0; 06055 06056 print_app_docs(aa, a->fd); 06057 } 06058 } 06059 AST_RWLIST_UNLOCK(&apps); 06060 06061 /* we found at least one app? no? */ 06062 if (no_registered_app) { 06063 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 06064 return CLI_FAILURE; 06065 } 06066 06067 return CLI_SUCCESS; 06068 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6245 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.
06246 { 06247 struct ast_app *aa; 06248 int like = 0, describing = 0; 06249 int total_match = 0; /* Number of matches in like clause */ 06250 int total_apps = 0; /* Number of apps registered */ 06251 static const char * const choices[] = { "like", "describing", NULL }; 06252 06253 switch (cmd) { 06254 case CLI_INIT: 06255 e->command = "core show applications [like|describing]"; 06256 e->usage = 06257 "Usage: core show applications [{like|describing} <text>]\n" 06258 " List applications which are currently available.\n" 06259 " If 'like', <text> will be a substring of the app name\n" 06260 " If 'describing', <text> will be a substring of the description\n"; 06261 return NULL; 06262 case CLI_GENERATE: 06263 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 06264 } 06265 06266 AST_RWLIST_RDLOCK(&apps); 06267 06268 if (AST_RWLIST_EMPTY(&apps)) { 06269 ast_cli(a->fd, "There are no registered applications\n"); 06270 AST_RWLIST_UNLOCK(&apps); 06271 return CLI_SUCCESS; 06272 } 06273 06274 /* core list applications like <keyword> */ 06275 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 06276 like = 1; 06277 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 06278 describing = 1; 06279 } 06280 06281 /* core list applications describing <keyword1> [<keyword2>] [...] */ 06282 if ((!like) && (!describing)) { 06283 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 06284 } else { 06285 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 06286 } 06287 06288 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06289 int printapp = 0; 06290 total_apps++; 06291 if (like) { 06292 if (strcasestr(aa->name, a->argv[4])) { 06293 printapp = 1; 06294 total_match++; 06295 } 06296 } else if (describing) { 06297 if (aa->description) { 06298 /* Match all words on command line */ 06299 int i; 06300 printapp = 1; 06301 for (i = 4; i < a->argc; i++) { 06302 if (!strcasestr(aa->description, a->argv[i])) { 06303 printapp = 0; 06304 } else { 06305 total_match++; 06306 } 06307 } 06308 } 06309 } else { 06310 printapp = 1; 06311 } 06312 06313 if (printapp) { 06314 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 06315 } 06316 } 06317 if ((!like) && (!describing)) { 06318 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 06319 } else { 06320 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 06321 } 06322 06323 AST_RWLIST_UNLOCK(&apps); 06324 06325 return CLI_SUCCESS; 06326 }
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 6971 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.
06972 { 06973 struct ast_channel *chan = NULL; 06974 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 06975 06976 switch (cmd) { 06977 case CLI_INIT: 06978 e->command = "dialplan show chanvar"; 06979 e->usage = 06980 "Usage: dialplan show chanvar <channel>\n" 06981 " List current channel variables and their values\n"; 06982 return NULL; 06983 case CLI_GENERATE: 06984 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 06985 } 06986 06987 if (a->argc != e->args + 1) 06988 return CLI_SHOWUSAGE; 06989 06990 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 06991 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 06992 return CLI_FAILURE; 06993 } 06994 06995 pbx_builtin_serialize_variables(chan, &vars); 06996 06997 if (ast_str_strlen(vars)) { 06998 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 06999 } 07000 07001 chan = ast_channel_unref(chan); 07002 07003 return CLI_SUCCESS; 07004 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6591 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.
06592 { 06593 char *exten = NULL, *context = NULL; 06594 /* Variables used for different counters */ 06595 struct dialplan_counters counters; 06596 const char *incstack[AST_PBX_MAX_STACK]; 06597 06598 switch (cmd) { 06599 case CLI_INIT: 06600 e->command = "dialplan show"; 06601 e->usage = 06602 "Usage: dialplan show [[exten@]context]\n" 06603 " Show dialplan\n"; 06604 return NULL; 06605 case CLI_GENERATE: 06606 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06607 } 06608 06609 memset(&counters, 0, sizeof(counters)); 06610 06611 if (a->argc != 2 && a->argc != 3) 06612 return CLI_SHOWUSAGE; 06613 06614 /* we obtain [exten@]context? if yes, split them ... */ 06615 if (a->argc == 3) { 06616 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06617 context = ast_strdupa(a->argv[2]); 06618 exten = strsep(&context, "@"); 06619 /* change empty strings to NULL */ 06620 if (ast_strlen_zero(exten)) 06621 exten = NULL; 06622 } else { /* no '@' char, only context given */ 06623 context = ast_strdupa(a->argv[2]); 06624 } 06625 if (ast_strlen_zero(context)) 06626 context = NULL; 06627 } 06628 /* else Show complete dial plan, context and exten are NULL */ 06629 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06630 06631 /* check for input failure and throw some error messages */ 06632 if (context && !counters.context_existence) { 06633 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06634 return CLI_FAILURE; 06635 } 06636 06637 if (exten && !counters.extension_existence) { 06638 if (context) 06639 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 06640 exten, context); 06641 else 06642 ast_cli(a->fd, 06643 "There is no existence of '%s' extension in all contexts\n", 06644 exten); 06645 return CLI_FAILURE; 06646 } 06647 06648 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 06649 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 06650 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 06651 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06652 06653 /* everything ok */ 06654 return CLI_SUCCESS; 06655 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3395 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.
03396 { 03397 struct ast_custom_function *acf; 03398 /* Maximum number of characters added by terminal coloring is 22 */ 03399 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03400 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03401 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03402 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03403 char *ret = NULL; 03404 int which = 0; 03405 int wordlen; 03406 03407 switch (cmd) { 03408 case CLI_INIT: 03409 e->command = "core show function"; 03410 e->usage = 03411 "Usage: core show function <function>\n" 03412 " Describe a particular dialplan function.\n"; 03413 return NULL; 03414 case CLI_GENERATE: 03415 wordlen = strlen(a->word); 03416 /* case-insensitive for convenience in this 'complete' function */ 03417 AST_RWLIST_RDLOCK(&acf_root); 03418 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03419 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03420 ret = ast_strdup(acf->name); 03421 break; 03422 } 03423 } 03424 AST_RWLIST_UNLOCK(&acf_root); 03425 03426 return ret; 03427 } 03428 03429 if (a->argc < 4) { 03430 return CLI_SHOWUSAGE; 03431 } 03432 03433 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03434 ast_cli(a->fd, "No function by that name registered.\n"); 03435 return CLI_FAILURE; 03436 } 03437 03438 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03439 if (!(syntax = ast_malloc(syntax_size))) { 03440 ast_cli(a->fd, "Memory allocation failure!\n"); 03441 return CLI_FAILURE; 03442 } 03443 03444 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03445 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03446 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03447 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03448 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03449 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03450 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03451 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03452 #ifdef AST_XML_DOCS 03453 if (acf->docsrc == AST_XML_DOC) { 03454 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03455 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03456 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03457 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03458 } else 03459 #endif 03460 { 03461 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03462 synopsis = ast_malloc(synopsis_size); 03463 03464 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03465 description = ast_malloc(description_size); 03466 03467 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03468 arguments = ast_malloc(arguments_size); 03469 03470 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03471 seealso = ast_malloc(seealso_size); 03472 03473 /* check allocated memory. */ 03474 if (!synopsis || !description || !arguments || !seealso) { 03475 ast_free(synopsis); 03476 ast_free(description); 03477 ast_free(arguments); 03478 ast_free(seealso); 03479 ast_free(syntax); 03480 return CLI_FAILURE; 03481 } 03482 03483 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03484 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03485 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03486 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03487 } 03488 03489 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03490 infotitle, syntitle, synopsis, destitle, description, 03491 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03492 03493 ast_free(arguments); 03494 ast_free(synopsis); 03495 ast_free(description); 03496 ast_free(seealso); 03497 ast_free(syntax); 03498 03499 return CLI_SUCCESS; 03500 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3353 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.
03354 { 03355 struct ast_custom_function *acf; 03356 int count_acf = 0; 03357 int like = 0; 03358 03359 switch (cmd) { 03360 case CLI_INIT: 03361 e->command = "core show functions [like]"; 03362 e->usage = 03363 "Usage: core show functions [like <text>]\n" 03364 " List builtin functions, optionally only those matching a given string\n"; 03365 return NULL; 03366 case CLI_GENERATE: 03367 return NULL; 03368 } 03369 03370 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03371 like = 1; 03372 } else if (a->argc != 3) { 03373 return CLI_SHOWUSAGE; 03374 } 03375 03376 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03377 03378 AST_RWLIST_RDLOCK(&acf_root); 03379 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03380 if (!like || strstr(acf->name, a->argv[4])) { 03381 count_acf++; 03382 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03383 S_OR(acf->name, ""), 03384 S_OR(acf->syntax, ""), 03385 S_OR(acf->synopsis, "")); 03386 } 03387 } 03388 AST_RWLIST_UNLOCK(&acf_root); 03389 03390 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03391 03392 return CLI_SUCCESS; 03393 }
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 6913 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.
06914 { 06915 int i = 0; 06916 struct ast_var_t *newvariable; 06917 06918 switch (cmd) { 06919 case CLI_INIT: 06920 e->command = "dialplan show globals"; 06921 e->usage = 06922 "Usage: dialplan show globals\n" 06923 " List current global dialplan variables and their values\n"; 06924 return NULL; 06925 case CLI_GENERATE: 06926 return NULL; 06927 } 06928 06929 ast_rwlock_rdlock(&globalslock); 06930 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 06931 i++; 06932 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 06933 } 06934 ast_rwlock_unlock(&globalslock); 06935 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 06936 06937 return CLI_SUCCESS; 06938 }
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 6157 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.
06158 { 06159 struct ast_hint *hint; 06160 int watchers; 06161 int num = 0, extenlen; 06162 struct ao2_iterator i; 06163 06164 switch (cmd) { 06165 case CLI_INIT: 06166 e->command = "core show hint"; 06167 e->usage = 06168 "Usage: core show hint <exten>\n" 06169 " List registered hint\n"; 06170 return NULL; 06171 case CLI_GENERATE: 06172 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 06173 } 06174 06175 if (a->argc < 4) 06176 return CLI_SHOWUSAGE; 06177 06178 if (ao2_container_count(hints) == 0) { 06179 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06180 return CLI_SUCCESS; 06181 } 06182 06183 extenlen = strlen(a->argv[3]); 06184 i = ao2_iterator_init(hints, 0); 06185 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06186 ao2_lock(hint); 06187 if (!hint->exten) { 06188 /* The extension has already been destroyed */ 06189 ao2_unlock(hint); 06190 continue; 06191 } 06192 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 06193 watchers = ao2_container_count(hint->callbacks); 06194 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06195 ast_get_extension_name(hint->exten), 06196 ast_get_context_name(ast_get_extension_context(hint->exten)), 06197 ast_get_extension_app(hint->exten), 06198 ast_extension_state2str(hint->laststate), watchers); 06199 num++; 06200 } 06201 ao2_unlock(hint); 06202 } 06203 ao2_iterator_destroy(&i); 06204 if (!num) 06205 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 06206 else 06207 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 06208 return CLI_SUCCESS; 06209 }
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 6071 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.
06072 { 06073 struct ast_hint *hint; 06074 int num = 0; 06075 int watchers; 06076 struct ao2_iterator i; 06077 06078 switch (cmd) { 06079 case CLI_INIT: 06080 e->command = "core show hints"; 06081 e->usage = 06082 "Usage: core show hints\n" 06083 " List registered hints\n"; 06084 return NULL; 06085 case CLI_GENERATE: 06086 return NULL; 06087 } 06088 06089 if (ao2_container_count(hints) == 0) { 06090 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06091 return CLI_SUCCESS; 06092 } 06093 /* ... we have hints ... */ 06094 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 06095 06096 i = ao2_iterator_init(hints, 0); 06097 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06098 ao2_lock(hint); 06099 if (!hint->exten) { 06100 /* The extension has already been destroyed */ 06101 ao2_unlock(hint); 06102 continue; 06103 } 06104 watchers = ao2_container_count(hint->callbacks); 06105 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06106 ast_get_extension_name(hint->exten), 06107 ast_get_context_name(ast_get_extension_context(hint->exten)), 06108 ast_get_extension_app(hint->exten), 06109 ast_extension_state2str(hint->laststate), watchers); 06110 ao2_unlock(hint); 06111 num++; 06112 } 06113 ao2_iterator_destroy(&i); 06114 06115 ast_cli(a->fd, "----------------\n"); 06116 ast_cli(a->fd, "- %d hints registered\n", num); 06117 return CLI_SUCCESS; 06118 }
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 6213 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.
06214 { 06215 struct ast_switch *sw; 06216 06217 switch (cmd) { 06218 case CLI_INIT: 06219 e->command = "core show switches"; 06220 e->usage = 06221 "Usage: core show switches\n" 06222 " List registered switches\n"; 06223 return NULL; 06224 case CLI_GENERATE: 06225 return NULL; 06226 } 06227 06228 AST_RWLIST_RDLOCK(&switches); 06229 06230 if (AST_RWLIST_EMPTY(&switches)) { 06231 AST_RWLIST_UNLOCK(&switches); 06232 ast_cli(a->fd, "There are no registered alternative switches\n"); 06233 return CLI_SUCCESS; 06234 } 06235 06236 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 06237 AST_RWLIST_TRAVERSE(&switches, sw, list) 06238 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 06239 06240 AST_RWLIST_UNLOCK(&switches); 06241 06242 return CLI_SUCCESS; 06243 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4417 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().
04418 { 04419 struct ast_hint *hint; 04420 struct ast_str *hint_app; 04421 struct statechange *sc = datap; 04422 struct ao2_iterator i; 04423 struct ao2_iterator cb_iter; 04424 char context_name[AST_MAX_CONTEXT]; 04425 char exten_name[AST_MAX_EXTENSION]; 04426 04427 hint_app = ast_str_create(1024); 04428 if (!hint_app) { 04429 ast_free(sc); 04430 return -1; 04431 } 04432 04433 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ 04434 i = ao2_iterator_init(hints, 0); 04435 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 04436 struct ast_state_cb *state_cb; 04437 char *cur, *parse; 04438 int state; 04439 04440 ao2_lock(hint); 04441 if (!hint->exten) { 04442 /* The extension has already been destroyed */ 04443 ao2_unlock(hint); 04444 continue; 04445 } 04446 04447 /* Does this hint monitor the device that changed state? */ 04448 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04449 parse = ast_str_buffer(hint_app); 04450 while ((cur = strsep(&parse, "&"))) { 04451 if (!strcasecmp(cur, sc->dev)) { 04452 /* The hint monitors the device. */ 04453 break; 04454 } 04455 } 04456 if (!cur) { 04457 /* The hint does not monitor the device. */ 04458 ao2_unlock(hint); 04459 continue; 04460 } 04461 04462 /* 04463 * Save off strings in case the hint extension gets destroyed 04464 * while we are notifying the watchers. 04465 */ 04466 ast_copy_string(context_name, 04467 ast_get_context_name(ast_get_extension_context(hint->exten)), 04468 sizeof(context_name)); 04469 ast_copy_string(exten_name, ast_get_extension_name(hint->exten), 04470 sizeof(exten_name)); 04471 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04472 ao2_unlock(hint); 04473 04474 /* 04475 * Get device state for this hint. 04476 * 04477 * NOTE: We cannot hold any locks while determining the hint 04478 * device state or notifying the watchers without causing a 04479 * deadlock. (conlock, hints, and hint) 04480 */ 04481 state = ast_extension_state3(hint_app); 04482 if (state == hint->laststate) { 04483 continue; 04484 } 04485 04486 /* Device state changed since last check - notify the watchers. */ 04487 hint->laststate = state; /* record we saw the change */ 04488 04489 /* For general callbacks */ 04490 cb_iter = ao2_iterator_init(statecbs, 0); 04491 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04492 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04493 } 04494 ao2_iterator_destroy(&cb_iter); 04495 04496 /* For extension callbacks */ 04497 cb_iter = ao2_iterator_init(hint->callbacks, 0); 04498 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04499 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04500 } 04501 ao2_iterator_destroy(&cb_iter); 04502 } 04503 ao2_iterator_destroy(&i); 04504 ast_mutex_unlock(&context_merge_lock); 04505 04506 ast_free(hint_app); 04507 ast_free(sc); 04508 return 0; 04509 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7093 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.
07094 { 07095 int oldval = 0; 07096 07097 switch (cmd) { 07098 case CLI_INIT: 07099 e->command = "dialplan set extenpatternmatchnew false"; 07100 e->usage = 07101 "Usage: dialplan set extenpatternmatchnew true|false\n" 07102 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07103 return NULL; 07104 case CLI_GENERATE: 07105 return NULL; 07106 } 07107 07108 if (a->argc != 4) 07109 return CLI_SHOWUSAGE; 07110 07111 oldval = pbx_set_extenpatternmatchnew(0); 07112 07113 if (!oldval) 07114 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07115 else 07116 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07117 07118 return CLI_SUCCESS; 07119 }
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 1110 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01111 { 01112 const struct ast_exten *ac = ah_a; 01113 const struct ast_exten *bc = ah_b; 01114 return ac->priority != bc->priority; 01115 }
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1091 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01092 { 01093 const struct ast_exten *ac = ah_a; 01094 const struct ast_exten *bc = ah_b; 01095 int x = strcmp(ac->exten, bc->exten); 01096 if (x) { /* if exten names are diff, then return */ 01097 return x; 01098 } 01099 01100 /* but if they are the same, do the cidmatch values match? */ 01101 if (ac->matchcid && bc->matchcid) { 01102 return strcmp(ac->cidmatch,bc->cidmatch); 01103 } else if (!ac->matchcid && !bc->matchcid) { 01104 return 0; /* if there's no matchcid on either side, then this is a match */ 01105 } else { 01106 return 1; /* if there's matchcid on one but not the other, they are different */ 01107 } 01108 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1130 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().
01131 { 01132 const struct ast_exten *ac = obj; 01133 unsigned int x = ast_hashtab_hash_string(ac->exten); 01134 unsigned int y = 0; 01135 if (ac->matchcid) 01136 y = ast_hashtab_hash_string(ac->cidmatch); 01137 return x+y; 01138 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1146 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01147 { 01148 const struct ast_exten *ac = obj; 01149 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01150 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1140 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01141 { 01142 const struct ast_exten *ac = obj; 01143 return ast_hashtab_hash_int(ac->priority); 01144 }
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 10664 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().
10665 { 10666 const struct ast_hint *hint = obj; 10667 const char *exten_name; 10668 int res; 10669 10670 exten_name = ast_get_extension_name(hint->exten); 10671 if (ast_strlen_zero(exten_name)) { 10672 /* 10673 * If the exten or extension name isn't set, return 0 so that 10674 * the ao2_find() search will start in the first bucket. 10675 */ 10676 res = 0; 10677 } else { 10678 res = ast_str_case_hash(exten_name); 10679 } 10680 10681 return res; 10682 }
static int hint_id_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4672 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
04673 { 04674 const struct ast_state_cb *cb = obj; 04675 int *id = arg; 04676 04677 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 04678 }
static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 10264 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.
10266 { 10267 struct ast_data *data_hint; 10268 struct ast_hint *hint; 10269 int watchers; 10270 struct ao2_iterator i; 10271 10272 if (ao2_container_count(hints) == 0) { 10273 return 0; 10274 } 10275 10276 i = ao2_iterator_init(hints, 0); 10277 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 10278 watchers = ao2_container_count(hint->callbacks); 10279 data_hint = ast_data_add_node(data_root, "hint"); 10280 if (!data_hint) { 10281 continue; 10282 } 10283 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 10284 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 10285 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 10286 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 10287 ast_data_add_int(data_hint, "watchers", watchers); 10288 10289 if (!ast_data_search_match(search, data_hint)) { 10290 ast_data_remove_node(data_root, data_hint); 10291 } 10292 } 10293 ao2_iterator_destroy(&i); 10294 10295 return 0; 10296 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1490 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01491 { 01492 if (!i->hastime) 01493 return 1; 01494 01495 return ast_check_timing(&(i->timing)); 01496 }
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 5264 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().
05265 { 05266 int failed = 0; 05267 double curloadavg; 05268 #if defined(HAVE_SYSINFO) 05269 long curfreemem; 05270 struct sysinfo sys_info; 05271 #endif 05272 05273 ast_mutex_lock(&maxcalllock); 05274 if (option_maxcalls) { 05275 if (countcalls >= option_maxcalls) { 05276 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 05277 failed = -1; 05278 } 05279 } 05280 if (option_maxload) { 05281 getloadavg(&curloadavg, 1); 05282 if (curloadavg >= option_maxload) { 05283 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 05284 failed = -1; 05285 } 05286 } 05287 #if defined(HAVE_SYSINFO) 05288 if (option_minmemfree) { 05289 if (!sysinfo(&sys_info)) { 05290 /* make sure that the free system memory is above the configured low watermark 05291 * convert the amount of freeram from mem_units to MB */ 05292 curfreemem = sys_info.freeram * sys_info.mem_unit; 05293 curfreemem /= 1024 * 1024; 05294 if (curfreemem < option_minmemfree) { 05295 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 05296 failed = -1; 05297 } 05298 } 05299 } 05300 #endif 05301 05302 if (!failed) { 05303 countcalls++; 05304 totalcalls++; 05305 } 05306 ast_mutex_unlock(&maxcalllock); 05307 05308 return failed; 05309 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1908 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01909 { 01910 struct match_char *curr, *lcurr; 01911 01912 /* insert node into the tree at "current", so the alt_char list from current is 01913 sorted in increasing value as you go to the leaves */ 01914 if (!(*parent_ptr)) { 01915 *parent_ptr = node; 01916 return; 01917 } 01918 01919 if ((*parent_ptr)->specificity > node->specificity) { 01920 /* insert at head */ 01921 node->alt_char = (*parent_ptr); 01922 *parent_ptr = node; 01923 return; 01924 } 01925 01926 lcurr = *parent_ptr; 01927 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01928 if (curr->specificity > node->specificity) { 01929 node->alt_char = curr; 01930 lcurr->alt_char = node; 01931 break; 01932 } 01933 lcurr = curr; 01934 } 01935 01936 if (!curr) { 01937 lcurr->alt_char = node; 01938 } 01939 01940 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 10307 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().
10308 { 10309 int x; 10310 10311 /* Initialize the PBX */ 10312 ast_verb(1, "Asterisk PBX Core Initializing\n"); 10313 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 10314 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 10315 } 10316 10317 ast_verb(1, "Registering builtin applications:\n"); 10318 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10319 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 10320 __ast_custom_function_register(&exception_function, NULL); 10321 __ast_custom_function_register(&testtime_function, NULL); 10322 10323 /* Register builtin applications */ 10324 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10325 ast_verb(1, "[%s]\n", builtins[x].name); 10326 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 10327 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 10328 return -1; 10329 } 10330 } 10331 10332 /* Register manager application */ 10333 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 10334 10335 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 10336 AST_EVENT_IE_END))) { 10337 return -1; 10338 } 10339 10340 return 0; 10341 }
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 7603 of file pbx.c.
Referenced by get_range().
07604 { 07605 int i; 07606 07607 if (names && *s > '9') { 07608 for (i = 0; names[i]; i++) { 07609 if (!strcasecmp(s, names[i])) { 07610 return i; 07611 } 07612 } 07613 } 07614 07615 /* Allow months and weekdays to be specified as numbers, as well */ 07616 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 07617 /* What the array offset would have been: "1" would be at offset 0 */ 07618 return i - 1; 07619 } 07620 return -1; /* error return */ 07621 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 6714 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan_helper().
06715 { 06716 astman_send_listack(s, m, "DialPlan list will follow", "start"); 06717 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 6860 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().
06861 { 06862 const char *exten, *context; 06863 const char *id = astman_get_header(m, "ActionID"); 06864 char idtext[256]; 06865 06866 /* Variables used for different counters */ 06867 struct dialplan_counters counters; 06868 06869 if (!ast_strlen_zero(id)) 06870 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 06871 else 06872 idtext[0] = '\0'; 06873 06874 memset(&counters, 0, sizeof(counters)); 06875 06876 exten = astman_get_header(m, "Extension"); 06877 context = astman_get_header(m, "Context"); 06878 06879 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 06880 06881 if (context && !counters.context_existence) { 06882 char errorbuf[BUFSIZ]; 06883 06884 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 06885 astman_send_error(s, m, errorbuf); 06886 return 0; 06887 } 06888 if (exten && !counters.extension_existence) { 06889 char errorbuf[BUFSIZ]; 06890 06891 if (context) 06892 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 06893 else 06894 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 06895 astman_send_error(s, m, errorbuf); 06896 return 0; 06897 } 06898 06899 astman_append(s, "Event: ShowDialPlanComplete\r\n" 06900 "EventList: Complete\r\n" 06901 "ListItems: %d\r\n" 06902 "ListExtensions: %d\r\n" 06903 "ListPriorities: %d\r\n" 06904 "ListContexts: %d\r\n" 06905 "%s" 06906 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 06907 06908 /* everything ok */ 06909 return 0; 06910 }
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 6723 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().
06727 { 06728 struct ast_context *c; 06729 int res = 0, old_total_exten = dpc->total_exten; 06730 06731 if (ast_strlen_zero(exten)) 06732 exten = NULL; 06733 if (ast_strlen_zero(context)) 06734 context = NULL; 06735 06736 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 06737 06738 /* try to lock contexts */ 06739 if (ast_rdlock_contexts()) { 06740 astman_send_error(s, m, "Failed to lock contexts"); 06741 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 06742 return -1; 06743 } 06744 06745 c = NULL; /* walk all contexts ... */ 06746 while ( (c = ast_walk_contexts(c)) ) { 06747 struct ast_exten *e; 06748 struct ast_include *i; 06749 struct ast_ignorepat *ip; 06750 06751 if (context && strcmp(ast_get_context_name(c), context) != 0) 06752 continue; /* not the name we want */ 06753 06754 dpc->context_existence = 1; 06755 06756 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 06757 06758 if (ast_rdlock_context(c)) { /* failed to lock */ 06759 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 06760 continue; 06761 } 06762 06763 /* XXX note- an empty context is not printed */ 06764 e = NULL; /* walk extensions in context */ 06765 while ( (e = ast_walk_context_extensions(c, e)) ) { 06766 struct ast_exten *p; 06767 06768 /* looking for extension? is this our extension? */ 06769 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 06770 /* not the one we are looking for, continue */ 06771 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 06772 continue; 06773 } 06774 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 06775 06776 dpc->extension_existence = 1; 06777 06778 /* may we print context info? */ 06779 dpc->total_context++; 06780 dpc->total_exten++; 06781 06782 p = NULL; /* walk next extension peers */ 06783 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06784 int prio = ast_get_extension_priority(p); 06785 06786 dpc->total_prio++; 06787 if (!dpc->total_items++) 06788 manager_dpsendack(s, m); 06789 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06790 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 06791 06792 /* XXX maybe make this conditional, if p != e ? */ 06793 if (ast_get_extension_label(p)) 06794 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 06795 06796 if (prio == PRIORITY_HINT) { 06797 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 06798 } else { 06799 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)); 06800 } 06801 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 06802 } 06803 } 06804 06805 i = NULL; /* walk included and write info ... */ 06806 while ( (i = ast_walk_context_includes(c, i)) ) { 06807 if (exten) { 06808 /* Check all includes for the requested extension */ 06809 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 06810 } else { 06811 if (!dpc->total_items++) 06812 manager_dpsendack(s, m); 06813 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06814 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)); 06815 astman_append(s, "\r\n"); 06816 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 06817 } 06818 } 06819 06820 ip = NULL; /* walk ignore patterns and write info ... */ 06821 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06822 const char *ipname = ast_get_ignorepat_name(ip); 06823 char ignorepat[AST_MAX_EXTENSION]; 06824 06825 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06826 if (!exten || ast_extension_match(ignorepat, exten)) { 06827 if (!dpc->total_items++) 06828 manager_dpsendack(s, m); 06829 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06830 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 06831 astman_append(s, "\r\n"); 06832 } 06833 } 06834 if (!rinclude) { 06835 struct ast_sw *sw = NULL; 06836 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06837 if (!dpc->total_items++) 06838 manager_dpsendack(s, m); 06839 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06840 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)); 06841 astman_append(s, "\r\n"); 06842 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 06843 } 06844 } 06845 06846 ast_unlock_context(c); 06847 } 06848 ast_unlock_contexts(); 06849 06850 if (dpc->total_exten == old_total_exten) { 06851 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 06852 /* Nothing new under the sun */ 06853 return -1; 06854 } else { 06855 return res; 06856 } 06857 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2703 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02704 { 02705 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02706 failing to get a number should count as a match, otherwise not */ 02707 02708 if (ast_strlen_zero(callerid)) { 02709 return ast_strlen_zero(cidpattern) ? 1 : 0; 02710 } 02711 02712 return ast_extension_match(cidpattern, callerid); 02713 }
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 1732 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().
01733 { 01734 struct match_char *p; /* note minimal stack storage requirements */ 01735 struct ast_exten pattern = { .label = label }; 01736 #ifdef DEBUG_THIS 01737 if (tree) 01738 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01739 else 01740 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01741 #endif 01742 for (p = tree; p; p = p->alt_char) { 01743 if (p->is_pattern) { 01744 if (p->x[0] == 'N') { 01745 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01746 #define NEW_MATCHER_CHK_MATCH \ 01747 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01748 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01749 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01750 if (!p->deleted) { \ 01751 if (action == E_FINDLABEL) { \ 01752 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01753 ast_debug(4, "Found label in preferred extension\n"); \ 01754 return; \ 01755 } \ 01756 } else { \ 01757 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01758 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01759 } \ 01760 } \ 01761 } \ 01762 } 01763 01764 #define NEW_MATCHER_RECURSE \ 01765 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01766 || p->next_char->x[0] == '!')) { \ 01767 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01768 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01769 if (score->exten) { \ 01770 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01771 return; /* the first match is all we need */ \ 01772 } \ 01773 } else { \ 01774 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01775 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01776 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01777 "NULL"); \ 01778 return; /* the first match is all we need */ \ 01779 } \ 01780 } \ 01781 } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \ 01782 score->canmatch = 1; \ 01783 score->canmatch_exten = get_canmatch_exten(p); \ 01784 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01785 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01786 return; \ 01787 } \ 01788 } 01789 01790 NEW_MATCHER_CHK_MATCH; 01791 NEW_MATCHER_RECURSE; 01792 } 01793 } else if (p->x[0] == 'Z') { 01794 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01795 NEW_MATCHER_CHK_MATCH; 01796 NEW_MATCHER_RECURSE; 01797 } 01798 } else if (p->x[0] == 'X') { 01799 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01800 NEW_MATCHER_CHK_MATCH; 01801 NEW_MATCHER_RECURSE; 01802 } 01803 } else if (p->x[0] == '.' && p->x[1] == 0) { 01804 /* how many chars will the . match against? */ 01805 int i = 0; 01806 const char *str2 = str; 01807 while (*str2 && *str2 != '/') { 01808 str2++; 01809 i++; 01810 } 01811 if (p->exten && *str2 != '/') { 01812 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01813 if (score->exten) { 01814 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01815 return; /* the first match is all we need */ 01816 } 01817 } 01818 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01819 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01820 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01821 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01822 return; /* the first match is all we need */ 01823 } 01824 } 01825 } else if (p->x[0] == '!' && p->x[1] == 0) { 01826 /* how many chars will the . match against? */ 01827 int i = 1; 01828 const char *str2 = str; 01829 while (*str2 && *str2 != '/') { 01830 str2++; 01831 i++; 01832 } 01833 if (p->exten && *str2 != '/') { 01834 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01835 if (score->exten) { 01836 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01837 return; /* the first match is all we need */ 01838 } 01839 } 01840 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01841 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01842 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01843 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01844 return; /* the first match is all we need */ 01845 } 01846 } 01847 } else if (p->x[0] == '/' && p->x[1] == 0) { 01848 /* the pattern in the tree includes the cid match! */ 01849 if (p->next_char && callerid && *callerid) { 01850 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01851 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01852 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01853 return; /* the first match is all we need */ 01854 } 01855 } 01856 } else if (strchr(p->x, *str)) { 01857 ast_debug(4, "Nothing strange about this match\n"); 01858 NEW_MATCHER_CHK_MATCH; 01859 NEW_MATCHER_RECURSE; 01860 } 01861 } else if (strchr(p->x, *str)) { 01862 ast_debug(4, "Nothing strange about this match\n"); 01863 NEW_MATCHER_CHK_MATCH; 01864 NEW_MATCHER_RECURSE; 01865 } 01866 } 01867 ast_debug(4, "return at end of func\n"); 01868 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 3013 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
03014 { 03015 int parens = 0; 03016 03017 *offset = 0; 03018 *length = INT_MAX; 03019 *isfunc = 0; 03020 for (; *var; var++) { 03021 if (*var == '(') { 03022 (*isfunc)++; 03023 parens++; 03024 } else if (*var == ')') { 03025 parens--; 03026 } else if (*var == ':' && parens == 0) { 03027 *var++ = '\0'; 03028 sscanf(var, "%30d:%30d", offset, length); 03029 return 1; /* offset:length valid */ 03030 } 03031 } 03032 return 0; 03033 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10140 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().
10141 { 10142 struct ast_var_t *vardata; 10143 10144 ast_rwlock_wrlock(&globalslock); 10145 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10146 ast_var_delete(vardata); 10147 ast_rwlock_unlock(&globalslock); 10148 }
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 9902 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_exec(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sig_pri_call(), sig_pri_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().
09903 { 09904 struct ast_var_t *variables; 09905 const char *ret = NULL; 09906 int i; 09907 struct varshead *places[2] = { NULL, &globals }; 09908 09909 if (!name) 09910 return NULL; 09911 09912 if (chan) { 09913 ast_channel_lock(chan); 09914 places[0] = &chan->varshead; 09915 } 09916 09917 for (i = 0; i < 2; i++) { 09918 if (!places[i]) 09919 continue; 09920 if (places[i] == &globals) 09921 ast_rwlock_rdlock(&globalslock); 09922 AST_LIST_TRAVERSE(places[i], variables, entries) { 09923 if (!strcmp(name, ast_var_name(variables))) { 09924 ret = ast_var_value(variables); 09925 break; 09926 } 09927 } 09928 if (places[i] == &globals) 09929 ast_rwlock_unlock(&globalslock); 09930 if (ret) 09931 break; 09932 } 09933 09934 if (chan) 09935 ast_channel_unlock(chan); 09936 09937 return ret; 09938 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10162 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
10163 { 10164 char *condition, *branch1, *branch2, *branch; 10165 char *stringp; 10166 10167 if (ast_strlen_zero(data)) { 10168 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 10169 return 0; 10170 } 10171 10172 stringp = ast_strdupa(data); 10173 condition = strsep(&stringp,"?"); 10174 branch1 = strsep(&stringp,":"); 10175 branch2 = strsep(&stringp,""); 10176 branch = pbx_checkcondition(condition) ? branch1 : branch2; 10177 10178 if (ast_strlen_zero(branch)) { 10179 ast_debug(1, "Not taking any branch\n"); 10180 return 0; 10181 } 10182 10183 return pbx_builtin_goto(chan, branch); 10184 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10098 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.
10099 { 10100 char *name; 10101 char *value; 10102 char *channel; 10103 char tmp[VAR_BUF_SIZE]; 10104 static int deprecation_warning = 0; 10105 10106 if (ast_strlen_zero(data)) { 10107 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 10108 return 0; 10109 } 10110 tmp[0] = 0; 10111 if (!deprecation_warning) { 10112 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 10113 deprecation_warning = 1; 10114 } 10115 10116 value = ast_strdupa(data); 10117 name = strsep(&value,"="); 10118 channel = strsep(&value,","); 10119 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 10120 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 10121 if (chan2) { 10122 char *s = alloca(strlen(value) + 4); 10123 if (s) { 10124 sprintf(s, "${%s}", value); 10125 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 10126 } 10127 chan2 = ast_channel_unref(chan2); 10128 } 10129 pbx_builtin_setvar_helper(chan, name, tmp); 10130 } 10131 10132 return(0); 10133 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9423 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().
09424 { 09425 const char *options = data; 09426 int answer = 1; 09427 09428 /* Some channels can receive DTMF in unanswered state; some cannot */ 09429 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 09430 answer = 0; 09431 } 09432 09433 /* If the channel is hungup, stop waiting */ 09434 if (ast_check_hangup(chan)) { 09435 return -1; 09436 } else if (chan->_state != AST_STATE_UP && answer) { 09437 __ast_answer(chan, 0, 1); 09438 } 09439 09440 ast_indicate(chan, AST_CONTROL_INCOMPLETE); 09441 09442 return AST_PBX_INCOMPLETE; 09443 }
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 9940 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().
09941 { 09942 struct ast_var_t *newvariable; 09943 struct varshead *headp; 09944 09945 if (name[strlen(name)-1] == ')') { 09946 char *function = ast_strdupa(name); 09947 09948 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 09949 ast_func_write(chan, function, value); 09950 return; 09951 } 09952 09953 if (chan) { 09954 ast_channel_lock(chan); 09955 headp = &chan->varshead; 09956 } else { 09957 ast_rwlock_wrlock(&globalslock); 09958 headp = &globals; 09959 } 09960 09961 if (value) { 09962 if (headp == &globals) 09963 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09964 newvariable = ast_var_assign(name, value); 09965 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09966 } 09967 09968 if (chan) 09969 ast_channel_unlock(chan); 09970 else 09971 ast_rwlock_unlock(&globalslock); 09972 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason | |||
) |
Definition at line 3322 of file pbx.c.
References raise_exception().
03323 { 03324 /* Priority will become 1, next time through the AUTOLOOP */ 03325 return raise_exception(chan, reason, 0); 03326 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10223 of file pbx.c.
References ast_say_character_str(), and ast_channel::language.
10224 { 10225 int res = 0; 10226 10227 if (data) 10228 res = ast_say_character_str(chan, data, "", chan->language); 10229 return res; 10230 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10214 of file pbx.c.
References ast_say_digit_str(), and ast_channel::language.
10215 { 10216 int res = 0; 10217 10218 if (data) 10219 res = ast_say_digit_str(chan, data, "", chan->language); 10220 return res; 10221 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10186 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), ast_channel::language, LOG_WARNING, and strsep().
10187 { 10188 char tmp[256]; 10189 char *number = tmp; 10190 char *options; 10191 10192 if (ast_strlen_zero(data)) { 10193 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 10194 return -1; 10195 } 10196 ast_copy_string(tmp, data, sizeof(tmp)); 10197 strsep(&number, ","); 10198 options = strsep(&number, ","); 10199 if (options) { 10200 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 10201 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 10202 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 10203 return -1; 10204 } 10205 } 10206 10207 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 10208 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 10209 } 10210 10211 return 0; 10212 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 10232 of file pbx.c.
References ast_say_phonetic_str(), and ast_channel::language.
10233 { 10234 int res = 0; 10235 10236 if (data) 10237 res = ast_say_phonetic_str(chan, data, "", chan->language); 10238 return res; 10239 }
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 9871 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().
09872 { 09873 struct ast_var_t *variables; 09874 const char *var, *val; 09875 int total = 0; 09876 09877 if (!chan) 09878 return 0; 09879 09880 ast_str_reset(*buf); 09881 09882 ast_channel_lock(chan); 09883 09884 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 09885 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 09886 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 09887 ) { 09888 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 09889 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 09890 break; 09891 } else 09892 total++; 09893 } else 09894 break; 09895 } 09896 09897 ast_channel_unlock(chan); 09898 09899 return total; 09900 }
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 10032 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().
10033 { 10034 char *name, *value, *mydata; 10035 10036 if (ast_compat_app_set) { 10037 return pbx_builtin_setvar_multiple(chan, data); 10038 } 10039 10040 if (ast_strlen_zero(data)) { 10041 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10042 return 0; 10043 } 10044 10045 mydata = ast_strdupa(data); 10046 name = strsep(&mydata, "="); 10047 value = mydata; 10048 if (!value) { 10049 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10050 return 0; 10051 } 10052 10053 if (strchr(name, ' ')) { 10054 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10055 } 10056 10057 pbx_builtin_setvar_helper(chan, name, value); 10058 10059 return 0; 10060 }
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 9974 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(), 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().
09975 { 09976 struct ast_var_t *newvariable; 09977 struct varshead *headp; 09978 const char *nametail = name; 09979 09980 if (name[strlen(name) - 1] == ')') { 09981 char *function = ast_strdupa(name); 09982 09983 return ast_func_write(chan, function, value); 09984 } 09985 09986 if (chan) { 09987 ast_channel_lock(chan); 09988 headp = &chan->varshead; 09989 } else { 09990 ast_rwlock_wrlock(&globalslock); 09991 headp = &globals; 09992 } 09993 09994 /* For comparison purposes, we have to strip leading underscores */ 09995 if (*nametail == '_') { 09996 nametail++; 09997 if (*nametail == '_') 09998 nametail++; 09999 } 10000 10001 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10002 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10003 /* there is already such a variable, delete it */ 10004 AST_LIST_REMOVE_CURRENT(entries); 10005 ast_var_delete(newvariable); 10006 break; 10007 } 10008 } 10009 AST_LIST_TRAVERSE_SAFE_END; 10010 10011 if (value) { 10012 if (headp == &globals) 10013 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10014 newvariable = ast_var_assign(name, value); 10015 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10016 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10017 "Channel: %s\r\n" 10018 "Variable: %s\r\n" 10019 "Value: %s\r\n" 10020 "Uniqueid: %s\r\n", 10021 chan ? chan->name : "none", name, value, 10022 chan ? chan->uniqueid : "none"); 10023 } 10024 10025 if (chan) 10026 ast_channel_unlock(chan); 10027 else 10028 ast_rwlock_unlock(&globalslock); 10029 return 0; 10030 }
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 10062 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().
10063 { 10064 char *data; 10065 int x; 10066 AST_DECLARE_APP_ARGS(args, 10067 AST_APP_ARG(pair)[24]; 10068 ); 10069 AST_DECLARE_APP_ARGS(pair, 10070 AST_APP_ARG(name); 10071 AST_APP_ARG(value); 10072 ); 10073 10074 if (ast_strlen_zero(vdata)) { 10075 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10076 return 0; 10077 } 10078 10079 data = ast_strdupa(vdata); 10080 AST_STANDARD_APP_ARGS(args, data); 10081 10082 for (x = 0; x < args.argc; x++) { 10083 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10084 if (pair.argc == 2) { 10085 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10086 if (strchr(pair.name, ' ')) 10087 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); 10088 } else if (!chan) { 10089 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10090 } else { 10091 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10092 } 10093 } 10094 10095 return 0; 10096 }
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 10150 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().
10151 { 10152 int res; 10153 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10154 return 0; 10155 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10156 return res; 10157 } else { /* Strings are true */ 10158 return 1; 10159 } 10160 }
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 1418 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(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
01421 { 01422 int res; 01423 struct ast_module_user *u = NULL; 01424 const char *saved_c_appl; 01425 const char *saved_c_data; 01426 01427 if (c->cdr && !ast_check_hangup(c)) 01428 ast_cdr_setapp(c->cdr, app->name, data); 01429 01430 /* save channel values */ 01431 saved_c_appl= c->appl; 01432 saved_c_data= c->data; 01433 01434 c->appl = app->name; 01435 c->data = data; 01436 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01437 01438 if (app->module) 01439 u = __ast_module_user_add(app->module, c); 01440 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01441 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01442 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01443 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01444 app->name, (char *) data); 01445 } 01446 res = app->execute(c, S_OR(data, "")); 01447 if (app->module && u) 01448 __ast_module_user_remove(app->module, u); 01449 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01450 /* restore channel values */ 01451 c->appl = saved_c_appl; 01452 c->data = saved_c_data; 01453 return res; 01454 }
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 4202 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().
04205 { 04206 struct ast_exten *e; 04207 struct ast_app *app; 04208 int res; 04209 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04210 char passdata[EXT_DATA_SIZE]; 04211 04212 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04213 04214 ast_rdlock_contexts(); 04215 if (found) 04216 *found = 0; 04217 04218 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04219 if (e) { 04220 if (found) 04221 *found = 1; 04222 if (matching_action) { 04223 ast_unlock_contexts(); 04224 return -1; /* success, we found it */ 04225 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04226 res = e->priority; 04227 ast_unlock_contexts(); 04228 return res; /* the priority we were looking for */ 04229 } else { /* spawn */ 04230 if (!e->cached_app) 04231 e->cached_app = pbx_findapp(e->app); 04232 app = e->cached_app; 04233 ast_unlock_contexts(); 04234 if (!app) { 04235 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04236 return -1; 04237 } 04238 if (c->context != context) 04239 ast_copy_string(c->context, context, sizeof(c->context)); 04240 if (c->exten != exten) 04241 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04242 c->priority = priority; 04243 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 04244 #ifdef CHANNEL_TRACE 04245 ast_channel_trace_update(c); 04246 #endif 04247 ast_debug(1, "Launching '%s'\n", app->name); 04248 if (VERBOSITY_ATLEAST(3)) { 04249 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04250 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04251 exten, context, priority, 04252 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04253 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04254 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04255 "in new stack"); 04256 } 04257 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04258 "Channel: %s\r\n" 04259 "Context: %s\r\n" 04260 "Extension: %s\r\n" 04261 "Priority: %d\r\n" 04262 "Application: %s\r\n" 04263 "AppData: %s\r\n" 04264 "Uniqueid: %s\r\n", 04265 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 04266 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04267 } 04268 } else if (q.swo) { /* not found here, but in another switch */ 04269 if (found) 04270 *found = 1; 04271 ast_unlock_contexts(); 04272 if (matching_action) { 04273 return -1; 04274 } else { 04275 if (!q.swo->exec) { 04276 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04277 res = -1; 04278 } 04279 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04280 } 04281 } else { /* not found anywhere, see what happened */ 04282 ast_unlock_contexts(); 04283 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04284 switch (q.status) { 04285 case STATUS_NO_CONTEXT: 04286 if (!matching_action && !combined_find_spawn) 04287 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04288 break; 04289 case STATUS_NO_EXTENSION: 04290 if (!matching_action && !combined_find_spawn) 04291 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04292 break; 04293 case STATUS_NO_PRIORITY: 04294 if (!matching_action && !combined_find_spawn) 04295 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04296 break; 04297 case STATUS_NO_LABEL: 04298 if (context && !combined_find_spawn) 04299 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04300 break; 04301 default: 04302 ast_debug(1, "Shouldn't happen!\n"); 04303 } 04304 04305 return (matching_action) ? 0 : -1; 04306 } 04307 }
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 2715 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().
02719 { 02720 int x, res; 02721 struct ast_context *tmp = NULL; 02722 struct ast_exten *e = NULL, *eroot = NULL; 02723 struct ast_include *i = NULL; 02724 struct ast_sw *sw = NULL; 02725 struct ast_exten pattern = {NULL, }; 02726 struct scoreboard score = {0, }; 02727 struct ast_str *tmpdata = NULL; 02728 02729 pattern.label = label; 02730 pattern.priority = priority; 02731 #ifdef NEED_DEBUG_HERE 02732 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02733 #endif 02734 02735 /* Initialize status if appropriate */ 02736 if (q->stacklen == 0) { 02737 q->status = STATUS_NO_CONTEXT; 02738 q->swo = NULL; 02739 q->data = NULL; 02740 q->foundcontext = NULL; 02741 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02742 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02743 return NULL; 02744 } 02745 02746 /* Check first to see if we've already been checked */ 02747 for (x = 0; x < q->stacklen; x++) { 02748 if (!strcasecmp(q->incstack[x], context)) 02749 return NULL; 02750 } 02751 02752 if (bypass) { /* bypass means we only look there */ 02753 tmp = bypass; 02754 } else { /* look in contexts */ 02755 tmp = find_context(context); 02756 if (!tmp) { 02757 return NULL; 02758 } 02759 } 02760 02761 if (q->status < STATUS_NO_EXTENSION) 02762 q->status = STATUS_NO_EXTENSION; 02763 02764 /* Do a search for matching extension */ 02765 02766 eroot = NULL; 02767 score.total_specificity = 0; 02768 score.exten = 0; 02769 score.total_length = 0; 02770 if (!tmp->pattern_tree && tmp->root_table) { 02771 create_match_char_tree(tmp); 02772 #ifdef NEED_DEBUG 02773 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02774 log_match_char_tree(tmp->pattern_tree," "); 02775 #endif 02776 } 02777 #ifdef NEED_DEBUG 02778 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02779 log_match_char_tree(tmp->pattern_tree, ":: "); 02780 #endif 02781 02782 do { 02783 if (!ast_strlen_zero(overrideswitch)) { 02784 char *osw = ast_strdupa(overrideswitch), *name; 02785 struct ast_switch *asw; 02786 ast_switch_f *aswf = NULL; 02787 char *datap; 02788 int eval = 0; 02789 02790 name = strsep(&osw, "/"); 02791 asw = pbx_findswitch(name); 02792 02793 if (!asw) { 02794 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02795 break; 02796 } 02797 02798 if (osw && strchr(osw, '$')) { 02799 eval = 1; 02800 } 02801 02802 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02803 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 02804 break; 02805 } else if (eval) { 02806 /* Substitute variables now */ 02807 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02808 datap = ast_str_buffer(tmpdata); 02809 } else { 02810 datap = osw; 02811 } 02812 02813 /* equivalent of extension_match_core() at the switch level */ 02814 if (action == E_CANMATCH) 02815 aswf = asw->canmatch; 02816 else if (action == E_MATCHMORE) 02817 aswf = asw->matchmore; 02818 else /* action == E_MATCH */ 02819 aswf = asw->exists; 02820 if (!aswf) { 02821 res = 0; 02822 } else { 02823 if (chan) { 02824 ast_autoservice_start(chan); 02825 } 02826 res = aswf(chan, context, exten, priority, callerid, datap); 02827 if (chan) { 02828 ast_autoservice_stop(chan); 02829 } 02830 } 02831 if (res) { /* Got a match */ 02832 q->swo = asw; 02833 q->data = datap; 02834 q->foundcontext = context; 02835 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02836 return NULL; 02837 } 02838 } 02839 } while (0); 02840 02841 if (extenpatternmatchnew) { 02842 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02843 eroot = score.exten; 02844 02845 if (score.last_char == '!' && action == E_MATCHMORE) { 02846 /* We match an extension ending in '!'. 02847 * The decision in this case is final and is NULL (no match). 02848 */ 02849 #ifdef NEED_DEBUG_HERE 02850 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02851 #endif 02852 return NULL; 02853 } 02854 02855 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02856 q->status = STATUS_SUCCESS; 02857 #ifdef NEED_DEBUG_HERE 02858 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02859 #endif 02860 return score.canmatch_exten; 02861 } 02862 02863 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02864 if (score.node) { 02865 struct ast_exten *z = trie_find_next_match(score.node); 02866 if (z) { 02867 #ifdef NEED_DEBUG_HERE 02868 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02869 #endif 02870 } else { 02871 if (score.canmatch_exten) { 02872 #ifdef NEED_DEBUG_HERE 02873 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02874 #endif 02875 return score.canmatch_exten; 02876 } else { 02877 #ifdef NEED_DEBUG_HERE 02878 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02879 #endif 02880 } 02881 } 02882 return z; 02883 } 02884 #ifdef NEED_DEBUG_HERE 02885 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02886 #endif 02887 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02888 } 02889 02890 if (eroot) { 02891 /* found entry, now look for the right priority */ 02892 if (q->status < STATUS_NO_PRIORITY) 02893 q->status = STATUS_NO_PRIORITY; 02894 e = NULL; 02895 if (action == E_FINDLABEL && label ) { 02896 if (q->status < STATUS_NO_LABEL) 02897 q->status = STATUS_NO_LABEL; 02898 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02899 } else { 02900 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02901 } 02902 if (e) { /* found a valid match */ 02903 q->status = STATUS_SUCCESS; 02904 q->foundcontext = context; 02905 #ifdef NEED_DEBUG_HERE 02906 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02907 #endif 02908 return e; 02909 } 02910 } 02911 } else { /* the old/current default exten pattern match algorithm */ 02912 02913 /* scan the list trying to match extension and CID */ 02914 eroot = NULL; 02915 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02916 int match = extension_match_core(eroot->exten, exten, action); 02917 /* 0 on fail, 1 on match, 2 on earlymatch */ 02918 02919 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02920 continue; /* keep trying */ 02921 if (match == 2 && action == E_MATCHMORE) { 02922 /* We match an extension ending in '!'. 02923 * The decision in this case is final and is NULL (no match). 02924 */ 02925 return NULL; 02926 } 02927 /* found entry, now look for the right priority */ 02928 if (q->status < STATUS_NO_PRIORITY) 02929 q->status = STATUS_NO_PRIORITY; 02930 e = NULL; 02931 if (action == E_FINDLABEL && label ) { 02932 if (q->status < STATUS_NO_LABEL) 02933 q->status = STATUS_NO_LABEL; 02934 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02935 } else { 02936 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02937 } 02938 if (e) { /* found a valid match */ 02939 q->status = STATUS_SUCCESS; 02940 q->foundcontext = context; 02941 return e; 02942 } 02943 } 02944 } 02945 02946 /* Check alternative switches */ 02947 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02948 struct ast_switch *asw = pbx_findswitch(sw->name); 02949 ast_switch_f *aswf = NULL; 02950 char *datap; 02951 02952 if (!asw) { 02953 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02954 continue; 02955 } 02956 02957 /* Substitute variables now */ 02958 if (sw->eval) { 02959 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02960 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 02961 continue; 02962 } 02963 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02964 } 02965 02966 /* equivalent of extension_match_core() at the switch level */ 02967 if (action == E_CANMATCH) 02968 aswf = asw->canmatch; 02969 else if (action == E_MATCHMORE) 02970 aswf = asw->matchmore; 02971 else /* action == E_MATCH */ 02972 aswf = asw->exists; 02973 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02974 if (!aswf) 02975 res = 0; 02976 else { 02977 if (chan) 02978 ast_autoservice_start(chan); 02979 res = aswf(chan, context, exten, priority, callerid, datap); 02980 if (chan) 02981 ast_autoservice_stop(chan); 02982 } 02983 if (res) { /* Got a match */ 02984 q->swo = asw; 02985 q->data = datap; 02986 q->foundcontext = context; 02987 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02988 return NULL; 02989 } 02990 } 02991 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02992 /* Now try any includes we have in this context */ 02993 for (i = tmp->includes; i; i = i->next) { 02994 if (include_valid(i)) { 02995 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02996 #ifdef NEED_DEBUG_HERE 02997 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02998 #endif 02999 return e; 03000 } 03001 if (q->swo) 03002 return NULL; 03003 } 03004 } 03005 return NULL; 03006 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 1462 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().
01463 { 01464 struct ast_app *tmp; 01465 01466 AST_RWLIST_RDLOCK(&apps); 01467 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01468 if (!strcasecmp(tmp->name, app)) 01469 break; 01470 } 01471 AST_RWLIST_UNLOCK(&apps); 01472 01473 return tmp; 01474 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 1476 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().
01477 { 01478 struct ast_switch *asw; 01479 01480 AST_RWLIST_RDLOCK(&switches); 01481 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01482 if (!strcasecmp(asw->name, sw)) 01483 break; 01484 } 01485 AST_RWLIST_UNLOCK(&switches); 01486 01487 return asw; 01488 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 10580 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().
10581 { 10582 char *exten, *pri, *context; 10583 char *stringp; 10584 int ipri; 10585 int mode = 0; 10586 10587 if (ast_strlen_zero(goto_string)) { 10588 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 10589 return -1; 10590 } 10591 stringp = ast_strdupa(goto_string); 10592 context = strsep(&stringp, ","); /* guaranteed non-null */ 10593 exten = strsep(&stringp, ","); 10594 pri = strsep(&stringp, ","); 10595 if (!exten) { /* Only a priority in this one */ 10596 pri = context; 10597 exten = NULL; 10598 context = NULL; 10599 } else if (!pri) { /* Only an extension and priority in this one */ 10600 pri = exten; 10601 exten = context; 10602 context = NULL; 10603 } 10604 if (*pri == '+') { 10605 mode = 1; 10606 pri++; 10607 } else if (*pri == '-') { 10608 mode = -1; 10609 pri++; 10610 } 10611 if (sscanf(pri, "%30d", &ipri) != 1) { 10612 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 10613 exten ? exten : chan->exten, pri, 10614 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 10615 if (ipri < 1) { 10616 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 10617 return -1; 10618 } else 10619 mode = 0; 10620 } 10621 /* At this point we have a priority and maybe an extension and a context */ 10622 10623 if (mode) 10624 ipri = chan->priority + (ipri * mode); 10625 10626 if (async) 10627 ast_async_goto(chan, context, exten, ipri); 10628 else 10629 ast_explicit_goto(chan, context, exten, ipri); 10630 10631 return 0; 10632 10633 }
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 3136 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().
03137 { 03138 struct ast_str *str = ast_str_create(16); 03139 const char *cret; 03140 03141 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03142 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03143 *ret = cret ? workspace : NULL; 03144 ast_free(str); 03145 }
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 5415 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05416 { 05417 int oldval = autofallthrough; 05418 autofallthrough = newval; 05419 return oldval; 05420 }
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 5422 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05423 { 05424 int oldval = extenpatternmatchnew; 05425 extenpatternmatchnew = newval; 05426 return oldval; 05427 }
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 5429 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05430 { 05431 if (overrideswitch) { 05432 ast_free(overrideswitch); 05433 } 05434 if (!ast_strlen_zero(newval)) { 05435 overrideswitch = ast_strdup(newval); 05436 } else { 05437 overrideswitch = NULL; 05438 } 05439 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 4165 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
04166 { 04167 const char *tmp; 04168 04169 /* Nothing more to do */ 04170 if (!e->data) { 04171 *passdata = '\0'; 04172 return; 04173 } 04174 04175 /* No variables or expressions in e->data, so why scan it? */ 04176 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 04177 ast_copy_string(passdata, e->data, datalen); 04178 return; 04179 } 04180 04181 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 04182 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4153 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(), substituted(), and write_cdr().
04154 { 04155 size_t used; 04156 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04157 }
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 3957 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().
03958 { 03959 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03960 char *cp4 = NULL; 03961 const char *tmp, *whereweare, *orig_cp2 = cp2; 03962 int length, offset, offset2, isfunction; 03963 char *workspace = NULL; 03964 char *ltmp = NULL, *var = NULL; 03965 char *nextvar, *nextexp, *nextthing; 03966 char *vars, *vare; 03967 int pos, brackets, needsub, len; 03968 03969 *cp2 = 0; /* just in case nothing ends up there */ 03970 whereweare=tmp=cp1; 03971 while (!ast_strlen_zero(whereweare) && count) { 03972 /* Assume we're copying the whole remaining string */ 03973 pos = strlen(whereweare); 03974 nextvar = NULL; 03975 nextexp = NULL; 03976 nextthing = strchr(whereweare, '$'); 03977 if (nextthing) { 03978 switch (nextthing[1]) { 03979 case '{': 03980 nextvar = nextthing; 03981 pos = nextvar - whereweare; 03982 break; 03983 case '[': 03984 nextexp = nextthing; 03985 pos = nextexp - whereweare; 03986 break; 03987 default: 03988 pos = 1; 03989 } 03990 } 03991 03992 if (pos) { 03993 /* Can't copy more than 'count' bytes */ 03994 if (pos > count) 03995 pos = count; 03996 03997 /* Copy that many bytes */ 03998 memcpy(cp2, whereweare, pos); 03999 04000 count -= pos; 04001 cp2 += pos; 04002 whereweare += pos; 04003 *cp2 = 0; 04004 } 04005 04006 if (nextvar) { 04007 /* We have a variable. Find the start and end, and determine 04008 if we are going to have to recursively call ourselves on the 04009 contents */ 04010 vars = vare = nextvar + 2; 04011 brackets = 1; 04012 needsub = 0; 04013 04014 /* Find the end of it */ 04015 while (brackets && *vare) { 04016 if ((vare[0] == '$') && (vare[1] == '{')) { 04017 needsub++; 04018 } else if (vare[0] == '{') { 04019 brackets++; 04020 } else if (vare[0] == '}') { 04021 brackets--; 04022 } else if ((vare[0] == '$') && (vare[1] == '[')) 04023 needsub++; 04024 vare++; 04025 } 04026 if (brackets) 04027 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04028 len = vare - vars - 1; 04029 04030 /* Skip totally over variable string */ 04031 whereweare += (len + 3); 04032 04033 if (!var) 04034 var = alloca(VAR_BUF_SIZE); 04035 04036 /* Store variable name (and truncate) */ 04037 ast_copy_string(var, vars, len + 1); 04038 04039 /* Substitute if necessary */ 04040 if (needsub) { 04041 size_t used; 04042 if (!ltmp) 04043 ltmp = alloca(VAR_BUF_SIZE); 04044 04045 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04046 vars = ltmp; 04047 } else { 04048 vars = var; 04049 } 04050 04051 if (!workspace) 04052 workspace = alloca(VAR_BUF_SIZE); 04053 04054 workspace[0] = '\0'; 04055 04056 parse_variable_name(vars, &offset, &offset2, &isfunction); 04057 if (isfunction) { 04058 /* Evaluate function */ 04059 if (c || !headp) 04060 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04061 else { 04062 struct varshead old; 04063 struct ast_channel *c = ast_dummy_channel_alloc(); 04064 if (c) { 04065 memcpy(&old, &c->varshead, sizeof(old)); 04066 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04067 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04068 /* Don't deallocate the varshead that was passed in */ 04069 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04070 c = ast_channel_unref(c); 04071 } else { 04072 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04073 } 04074 } 04075 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04076 } else { 04077 /* Retrieve variable value */ 04078 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04079 } 04080 if (cp4) { 04081 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04082 04083 length = strlen(cp4); 04084 if (length > count) 04085 length = count; 04086 memcpy(cp2, cp4, length); 04087 count -= length; 04088 cp2 += length; 04089 *cp2 = 0; 04090 } 04091 } else if (nextexp) { 04092 /* We have an expression. Find the start and end, and determine 04093 if we are going to have to recursively call ourselves on the 04094 contents */ 04095 vars = vare = nextexp + 2; 04096 brackets = 1; 04097 needsub = 0; 04098 04099 /* Find the end of it */ 04100 while (brackets && *vare) { 04101 if ((vare[0] == '$') && (vare[1] == '[')) { 04102 needsub++; 04103 brackets++; 04104 vare++; 04105 } else if (vare[0] == '[') { 04106 brackets++; 04107 } else if (vare[0] == ']') { 04108 brackets--; 04109 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04110 needsub++; 04111 vare++; 04112 } 04113 vare++; 04114 } 04115 if (brackets) 04116 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04117 len = vare - vars - 1; 04118 04119 /* Skip totally over expression */ 04120 whereweare += (len + 3); 04121 04122 if (!var) 04123 var = alloca(VAR_BUF_SIZE); 04124 04125 /* Store variable name (and truncate) */ 04126 ast_copy_string(var, vars, len + 1); 04127 04128 /* Substitute if necessary */ 04129 if (needsub) { 04130 size_t used; 04131 if (!ltmp) 04132 ltmp = alloca(VAR_BUF_SIZE); 04133 04134 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04135 vars = ltmp; 04136 } else { 04137 vars = var; 04138 } 04139 04140 length = ast_expr(vars, cp2, count, c); 04141 04142 if (length) { 04143 ast_debug(1, "Expression result is '%s'\n", cp2); 04144 count -= length; 04145 cp2 += length; 04146 *cp2 = 0; 04147 } 04148 } 04149 } 04150 *used = cp2 - orig_cp2; 04151 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4159 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by dundi_lookup_local(), and loopback_subst().
04160 { 04161 size_t used; 04162 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04163 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5333 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05334 { 05335 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05336 answer this channel and get it going. 05337 */ 05338 /* NOTE: 05339 The launcher of this function _MUST_ increment 'countcalls' 05340 before invoking the function; it will be decremented when the 05341 PBX has finished running on the channel 05342 */ 05343 struct ast_channel *c = data; 05344 05345 __ast_pbx_run(c, NULL); 05346 decrease_call_count(); 05347 05348 pthread_exit(NULL); 05349 05350 return NULL; 05351 }
static void print_app_docs | ( | struct ast_app * | aa, | |
int | fd | |||
) | [static] |
Definition at line 5945 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().
05946 { 05947 /* Maximum number of characters added by terminal coloring is 22 */ 05948 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 05949 char seealsotitle[40]; 05950 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 05951 char *seealso = NULL; 05952 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 05953 05954 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 05955 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 05956 05957 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 05958 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 05959 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 05960 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 05961 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 05962 05963 #ifdef AST_XML_DOCS 05964 if (aa->docsrc == AST_XML_DOC) { 05965 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 05966 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 05967 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 05968 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 05969 05970 if (!synopsis || !description || !arguments || !seealso) { 05971 goto return_cleanup; 05972 } 05973 } else 05974 #endif 05975 { 05976 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05977 synopsis = ast_malloc(synopsis_size); 05978 05979 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05980 description = ast_malloc(description_size); 05981 05982 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05983 arguments = ast_malloc(arguments_size); 05984 05985 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05986 seealso = ast_malloc(seealso_size); 05987 05988 if (!synopsis || !description || !arguments || !seealso) { 05989 goto return_cleanup; 05990 } 05991 05992 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 05993 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 05994 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 05995 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 05996 } 05997 05998 /* Handle the syntax the same for both XML and raw docs */ 05999 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06000 if (!(syntax = ast_malloc(syntax_size))) { 06001 goto return_cleanup; 06002 } 06003 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 06004 06005 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 06006 infotitle, syntitle, synopsis, destitle, description, 06007 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 06008 06009 return_cleanup: 06010 ast_free(description); 06011 ast_free(arguments); 06012 ast_free(synopsis); 06013 ast_free(seealso); 06014 ast_free(syntax); 06015 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 6371 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().
06372 { 06373 int prio = ast_get_extension_priority(e); 06374 if (prio == PRIORITY_HINT) { 06375 snprintf(buf, buflen, "hint: %s", 06376 ast_get_extension_app(e)); 06377 } else { 06378 snprintf(buf, buflen, "%d. %s(%s)", 06379 prio, ast_get_extension_app(e), 06380 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06381 } 06382 }
static int raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason, | |||
int | priority | |||
) | [static] |
Definition at line 3296 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().
03297 { 03298 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03299 struct pbx_exception *exception = NULL; 03300 03301 if (!ds) { 03302 ds = ast_datastore_alloc(&exception_store_info, NULL); 03303 if (!ds) 03304 return -1; 03305 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03306 ast_datastore_free(ds); 03307 return -1; 03308 } 03309 ds->data = exception; 03310 ast_channel_datastore_add(chan, ds); 03311 } else 03312 exception = ds->data; 03313 03314 ast_string_field_set(exception, reason, reason); 03315 ast_string_field_set(exception, context, chan->context); 03316 ast_string_field_set(exception, exten, chan->exten); 03317 exception->priority = chan->priority; 03318 set_ext_pri(chan, "e", priority); 03319 return 0; 03320 }
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 4908 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().
04909 { 04910 ast_channel_lock(c); 04911 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04912 c->priority = pri; 04913 ast_channel_unlock(c); 04914 }
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 6536 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().
06537 { 06538 struct ast_context *c = NULL; 06539 int res = 0, old_total_exten = dpc->total_exten; 06540 06541 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 06542 06543 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 06544 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 06545 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 06546 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 06547 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 06548 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 06549 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 06550 ast_rdlock_contexts(); 06551 06552 /* walk all contexts ... */ 06553 while ( (c = ast_walk_contexts(c)) ) { 06554 int context_info_printed = 0; 06555 06556 if (context && strcmp(ast_get_context_name(c), context)) 06557 continue; /* skip this one, name doesn't match */ 06558 06559 dpc->context_existence = 1; 06560 06561 if (!c->pattern_tree) { 06562 /* Ignore check_return warning from Coverity for ast_exists_extension below */ 06563 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 06564 } 06565 06566 ast_rdlock_context(c); 06567 06568 dpc->total_context++; 06569 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06570 ast_get_context_name(c), ast_get_context_registrar(c)); 06571 context_info_printed = 1; 06572 06573 if (c->pattern_tree) 06574 { 06575 cli_match_char_tree(c->pattern_tree, " ", fd); 06576 } else { 06577 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 06578 } 06579 06580 ast_unlock_context(c); 06581 06582 /* if we print something in context, make an empty line */ 06583 if (context_info_printed) 06584 ast_cli(fd, "\n"); 06585 } 06586 ast_unlock_contexts(); 06587 06588 return (dpc->total_exten == old_total_exten) ? -1 : res; 06589 }
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 6385 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().
06386 { 06387 struct ast_context *c = NULL; 06388 int res = 0, old_total_exten = dpc->total_exten; 06389 06390 ast_rdlock_contexts(); 06391 06392 /* walk all contexts ... */ 06393 while ( (c = ast_walk_contexts(c)) ) { 06394 struct ast_exten *e; 06395 struct ast_include *i; 06396 struct ast_ignorepat *ip; 06397 char buf[256], buf2[256]; 06398 int context_info_printed = 0; 06399 06400 if (context && strcmp(ast_get_context_name(c), context)) 06401 continue; /* skip this one, name doesn't match */ 06402 06403 dpc->context_existence = 1; 06404 06405 ast_rdlock_context(c); 06406 06407 /* are we looking for exten too? if yes, we print context 06408 * only if we find our extension. 06409 * Otherwise print context even if empty ? 06410 * XXX i am not sure how the rinclude is handled. 06411 * I think it ought to go inside. 06412 */ 06413 if (!exten) { 06414 dpc->total_context++; 06415 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06416 ast_get_context_name(c), ast_get_context_registrar(c)); 06417 context_info_printed = 1; 06418 } 06419 06420 /* walk extensions ... */ 06421 e = NULL; 06422 while ( (e = ast_walk_context_extensions(c, e)) ) { 06423 struct ast_exten *p; 06424 06425 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06426 continue; /* skip, extension match failed */ 06427 06428 dpc->extension_existence = 1; 06429 06430 /* may we print context info? */ 06431 if (!context_info_printed) { 06432 dpc->total_context++; 06433 if (rinclude) { /* TODO Print more info about rinclude */ 06434 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06435 ast_get_context_name(c), ast_get_context_registrar(c)); 06436 } else { 06437 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06438 ast_get_context_name(c), ast_get_context_registrar(c)); 06439 } 06440 context_info_printed = 1; 06441 } 06442 dpc->total_prio++; 06443 06444 /* write extension name and first peer */ 06445 if (e->matchcid) 06446 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06447 else 06448 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06449 06450 print_ext(e, buf2, sizeof(buf2)); 06451 06452 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06453 ast_get_extension_registrar(e)); 06454 06455 dpc->total_exten++; 06456 /* walk next extension peers */ 06457 p = e; /* skip the first one, we already got it */ 06458 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06459 const char *el = ast_get_extension_label(p); 06460 dpc->total_prio++; 06461 if (el) 06462 snprintf(buf, sizeof(buf), " [%s]", el); 06463 else 06464 buf[0] = '\0'; 06465 print_ext(p, buf2, sizeof(buf2)); 06466 06467 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 06468 ast_get_extension_registrar(p)); 06469 } 06470 } 06471 06472 /* walk included and write info ... */ 06473 i = NULL; 06474 while ( (i = ast_walk_context_includes(c, i)) ) { 06475 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 06476 if (exten) { 06477 /* Check all includes for the requested extension */ 06478 if (includecount >= AST_PBX_MAX_STACK) { 06479 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 06480 } else { 06481 int dupe = 0; 06482 int x; 06483 for (x = 0; x < includecount; x++) { 06484 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 06485 dupe++; 06486 break; 06487 } 06488 } 06489 if (!dupe) { 06490 includes[includecount] = ast_get_include_name(i); 06491 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 06492 } else { 06493 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 06494 } 06495 } 06496 } else { 06497 ast_cli(fd, " Include => %-45s [%s]\n", 06498 buf, ast_get_include_registrar(i)); 06499 } 06500 } 06501 06502 /* walk ignore patterns and write info ... */ 06503 ip = NULL; 06504 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06505 const char *ipname = ast_get_ignorepat_name(ip); 06506 char ignorepat[AST_MAX_EXTENSION]; 06507 snprintf(buf, sizeof(buf), "'%s'", ipname); 06508 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06509 if (!exten || ast_extension_match(ignorepat, exten)) { 06510 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 06511 buf, ast_get_ignorepat_registrar(ip)); 06512 } 06513 } 06514 if (!rinclude) { 06515 struct ast_sw *sw = NULL; 06516 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06517 snprintf(buf, sizeof(buf), "'%s/%s'", 06518 ast_get_switch_name(sw), 06519 ast_get_switch_data(sw)); 06520 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 06521 buf, ast_get_switch_registrar(sw)); 06522 } 06523 } 06524 06525 ast_unlock_context(c); 06526 06527 /* if we print something in context, make an empty line */ 06528 if (context_info_printed) 06529 ast_cli(fd, "\n"); 06530 } 06531 ast_unlock_contexts(); 06532 06533 return (dpc->total_exten == old_total_exten) ? -1 : res; 06534 }
static int statecbs_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 10692 of file pbx.c.
References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
10693 { 10694 const struct ast_state_cb *state_cb = obj; 10695 ast_state_cb_type change_cb = arg; 10696 10697 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; 10698 }
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 3046 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
03047 { 03048 char *ret = workspace; 03049 int lr; /* length of the input string after the copy */ 03050 03051 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 03052 03053 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 03054 03055 /* Quick check if no need to do anything */ 03056 if (offset == 0 && length >= lr) /* take the whole string */ 03057 return ret; 03058 03059 if (offset < 0) { /* translate negative offset into positive ones */ 03060 offset = lr + offset; 03061 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03062 offset = 0; 03063 } 03064 03065 /* too large offset result in empty string so we know what to return */ 03066 if (offset >= lr) 03067 return ret + lr; /* the final '\0' */ 03068 03069 ret += offset; /* move to the start position */ 03070 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 03071 ret[length] = '\0'; 03072 else if (length < 0) { 03073 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 03074 ret[lr + length - offset] = '\0'; 03075 else 03076 ret[0] = '\0'; 03077 } 03078 03079 return ret; 03080 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static] |
Definition at line 1673 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().
01674 { 01675 struct match_char *m3; 01676 struct match_char *m4; 01677 struct ast_exten *e3; 01678 01679 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01680 return node->exten; 01681 } 01682 01683 if (node && node->x[0] == '!' && !node->x[1]) { 01684 return node->exten; 01685 } 01686 01687 if (!node || !node->next_char) { 01688 return NULL; 01689 } 01690 01691 m3 = node->next_char; 01692 01693 if (m3->exten) { 01694 return m3->exten; 01695 } 01696 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01697 if (m4->exten) { 01698 return m4->exten; 01699 } 01700 } 01701 for (m4 = m3; m4; m4 = m4->alt_char) { 01702 e3 = trie_find_next_match(m3); 01703 if (e3) { 01704 return e3; 01705 } 01706 } 01707 01708 return NULL; 01709 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 7145 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().
07146 { 07147 struct ast_context *context = NULL; 07148 struct ast_exten *eroot = NULL, *e = NULL; 07149 07150 ast_rdlock_contexts(); 07151 while ((context = ast_walk_contexts(context))) { 07152 while ((eroot = ast_walk_context_extensions(context, eroot))) { 07153 while ((e = ast_walk_extension_priorities(eroot, e))) { 07154 if (e->cached_app == app) 07155 e->cached_app = NULL; 07156 } 07157 } 07158 } 07159 ast_unlock_contexts(); 07160 07161 return; 07162 }
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 1577 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().
01578 { 01579 /* if this extension is marked as deleted, then skip this -- if it never shows 01580 on the scoreboard, it will never be found, nor will halt the traversal. */ 01581 if (deleted) 01582 return; 01583 board->total_specificity = spec; 01584 board->total_length = length; 01585 board->exten = exten; 01586 board->last_char = last; 01587 board->node = node; 01588 #ifdef NEED_DEBUG_HERE 01589 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01590 #endif 01591 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
const void * | data | |||
) | [static] |
Definition at line 9309 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().
09310 { 09311 int res; 09312 struct ast_frame *f; 09313 double waitsec; 09314 int waittime; 09315 09316 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 09317 waitsec = -1; 09318 if (waitsec > -1) { 09319 waittime = waitsec * 1000.0; 09320 ast_safe_sleep(chan, waittime); 09321 } else do { 09322 res = ast_waitfor(chan, -1); 09323 if (res < 0) 09324 return; 09325 f = ast_read(chan); 09326 if (f) 09327 ast_frfree(f); 09328 } while(f); 09329 }
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 1215 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 1220 of file pbx.c.
Referenced by ast_merge_contexts_and_delete(), and handle_statechange().
struct ast_context* contexts [static] |
Definition at line 1206 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 1207 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 1164 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 3348 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 3280 of file pbx.c.
Referenced by acf_exception_read(), and raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1157 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 1153 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 1235 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 1163 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 1158 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 10303 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 1237 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 9541 of file pbx.c.
Referenced by load_pbx().
int totalcalls [static] |
Definition at line 1165 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] |