#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 | pbx_builtin |
Declaration of builtin applications. More... | |
struct | pbx_exception |
struct | scoreboard |
struct | statecbs |
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 | 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, char *pattern, int is_pattern, int already, int specificity, struct match_char **parent) |
static int | add_pri (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 int | add_pri_lockopt (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace, int lockhints) |
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 lockconts, int lockhints) |
Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held. | |
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. | |
int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
Registers a state change callback. | |
int | ast_extension_state_del (int id, ast_state_cb_type callback) |
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 () |
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 () |
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 () |
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_pattern_tree (struct match_char *pattern_tree) |
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 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 | 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 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 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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } |
Lock for the ast_context list This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643. | |
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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RWLOCK_INITIALIZER } |
static const int | HASH_EXTENHINT_SIZE = 563 |
static struct ao2_container * | hints |
static struct ast_data_handler | hints_data_provider |
static ast_mutex_t | maxcalllock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } |
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 int | stateid = 1 |
static struct ast_threadstorage | switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } |
static struct ast_custom_function | testtime_function |
static int | totalcalls |
static struct ast_app_option | waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} |
Definition in file pbx.c.
#define AST_PBX_MAX_STACK 128 |
#define BACKGROUND_MATCHEXTEN (1 << 2) |
#define BACKGROUND_NOANSWER (1 << 1) |
#define BACKGROUND_PLAYBACK (1 << 3) |
#define BACKGROUND_SKIP (1 << 0) |
#define EXT_DATA_SIZE 8192 |
A new algorithm to do searching based on a 'compiled' pattern tree is introduced here, and shows a fairly flat (constant) search time, even for over 10000 patterns.
Also, using a hash table for context/priority name lookup can help prevent the find_extension routines from absorbing exponential cpu cycles as the number of contexts/priorities grow. I've previously tested find_extension with red-black trees, which have O(log2(n)) speed. Right now, I'm using hash tables, which do searches (ideally) in O(1) time. While these techniques do not yield much speed in small dialplans, they are worth the trouble in large dialplans.
Definition at line 770 of file pbx.c.
Referenced by pbx_extension_helper().
#define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
#define NEW_MATCHER_RECURSE |
#define VAR_BUF_SIZE 4096 |
Definition at line 775 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_DIALTONE (1 << 1) |
#define WAITEXTEN_MOH (1 << 0) |
void __ast_context_destroy | ( | struct ast_context * | list, | |
struct ast_hashtab * | contexttab, | |||
struct ast_context * | con, | |||
const char * | registrar | |||
) |
Definition at line 8711 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().
08712 { 08713 struct ast_context *tmp, *tmpl=NULL; 08714 struct ast_exten *exten_item, *prio_item; 08715 08716 for (tmp = list; tmp; ) { 08717 struct ast_context *next = NULL; /* next starting point */ 08718 /* The following code used to skip forward to the next 08719 context with matching registrar, but this didn't 08720 make sense; individual priorities registrar'd to 08721 the matching registrar could occur in any context! */ 08722 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 08723 if (con) { 08724 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 08725 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 08726 if ( !strcasecmp(tmp->name, con->name) ) { 08727 break; /* found it */ 08728 } 08729 } 08730 } 08731 08732 if (!tmp) /* not found, we are done */ 08733 break; 08734 ast_wrlock_context(tmp); 08735 08736 if (registrar) { 08737 /* then search thru and remove any extens that match registrar. */ 08738 struct ast_hashtab_iter *exten_iter; 08739 struct ast_hashtab_iter *prio_iter; 08740 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 08741 struct ast_include *i, *pi = NULL, *ni = NULL; 08742 struct ast_sw *sw = NULL; 08743 08744 /* remove any ignorepats whose registrar matches */ 08745 for (ip = tmp->ignorepats; ip; ip = ipn) { 08746 ipn = ip->next; 08747 if (!strcmp(ip->registrar, registrar)) { 08748 if (ipl) { 08749 ipl->next = ip->next; 08750 ast_free(ip); 08751 continue; /* don't change ipl */ 08752 } else { 08753 tmp->ignorepats = ip->next; 08754 ast_free(ip); 08755 continue; /* don't change ipl */ 08756 } 08757 } 08758 ipl = ip; 08759 } 08760 /* remove any includes whose registrar matches */ 08761 for (i = tmp->includes; i; i = ni) { 08762 ni = i->next; 08763 if (strcmp(i->registrar, registrar) == 0) { 08764 /* remove from list */ 08765 if (pi) { 08766 pi->next = i->next; 08767 /* free include */ 08768 ast_free(i); 08769 continue; /* don't change pi */ 08770 } else { 08771 tmp->includes = i->next; 08772 /* free include */ 08773 ast_free(i); 08774 continue; /* don't change pi */ 08775 } 08776 } 08777 pi = i; 08778 } 08779 /* remove any switches whose registrar matches */ 08780 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 08781 if (strcmp(sw->registrar,registrar) == 0) { 08782 AST_LIST_REMOVE_CURRENT(list); 08783 ast_free(sw); 08784 } 08785 } 08786 AST_LIST_TRAVERSE_SAFE_END; 08787 08788 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 08789 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 08790 while ((exten_item=ast_hashtab_next(exten_iter))) { 08791 int end_traversal = 1; 08792 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 08793 while ((prio_item=ast_hashtab_next(prio_iter))) { 08794 char extension[AST_MAX_EXTENSION]; 08795 char cidmatch[AST_MAX_EXTENSION]; 08796 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 08797 continue; 08798 } 08799 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 08800 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 08801 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 08802 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 08803 if (prio_item->cidmatch) { 08804 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 08805 } 08806 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1); 08807 } 08808 /* Explanation: 08809 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 08810 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 08811 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 08812 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 08813 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 08814 * free the iterator 08815 */ 08816 if (end_traversal) { 08817 ast_hashtab_end_traversal(prio_iter); 08818 } else { 08819 ast_free(prio_iter); 08820 } 08821 } 08822 ast_hashtab_end_traversal(exten_iter); 08823 } 08824 08825 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 08826 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 08827 another registrar. It's not empty if there are any extensions */ 08828 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 08829 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 08830 ast_hashtab_remove_this_object(contexttab, tmp); 08831 08832 next = tmp->next; 08833 if (tmpl) 08834 tmpl->next = next; 08835 else 08836 contexts = next; 08837 /* Okay, now we're safe to let it go -- in a sense, we were 08838 ready to let it go as soon as we locked it. */ 08839 ast_unlock_context(tmp); 08840 __ast_internal_context_destroy(tmp); 08841 } else { 08842 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 08843 tmp->refcount, tmp->root); 08844 ast_unlock_context(tmp); 08845 next = tmp->next; 08846 tmpl = tmp; 08847 } 08848 } else if (con) { 08849 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 08850 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 08851 ast_hashtab_remove_this_object(contexttab, tmp); 08852 08853 next = tmp->next; 08854 if (tmpl) 08855 tmpl->next = next; 08856 else 08857 contexts = next; 08858 /* Okay, now we're safe to let it go -- in a sense, we were 08859 ready to let it go as soon as we locked it. */ 08860 ast_unlock_context(tmp); 08861 __ast_internal_context_destroy(tmp); 08862 } 08863 08864 /* if we have a specific match, we are done, otherwise continue */ 08865 tmp = con ? NULL : next; 08866 } 08867 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3414 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().
03415 { 03416 struct ast_custom_function *cur; 03417 char tmps[80]; 03418 03419 if (!acf) { 03420 return -1; 03421 } 03422 03423 acf->mod = mod; 03424 #ifdef AST_XML_DOCS 03425 acf->docsrc = AST_STATIC_DOC; 03426 #endif 03427 03428 if (acf_retrieve_docs(acf)) { 03429 return -1; 03430 } 03431 03432 AST_RWLIST_WRLOCK(&acf_root); 03433 03434 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03435 if (!strcmp(acf->name, cur->name)) { 03436 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03437 AST_RWLIST_UNLOCK(&acf_root); 03438 return -1; 03439 } 03440 } 03441 03442 /* Store in alphabetical order */ 03443 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03444 if (strcasecmp(acf->name, cur->name) < 0) { 03445 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03446 break; 03447 } 03448 } 03449 AST_RWLIST_TRAVERSE_SAFE_END; 03450 03451 if (!cur) { 03452 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03453 } 03454 03455 AST_RWLIST_UNLOCK(&acf_root); 03456 03457 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03458 03459 return 0; 03460 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 10107 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().
10108 { 10109 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 10110 10111 if (!chan) 10112 return -2; 10113 10114 if (context == NULL) 10115 context = chan->context; 10116 if (exten == NULL) 10117 exten = chan->exten; 10118 10119 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 10120 if (ast_exists_extension(chan, context, exten, priority, 10121 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 10122 return goto_func(chan, context, exten, priority); 10123 else { 10124 return AST_PBX_GOTO_FAILED; 10125 } 10126 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 8664 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().
08665 { 08666 struct ast_include *tmpi; 08667 struct ast_sw *sw; 08668 struct ast_exten *e, *el, *en; 08669 struct ast_ignorepat *ipi; 08670 struct ast_context *tmp = con; 08671 08672 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 08673 struct ast_include *tmpil = tmpi; 08674 tmpi = tmpi->next; 08675 ast_free(tmpil); 08676 } 08677 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 08678 struct ast_ignorepat *ipl = ipi; 08679 ipi = ipi->next; 08680 ast_free(ipl); 08681 } 08682 if (tmp->registrar) 08683 ast_free(tmp->registrar); 08684 08685 /* destroy the hash tabs */ 08686 if (tmp->root_table) { 08687 ast_hashtab_destroy(tmp->root_table, 0); 08688 } 08689 /* and destroy the pattern tree */ 08690 if (tmp->pattern_tree) 08691 destroy_pattern_tree(tmp->pattern_tree); 08692 08693 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 08694 ast_free(sw); 08695 for (e = tmp->root; e;) { 08696 for (en = e->peer; en;) { 08697 el = en; 08698 en = en->peer; 08699 destroy_exten(el); 08700 } 08701 el = e; 08702 e = e->next; 08703 destroy_exten(el); 08704 } 08705 tmp->root = NULL; 08706 ast_rwlock_destroy(&tmp->lock); 08707 ast_free(tmp); 08708 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 4651 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_update(), ast_check_hangup(), ast_copy_string(), ast_debug, 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, pbx_builtin_raise_exception(), 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().
04653 { 04654 int found = 0; /* set if we find at least one match */ 04655 int res = 0; 04656 int autoloopflag; 04657 int error = 0; /* set an error conditions */ 04658 04659 /* A little initial setup here */ 04660 if (c->pbx) { 04661 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 04662 /* XXX and now what ? */ 04663 ast_free(c->pbx); 04664 } 04665 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 04666 return -1; 04667 /* Set reasonable defaults */ 04668 c->pbx->rtimeoutms = 10000; 04669 c->pbx->dtimeoutms = 5000; 04670 04671 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 04672 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 04673 04674 /* Start by trying whatever the channel is set to */ 04675 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 04676 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04677 /* If not successful fall back to 's' */ 04678 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); 04679 /* XXX the original code used the existing priority in the call to 04680 * ast_exists_extension(), and reset it to 1 afterwards. 04681 * I believe the correct thing is to set it to 1 immediately. 04682 */ 04683 set_ext_pri(c, "s", 1); 04684 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 04685 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04686 /* JK02: And finally back to default if everything else failed */ 04687 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); 04688 ast_copy_string(c->context, "default", sizeof(c->context)); 04689 } 04690 } 04691 if (c->cdr) { 04692 /* allow CDR variables that have been collected after channel was created to be visible during call */ 04693 ast_cdr_update(c); 04694 } 04695 for (;;) { 04696 char dst_exten[256]; /* buffer to accumulate digits */ 04697 int pos = 0; /* XXX should check bounds */ 04698 int digit = 0; 04699 int invalid = 0; 04700 int timeout = 0; 04701 04702 /* loop on priorities in this context/exten */ 04703 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 04704 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 04705 &found, 1))) { 04706 if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT) 04707 && ast_exists_extension(c, c->context, "T", 1, 04708 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04709 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 04710 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04711 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04712 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 04713 } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT) 04714 && ast_exists_extension(c, c->context, "e", 1, 04715 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04716 pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT"); 04717 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04718 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04719 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 04720 } else if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04721 c->_softhangup &= ~AST_SOFTHANGUP_ASYNCGOTO; 04722 continue; 04723 } else if (ast_check_hangup(c)) { 04724 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 04725 c->exten, c->priority); 04726 error = 1; 04727 break; 04728 } 04729 c->priority++; 04730 } /* end while - from here on we can use 'break' to go out */ 04731 if (found && res) { 04732 /* Something bad happened, or a hangup has been requested. */ 04733 if (strchr("0123456789ABCDEF*#", res)) { 04734 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 04735 pos = 0; 04736 dst_exten[pos++] = digit = res; 04737 dst_exten[pos] = '\0'; 04738 } else if (res == AST_PBX_INCOMPLETE) { 04739 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 04740 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 04741 04742 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 04743 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 04744 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04745 invalid = 1; 04746 } else { 04747 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 04748 digit = 1; 04749 pos = strlen(dst_exten); 04750 } 04751 } else { 04752 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04753 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04754 04755 if ((res == AST_PBX_ERROR) 04756 && ast_exists_extension(c, c->context, "e", 1, 04757 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04758 /* if we are already on the 'e' exten, don't jump to it again */ 04759 if (!strcmp(c->exten, "e")) { 04760 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); 04761 error = 1; 04762 } else { 04763 pbx_builtin_raise_exception(c, "ERROR"); 04764 continue; 04765 } 04766 } 04767 04768 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04769 c->_softhangup &= ~AST_SOFTHANGUP_ASYNCGOTO; 04770 continue; 04771 } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT) 04772 && ast_exists_extension(c, c->context, "T", 1, 04773 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04774 set_ext_pri(c, "T", 1); 04775 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04776 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04777 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 04778 continue; 04779 } else { 04780 if (c->cdr) 04781 ast_cdr_update(c); 04782 error = 1; 04783 break; 04784 } 04785 } 04786 } 04787 if (error) 04788 break; 04789 04790 /*!\note 04791 * We get here on a failure of some kind: non-existing extension or 04792 * hangup. We have options, here. We can either catch the failure 04793 * and continue, or we can drop out entirely. */ 04794 04795 if (invalid 04796 || !ast_exists_extension(c, c->context, c->exten, 1, 04797 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04798 /*!\note 04799 * If there is no match at priority 1, it is not a valid extension anymore. 04800 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 04801 * neither exist. 04802 */ 04803 if (ast_exists_extension(c, c->context, "i", 1, 04804 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04805 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 04806 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 04807 set_ext_pri(c, "i", 1); 04808 } else if (ast_exists_extension(c, c->context, "e", 1, 04809 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04810 pbx_builtin_raise_exception(c, "INVALID"); 04811 } else { 04812 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 04813 c->name, c->exten, c->context); 04814 error = 1; /* we know what to do with it */ 04815 break; 04816 } 04817 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 04818 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 04819 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 04820 } else { /* keypress received, get more digits for a full extension */ 04821 int waittime = 0; 04822 if (digit) 04823 waittime = c->pbx->dtimeoutms; 04824 else if (!autofallthrough) 04825 waittime = c->pbx->rtimeoutms; 04826 if (!waittime) { 04827 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 04828 if (!status) 04829 status = "UNKNOWN"; 04830 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 04831 if (!strcasecmp(status, "CONGESTION")) 04832 res = pbx_builtin_congestion(c, "10"); 04833 else if (!strcasecmp(status, "CHANUNAVAIL")) 04834 res = pbx_builtin_congestion(c, "10"); 04835 else if (!strcasecmp(status, "BUSY")) 04836 res = pbx_builtin_busy(c, "10"); 04837 error = 1; /* XXX disable message */ 04838 break; /* exit from the 'for' loop */ 04839 } 04840 04841 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 04842 break; 04843 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 04844 timeout = 1; 04845 if (!timeout 04846 && ast_exists_extension(c, c->context, dst_exten, 1, 04847 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 04848 set_ext_pri(c, dst_exten, 1); 04849 } else { 04850 /* No such extension */ 04851 if (!timeout && !ast_strlen_zero(dst_exten)) { 04852 /* An invalid extension */ 04853 if (ast_exists_extension(c, c->context, "i", 1, 04854 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04855 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 04856 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 04857 set_ext_pri(c, "i", 1); 04858 } else if (ast_exists_extension(c, c->context, "e", 1, 04859 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04860 pbx_builtin_raise_exception(c, "INVALID"); 04861 } else { 04862 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 04863 found = 1; /* XXX disable message */ 04864 break; 04865 } 04866 } else { 04867 /* A simple timeout */ 04868 if (ast_exists_extension(c, c->context, "t", 1, 04869 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04870 ast_verb(3, "Timeout on %s\n", c->name); 04871 set_ext_pri(c, "t", 1); 04872 } else if (ast_exists_extension(c, c->context, "e", 1, 04873 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04874 pbx_builtin_raise_exception(c, "RESPONSETIMEOUT"); 04875 } else { 04876 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 04877 found = 1; /* XXX disable message */ 04878 break; 04879 } 04880 } 04881 } 04882 if (c->cdr) { 04883 ast_verb(2, "CDR updated on %s\n",c->name); 04884 ast_cdr_update(c); 04885 } 04886 } 04887 } 04888 04889 if (!found && !error) { 04890 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 04891 } 04892 04893 if (!args || !args->no_hangup_chan) { 04894 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 04895 } 04896 04897 if ((!args || !args->no_hangup_chan) 04898 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 04899 && ast_exists_extension(c, c->context, "h", 1, 04900 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04901 set_ext_pri(c, "h", 1); 04902 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 04903 ast_cdr_end(c->cdr); 04904 } 04905 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 04906 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 04907 &found, 1)) == 0) { 04908 c->priority++; 04909 } 04910 if (found && res) { 04911 /* Something bad happened, or a hangup has been requested. */ 04912 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04913 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04914 } 04915 } 04916 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 04917 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 04918 pbx_destroy(c->pbx); 04919 c->pbx = NULL; 04920 04921 if (!args || !args->no_hangup_chan) { 04922 ast_hangup(c); 04923 } 04924 04925 return 0; 04926 }
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 2308 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02309 { 02310 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02311 02312 #ifdef NEED_DEBUG_HERE 02313 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02314 #endif 02315 02316 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 02317 #ifdef NEED_DEBUG_HERE 02318 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02319 #endif 02320 return 1; 02321 } 02322 02323 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02324 int ld = strlen(data), lp = strlen(pattern); 02325 02326 if (lp < ld) { /* pattern too short, cannot match */ 02327 #ifdef NEED_DEBUG_HERE 02328 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02329 #endif 02330 return 0; 02331 } 02332 /* depending on the mode, accept full or partial match or both */ 02333 if (mode == E_MATCH) { 02334 #ifdef NEED_DEBUG_HERE 02335 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 02336 #endif 02337 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 02338 } 02339 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 02340 #ifdef NEED_DEBUG_HERE 02341 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02342 #endif 02343 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02344 } else { 02345 #ifdef NEED_DEBUG_HERE 02346 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02347 #endif 02348 return 0; 02349 } 02350 } 02351 pattern++; /* skip leading _ */ 02352 /* 02353 * XXX below we stop at '/' which is a separator for the CID info. However we should 02354 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02355 */ 02356 while (*data && *pattern && *pattern != '/') { 02357 const char *end; 02358 02359 if (*data == '-') { /* skip '-' in data (just a separator) */ 02360 data++; 02361 continue; 02362 } 02363 switch (toupper(*pattern)) { 02364 case '[': /* a range */ 02365 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 02366 if (end == NULL) { 02367 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02368 return 0; /* unconditional failure */ 02369 } 02370 for (pattern++; pattern != end; pattern++) { 02371 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02372 if (*data >= pattern[0] && *data <= pattern[2]) 02373 break; /* match found */ 02374 else { 02375 pattern += 2; /* skip a total of 3 chars */ 02376 continue; 02377 } 02378 } else if (*data == pattern[0]) 02379 break; /* match found */ 02380 } 02381 if (pattern == end) { 02382 #ifdef NEED_DEBUG_HERE 02383 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 02384 #endif 02385 return 0; 02386 } 02387 pattern = end; /* skip and continue */ 02388 break; 02389 case 'N': 02390 if (*data < '2' || *data > '9') { 02391 #ifdef NEED_DEBUG_HERE 02392 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 02393 #endif 02394 return 0; 02395 } 02396 break; 02397 case 'X': 02398 if (*data < '0' || *data > '9') { 02399 #ifdef NEED_DEBUG_HERE 02400 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 02401 #endif 02402 return 0; 02403 } 02404 break; 02405 case 'Z': 02406 if (*data < '1' || *data > '9') { 02407 #ifdef NEED_DEBUG_HERE 02408 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 02409 #endif 02410 return 0; 02411 } 02412 break; 02413 case '.': /* Must match, even with more digits */ 02414 #ifdef NEED_DEBUG_HERE 02415 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02416 #endif 02417 return 1; 02418 case '!': /* Early match */ 02419 #ifdef NEED_DEBUG_HERE 02420 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02421 #endif 02422 return 2; 02423 case ' ': 02424 case '-': /* Ignore these in patterns */ 02425 data--; /* compensate the final data++ */ 02426 break; 02427 default: 02428 if (*data != *pattern) { 02429 #ifdef NEED_DEBUG_HERE 02430 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02431 #endif 02432 return 0; 02433 } 02434 } 02435 data++; 02436 pattern++; 02437 } 02438 if (*data) /* data longer than pattern, no match */ { 02439 #ifdef NEED_DEBUG_HERE 02440 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02441 #endif 02442 return 0; 02443 } 02444 02445 /* 02446 * match so far, but ran off the end of the data. 02447 * Depending on what is next, determine match or not. 02448 */ 02449 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02450 #ifdef NEED_DEBUG_HERE 02451 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02452 #endif 02453 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02454 } else if (*pattern == '!') { /* early match */ 02455 #ifdef NEED_DEBUG_HERE 02456 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02457 #endif 02458 return 2; 02459 } else { /* partial match */ 02460 #ifdef NEED_DEBUG_HERE 02461 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02462 #endif 02463 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02464 } 02465 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 3151 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.
03152 { 03153 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03154 struct pbx_exception *exception = NULL; 03155 if (!ds || !ds->data) 03156 return -1; 03157 exception = ds->data; 03158 if (!strcasecmp(data, "REASON")) 03159 ast_copy_string(buf, exception->reason, buflen); 03160 else if (!strcasecmp(data, "CONTEXT")) 03161 ast_copy_string(buf, exception->context, buflen); 03162 else if (!strncasecmp(data, "EXTEN", 5)) 03163 ast_copy_string(buf, exception->exten, buflen); 03164 else if (!strcasecmp(data, "PRIORITY")) 03165 snprintf(buf, buflen, "%d", exception->priority); 03166 else 03167 return -1; 03168 return 0; 03169 }
static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3369 of file pbx.c.
References ast_custom_function::arguments, ast_free, 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::name, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, and ast_custom_function::syntax.
Referenced by __ast_custom_function_register().
03370 { 03371 #ifdef AST_XML_DOCS 03372 char *tmpxml; 03373 03374 /* Let's try to find it in the Documentation XML */ 03375 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03376 return 0; 03377 } 03378 03379 if (ast_string_field_init(acf, 128)) { 03380 return -1; 03381 } 03382 03383 /* load synopsis */ 03384 tmpxml = ast_xmldoc_build_synopsis("function", acf->name); 03385 ast_string_field_set(acf, synopsis, tmpxml); 03386 ast_free(tmpxml); 03387 03388 /* load description */ 03389 tmpxml = ast_xmldoc_build_description("function", acf->name); 03390 ast_string_field_set(acf, desc, tmpxml); 03391 ast_free(tmpxml); 03392 03393 /* load syntax */ 03394 tmpxml = ast_xmldoc_build_syntax("function", acf->name); 03395 ast_string_field_set(acf, syntax, tmpxml); 03396 ast_free(tmpxml); 03397 03398 /* load arguments */ 03399 tmpxml = ast_xmldoc_build_arguments("function", acf->name); 03400 ast_string_field_set(acf, arguments, tmpxml); 03401 ast_free(tmpxml); 03402 03403 /* load seealso */ 03404 tmpxml = ast_xmldoc_build_seealso("function", acf->name); 03405 ast_string_field_set(acf, seealso, tmpxml); 03406 ast_free(tmpxml); 03407 03408 acf->docsrc = AST_XML_DOC; 03409 #endif 03410 03411 return 0; 03412 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static] |
Definition at line 1944 of file pbx.c.
References add_pattern_node(), already_in_tree(), ast_copy_string(), ast_log(), ast_exten::cidmatch, compare_char(), match_char::deleted, match_char::exten, ast_exten::exten, 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().
01945 { 01946 struct match_char *m1 = NULL, *m2 = NULL, **m0; 01947 int specif; 01948 int already; 01949 int pattern = 0; 01950 char buf[256]; 01951 char extenbuf[512]; 01952 char *s1 = extenbuf; 01953 int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2; 01954 01955 01956 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 01957 01958 if (e1->matchcid && l1 <= sizeof(extenbuf)) { 01959 strcat(extenbuf, "/"); 01960 strcat(extenbuf, e1->cidmatch); 01961 } else if (l1 > sizeof(extenbuf)) { 01962 ast_log(LOG_ERROR, "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch); 01963 return 0; 01964 } 01965 #ifdef NEED_DEBUG 01966 ast_log(LOG_DEBUG, "Adding exten %s%c%s to tree\n", s1, e1->matchcid ? '/' : ' ', e1->matchcid ? e1->cidmatch : ""); 01967 #endif 01968 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 01969 m0 = &con->pattern_tree; 01970 already = 1; 01971 01972 if ( *s1 == '_') { 01973 pattern = 1; 01974 s1++; 01975 } 01976 while (*s1) { 01977 if (pattern && *s1 == '[' && *(s1 - 1) != '\\') { 01978 char *s2 = buf; 01979 buf[0] = 0; 01980 s1++; /* get past the '[' */ 01981 while (*s1 != ']' && *(s1 - 1) != '\\') { 01982 if (*s1 == '\\') { 01983 if (*(s1 + 1) == ']') { 01984 *s2++ = ']'; 01985 s1 += 2; 01986 } else if (*(s1 + 1) == '\\') { 01987 *s2++ = '\\'; 01988 s1 += 2; 01989 } else if (*(s1 + 1) == '-') { 01990 *s2++ = '-'; 01991 s1 += 2; 01992 } else if (*(s1 + 1) == '[') { 01993 *s2++ = '['; 01994 s1 += 2; 01995 } 01996 } else if (*s1 == '-') { /* remember to add some error checking to all this! */ 01997 char s3 = *(s1 - 1); 01998 char s4 = *(s1 + 1); 01999 for (s3++; s3 <= s4; s3++) { 02000 *s2++ = s3; 02001 } 02002 s1 += 2; 02003 } else if (*s1 == '\0') { 02004 ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf); 02005 break; 02006 } else { 02007 *s2++ = *s1++; 02008 } 02009 } 02010 *s2 = 0; /* null terminate the exploded range */ 02011 /* sort the characters */ 02012 02013 specif = strlen(buf); 02014 qsort(buf, specif, 1, compare_char); 02015 specif <<= 8; 02016 specif += buf[0]; 02017 } else if (*s1 == '-') { 02018 /* Skip dashes in patterns */ 02019 s1++; 02020 continue; 02021 } else { 02022 if (*s1 == '\\') { 02023 s1++; 02024 buf[0] = *s1; 02025 } else { 02026 if (pattern) { 02027 if (*s1 == 'n') { /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02028 *s1 = 'N'; 02029 } else if (*s1 == 'x') { 02030 *s1 = 'X'; 02031 } else if (*s1 == 'z') { 02032 *s1 = 'Z'; 02033 } 02034 } 02035 buf[0] = *s1; 02036 } 02037 buf[1] = 0; 02038 specif = 1; 02039 } 02040 m2 = 0; 02041 if (already && (m2 = already_in_tree(m1, buf, pattern)) && m2->next_char) { 02042 if (!(*(s1 + 1))) { /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten... 02043 a shorter pattern might win if the longer one doesn't match */ 02044 if (m2->exten) { 02045 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", m2->exten->exten, e1->exten); 02046 } 02047 m2->exten = e1; 02048 m2->deleted = 0; 02049 } 02050 m1 = m2->next_char; /* m1 points to the node to compare against */ 02051 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02052 } else { /* not already OR not m2 OR nor m2->next_char */ 02053 if (m2) { 02054 if (findonly) { 02055 return m2; 02056 } 02057 m1 = m2; /* while m0 stays the same */ 02058 } else { 02059 if (findonly) { 02060 return m1; 02061 } 02062 if (!(m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0))) { /* m1 is the node just added */ 02063 return NULL; 02064 } 02065 m0 = &m1->next_char; 02066 } 02067 if (!(*(s1 + 1))) { 02068 if (m2 && m2->exten) { 02069 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", m2->exten->exten, e1->exten); 02070 } 02071 m1->deleted = 0; 02072 m1->exten = e1; 02073 } 02074 02075 /* The 'already' variable is a mini-optimization designed to make it so that we 02076 * don't have to call already_in_tree when we know it will return false. 02077 */ 02078 already = 0; 02079 } 02080 s1++; /* advance to next char */ 02081 } 02082 return m1; 02083 }
static struct match_char * add_pattern_node | ( | struct ast_context * | con, | |
struct match_char * | current, | |||
char * | pattern, | |||
int | is_pattern, | |||
int | already, | |||
int | specificity, | |||
struct match_char ** | parent | |||
) | [static] |
Definition at line 1902 of file pbx.c.
References ast_calloc, insert_in_next_chars_alt_char_list(), match_char::next_char, and ast_context::pattern_tree.
Referenced by add_exten_to_pattern_tree().
01903 { 01904 struct match_char *m; 01905 01906 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern)))) { 01907 return NULL; 01908 } 01909 01910 /* strcpy is safe here since we know its size and have allocated 01911 * just enough space for when we allocated m 01912 */ 01913 strcpy(m->x, pattern); 01914 01915 /* the specificity scores are the same as used in the old 01916 pattern matcher. */ 01917 m->is_pattern = is_pattern; 01918 if (specificity == 1 && is_pattern && pattern[0] == 'N') 01919 m->specificity = 0x0832; 01920 else if (specificity == 1 && is_pattern && pattern[0] == 'Z') 01921 m->specificity = 0x0931; 01922 else if (specificity == 1 && is_pattern && pattern[0] == 'X') 01923 m->specificity = 0x0a30; 01924 else if (specificity == 1 && is_pattern && pattern[0] == '.') 01925 m->specificity = 0x18000; 01926 else if (specificity == 1 && is_pattern && pattern[0] == '!') 01927 m->specificity = 0x28000; 01928 else 01929 m->specificity = specificity; 01930 01931 if (!con->pattern_tree) { 01932 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01933 } else { 01934 if (already) { /* switch to the new regime (traversing vs appending)*/ 01935 insert_in_next_chars_alt_char_list(nextcharptr, m); 01936 } else { 01937 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01938 } 01939 } 01940 01941 return m; 01942 }
static int add_pri | ( | 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 7873 of file pbx.c.
References add_pri_lockopt(), and el.
Referenced by ast_add_extension2_lockopt().
07875 { 07876 return add_pri_lockopt(con, tmp, el, e, replace, 1); 07877 }
static int add_pri_lockopt | ( | struct ast_context * | con, | |
struct ast_exten * | tmp, | |||
struct ast_exten * | el, | |||
struct ast_exten * | e, | |||
int | replace, | |||
int | lockhints | |||
) | [static] |
add the extension in the priority chain.
0 | on success. | |
-1 | on failure. |
Definition at line 7884 of file pbx.c.
References ast_hashtab_insert_safe(), ast_exten::label, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, and ast_exten::priority.
Referenced by add_pri().
07886 { 07887 struct ast_exten *ep; 07888 struct ast_exten *eh=e; 07889 07890 for (ep = NULL; e ; ep = e, e = e->peer) { 07891 if (e->priority >= tmp->priority) 07892 break; 07893 } 07894 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 07895 ast_hashtab_insert_safe(eh->peer_table, tmp); 07896 07897 if (tmp->label) { 07898 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 07899 } 07900 ep->peer = tmp; 07901 return 0; /* success */ 07902 } 07903 if (e->priority == tmp->priority) { 07904 /* Can't have something exactly the same. Is this a 07905 replacement? If so, replace, otherwise, bonk. */ 07906 if (!replace) { 07907 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 07908 if (tmp->datad) { 07909 tmp->datad(tmp->data); 07910 /* if you free this, null it out */ 07911 tmp->data = NULL; 07912 } 07913 07914 ast_free(tmp); 07915 return -1; 07916 } 07917 /* we are replacing e, so copy the link fields and then update 07918 * whoever pointed to e to point to us 07919 */ 07920 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 07921 tmp->peer = e->peer; /* always meaningful */ 07922 if (ep) { /* We're in the peer list, just insert ourselves */ 07923 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 07924 07925 if (e->label) { 07926 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 07927 } 07928 07929 ast_hashtab_insert_safe(eh->peer_table,tmp); 07930 if (tmp->label) { 07931 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 07932 } 07933 07934 ep->peer = tmp; 07935 } else if (el) { /* We're the first extension. Take over e's functions */ 07936 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 07937 tmp->peer_table = e->peer_table; 07938 tmp->peer_label_table = e->peer_label_table; 07939 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 07940 ast_hashtab_insert_safe(tmp->peer_table,tmp); 07941 if (e->label) { 07942 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 07943 } 07944 if (tmp->label) { 07945 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07946 } 07947 07948 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07949 ast_hashtab_insert_safe(con->root_table, tmp); 07950 el->next = tmp; 07951 /* The pattern trie points to this exten; replace the pointer, 07952 and all will be well */ 07953 if (x) { /* if the trie isn't formed yet, don't sweat this */ 07954 if (x->exten) { /* this test for safety purposes */ 07955 x->exten = tmp; /* replace what would become a bad pointer */ 07956 } else { 07957 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 07958 } 07959 } 07960 } else { /* We're the very first extension. */ 07961 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 07962 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07963 ast_hashtab_insert_safe(con->root_table, tmp); 07964 tmp->peer_table = e->peer_table; 07965 tmp->peer_label_table = e->peer_label_table; 07966 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 07967 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07968 if (e->label) { 07969 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 07970 } 07971 if (tmp->label) { 07972 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07973 } 07974 07975 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07976 ast_hashtab_insert_safe(con->root_table, tmp); 07977 con->root = tmp; 07978 /* The pattern trie points to this exten; replace the pointer, 07979 and all will be well */ 07980 if (x) { /* if the trie isn't formed yet; no problem */ 07981 if (x->exten) { /* this test for safety purposes */ 07982 x->exten = tmp; /* replace what would become a bad pointer */ 07983 } else { 07984 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 07985 } 07986 } 07987 } 07988 if (tmp->priority == PRIORITY_HINT) 07989 ast_change_hint(e,tmp); 07990 /* Destroy the old one */ 07991 if (e->datad) 07992 e->datad(e->data); 07993 ast_free(e); 07994 } else { /* Slip ourselves in just before e */ 07995 tmp->peer = e; 07996 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 07997 if (ep) { /* Easy enough, we're just in the peer list */ 07998 if (tmp->label) { 07999 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08000 } 08001 ast_hashtab_insert_safe(eh->peer_table, tmp); 08002 ep->peer = tmp; 08003 } else { /* we are the first in some peer list, so link in the ext list */ 08004 tmp->peer_table = e->peer_table; 08005 tmp->peer_label_table = e->peer_label_table; 08006 e->peer_table = 0; 08007 e->peer_label_table = 0; 08008 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08009 if (tmp->label) { 08010 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08011 } 08012 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08013 ast_hashtab_insert_safe(con->root_table, tmp); 08014 if (el) 08015 el->next = tmp; /* in the middle... */ 08016 else 08017 con->root = tmp; /* ... or at the head */ 08018 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 08019 } 08020 /* And immediately return success. */ 08021 if (tmp->priority == PRIORITY_HINT) { 08022 if (lockhints) { 08023 ast_add_hint(tmp); 08024 } else { 08025 ast_add_hint(tmp); 08026 } 08027 } 08028 } 08029 return 0; 08030 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat, | |||
int | is_pattern | |||
) | [static] |
Definition at line 1847 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01848 { 01849 struct match_char *t; 01850 01851 if (!current) { 01852 return 0; 01853 } 01854 01855 for (t = current; t; t = t->alt_char) { 01856 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01857 return t; 01858 } 01859 } 01860 01861 return 0; 01862 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5064 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05065 { 05066 return countcalls; 05067 }
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 7736 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state(), ast_extension_state_add(), handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().
07739 { 07740 int ret = -1; 07741 struct ast_context *c = find_context_locked(context); 07742 07743 if (c) { 07744 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 07745 application, data, datad, registrar); 07746 ast_unlock_contexts(); 07747 } 07748 07749 return ret; 07750 }
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 8057 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), build_parkinglot(), context_merge(), load_module(), manage_parkinglot(), park_call_full(), and pbx_load_users().
08061 { 08062 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 08063 }
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 | lockconts, | |||
int | lockhints | |||
) | [static] |
Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held.
Definition at line 8070 of file pbx.c.
References add_exten_to_pattern_tree(), add_pri(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_release(), 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().
08074 { 08075 /* 08076 * Sort extensions (or patterns) according to the rules indicated above. 08077 * These are implemented by the function ext_cmp()). 08078 * All priorities for the same ext/pattern/cid are kept in a list, 08079 * using the 'peer' field as a link field.. 08080 */ 08081 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 08082 int res; 08083 int length; 08084 char *p; 08085 char expand_buf[VAR_BUF_SIZE]; 08086 struct ast_exten dummy_exten = {0}; 08087 char dummy_name[1024]; 08088 08089 if (ast_strlen_zero(extension)) { 08090 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", 08091 con->name); 08092 return -1; 08093 } 08094 08095 /* If we are adding a hint evalulate in variables and global variables */ 08096 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 08097 struct ast_channel *c = ast_dummy_channel_alloc(); 08098 ast_copy_string(c->exten, extension, sizeof(c->exten)); 08099 ast_copy_string(c->context, con->name, sizeof(c->context)); 08100 08101 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 08102 application = expand_buf; 08103 ast_channel_release(c); 08104 } 08105 08106 length = sizeof(struct ast_exten); 08107 length += strlen(extension) + 1; 08108 length += strlen(application) + 1; 08109 if (label) 08110 length += strlen(label) + 1; 08111 if (callerid) 08112 length += strlen(callerid) + 1; 08113 else 08114 length ++; /* just the '\0' */ 08115 08116 /* Be optimistic: Build the extension structure first */ 08117 if (!(tmp = ast_calloc(1, length))) 08118 return -1; 08119 08120 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 08121 label = 0; 08122 08123 /* use p as dst in assignments, as the fields are const char * */ 08124 p = tmp->stuff; 08125 if (label) { 08126 tmp->label = p; 08127 strcpy(p, label); 08128 p += strlen(label) + 1; 08129 } 08130 tmp->exten = p; 08131 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 08132 tmp->priority = priority; 08133 tmp->cidmatch = p; /* but use p for assignments below */ 08134 08135 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 08136 if (callerid) { 08137 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 08138 tmp->matchcid = 1; 08139 } else { 08140 *p++ = '\0'; 08141 tmp->matchcid = 0; 08142 } 08143 tmp->app = p; 08144 strcpy(p, application); 08145 tmp->parent = con; 08146 tmp->data = data; 08147 tmp->datad = datad; 08148 tmp->registrar = registrar; 08149 08150 if (lockconts) { 08151 ast_wrlock_context(con); 08152 } 08153 08154 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 08155 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 08156 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 08157 dummy_exten.exten = dummy_name; 08158 dummy_exten.matchcid = 0; 08159 dummy_exten.cidmatch = 0; 08160 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 08161 if (!tmp2) { 08162 /* hmmm, not in the trie; */ 08163 add_exten_to_pattern_tree(con, tmp, 0); 08164 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 08165 } 08166 } 08167 res = 0; /* some compilers will think it is uninitialized otherwise */ 08168 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 08169 res = ext_cmp(e->exten, tmp->exten); 08170 if (res == 0) { /* extension match, now look at cidmatch */ 08171 if (!e->matchcid && !tmp->matchcid) 08172 res = 0; 08173 else if (tmp->matchcid && !e->matchcid) 08174 res = 1; 08175 else if (e->matchcid && !tmp->matchcid) 08176 res = -1; 08177 else 08178 res = ext_cmp(e->cidmatch, tmp->cidmatch); 08179 } 08180 if (res >= 0) 08181 break; 08182 } 08183 if (e && res == 0) { /* exact match, insert in the pri chain */ 08184 res = add_pri(con, tmp, el, e, replace); 08185 if (lockconts) { 08186 ast_unlock_context(con); 08187 } 08188 if (res < 0) { 08189 errno = EEXIST; /* XXX do we care ? */ 08190 return 0; /* XXX should we return -1 maybe ? */ 08191 } 08192 } else { 08193 /* 08194 * not an exact match, this is the first entry with this pattern, 08195 * so insert in the main list right before 'e' (if any) 08196 */ 08197 tmp->next = e; 08198 if (el) { /* there is another exten already in this context */ 08199 el->next = tmp; 08200 tmp->peer_table = ast_hashtab_create(13, 08201 hashtab_compare_exten_numbers, 08202 ast_hashtab_resize_java, 08203 ast_hashtab_newsize_java, 08204 hashtab_hash_priority, 08205 0); 08206 tmp->peer_label_table = ast_hashtab_create(7, 08207 hashtab_compare_exten_labels, 08208 ast_hashtab_resize_java, 08209 ast_hashtab_newsize_java, 08210 hashtab_hash_labels, 08211 0); 08212 if (label) { 08213 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08214 } 08215 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08216 } else { /* this is the first exten in this context */ 08217 if (!con->root_table) 08218 con->root_table = ast_hashtab_create(27, 08219 hashtab_compare_extens, 08220 ast_hashtab_resize_java, 08221 ast_hashtab_newsize_java, 08222 hashtab_hash_extens, 08223 0); 08224 con->root = tmp; 08225 con->root->peer_table = ast_hashtab_create(13, 08226 hashtab_compare_exten_numbers, 08227 ast_hashtab_resize_java, 08228 ast_hashtab_newsize_java, 08229 hashtab_hash_priority, 08230 0); 08231 con->root->peer_label_table = ast_hashtab_create(7, 08232 hashtab_compare_exten_labels, 08233 ast_hashtab_resize_java, 08234 ast_hashtab_newsize_java, 08235 hashtab_hash_labels, 08236 0); 08237 if (label) { 08238 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 08239 } 08240 ast_hashtab_insert_safe(con->root->peer_table, tmp); 08241 08242 } 08243 ast_hashtab_insert_safe(con->root_table, tmp); 08244 if (lockconts) { 08245 ast_unlock_context(con); 08246 } 08247 if (tmp->priority == PRIORITY_HINT) { 08248 if (lockhints) { 08249 ast_add_hint(tmp); 08250 } else { 08251 ast_add_hint(tmp); 08252 } 08253 } 08254 } 08255 if (option_debug) { 08256 if (tmp->matchcid) { 08257 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 08258 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 08259 } else { 08260 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 08261 tmp->exten, tmp->priority, con->name, con); 08262 } 08263 } 08264 08265 if (tmp->matchcid) { 08266 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 08267 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 08268 } else { 08269 ast_verb(3, "Added extension '%s' priority %d to %s\n", 08270 tmp->exten, tmp->priority, con->name); 08271 } 08272 08273 return 0; 08274 }
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 7717 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
07720 { 07721 int ret = -1; 07722 struct ast_context *c = find_context(context); 07723 07724 if (c) { 07725 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 07726 application, data, datad, registrar, 0, 0); 07727 } 07728 07729 return ret; 07730 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 4453 of file pbx.c.
References ao2_alloc, ao2_find, ao2_link, ao2_ref, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), and hints.
Referenced by ast_add_extension2_lockopt().
04454 { 04455 struct ast_hint *hint; 04456 04457 if (!e) { 04458 return -1; 04459 } 04460 04461 /* Search if hint exists, do nothing */ 04462 hint = ao2_find(hints, e, 0); 04463 if (hint) { 04464 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 04465 ao2_ref(hint, -1); 04466 return -1; 04467 } 04468 04469 ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 04470 04471 if (!(hint = ao2_alloc(sizeof(*hint), NULL))) { 04472 return -1; 04473 } 04474 04475 /* Initialize and insert new item at the top */ 04476 hint->exten = e; 04477 hint->laststate = ast_extension_state2(e); 04478 04479 ao2_link(hints, hint); 04480 04481 ao2_ref(hint, -1); 04482 04483 return 0; 04484 }
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 7775 of file pbx.c.
References ast_channel::_state, ast_channel::accountcode, ast_channel::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_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().
07776 { 07777 int res = 0; 07778 07779 ast_channel_lock(chan); 07780 07781 if (chan->pbx) { /* This channel is currently in the PBX */ 07782 ast_explicit_goto(chan, context, exten, priority + 1); 07783 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 07784 } else { 07785 /* In order to do it when the channel doesn't really exist within 07786 the PBX, we have to make a new channel, masquerade, and start the PBX 07787 at the new location */ 07788 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->linkedid, chan->amaflags, "AsyncGoto/%s", chan->name); 07789 if (!tmpchan) { 07790 res = -1; 07791 } else { 07792 if (chan->cdr) { 07793 ast_cdr_discard(tmpchan->cdr); 07794 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 07795 } 07796 /* Make formats okay */ 07797 tmpchan->readformat = chan->readformat; 07798 tmpchan->writeformat = chan->writeformat; 07799 /* Setup proper location */ 07800 ast_explicit_goto(tmpchan, 07801 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 07802 07803 /* Masquerade into temp channel */ 07804 if (ast_channel_masquerade(tmpchan, chan)) { 07805 /* Failed to set up the masquerade. It's probably chan_local 07806 * in the middle of optimizing itself out. Sad. :( */ 07807 ast_hangup(tmpchan); 07808 tmpchan = NULL; 07809 res = -1; 07810 } else { 07811 /* it may appear odd to unlock chan here since the masquerade is on 07812 * tmpchan, but no channel locks should be held when doing a masquerade 07813 * since a masquerade requires a lock on the channels ao2 container. */ 07814 ast_channel_unlock(chan); 07815 ast_do_masquerade(tmpchan); 07816 ast_channel_lock(chan); 07817 /* Start the PBX going on our stolen channel */ 07818 if (ast_pbx_start(tmpchan)) { 07819 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 07820 ast_hangup(tmpchan); 07821 res = -1; 07822 } 07823 } 07824 } 07825 } 07826 ast_channel_unlock(chan); 07827 return res; 07828 }
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 7830 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
07831 { 07832 struct ast_channel *chan; 07833 int res = -1; 07834 07835 if ((chan = ast_channel_get_by_name(channame))) { 07836 res = ast_async_goto(chan, context, exten, priority); 07837 chan = ast_channel_unref(chan); 07838 } 07839 07840 return res; 07841 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10133 of file pbx.c.
References __ast_goto_if_exists().
10134 { 10135 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10136 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10198 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10199 { 10200 return pbx_parseable_goto(chan, goto_string, 1); 10201 }
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 7366 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().
07367 { 07368 char *info_save, *info; 07369 int j, num_fields, last_sep = -1; 07370 07371 /* Check for empty just in case */ 07372 if (ast_strlen_zero(info_in)) { 07373 return 0; 07374 } 07375 07376 /* make a copy just in case we were passed a static string */ 07377 info_save = info = ast_strdupa(info_in); 07378 07379 /* count the number of fields in the timespec */ 07380 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07381 if (info[j] == ',') { 07382 last_sep = j; 07383 num_fields++; 07384 } 07385 } 07386 07387 /* save the timezone, if it is specified */ 07388 if (num_fields == 5) { 07389 i->timezone = ast_strdup(info + last_sep + 1); 07390 } else { 07391 i->timezone = NULL; 07392 } 07393 07394 /* Assume everything except time */ 07395 i->monthmask = 0xfff; /* 12 bits */ 07396 i->daymask = 0x7fffffffU; /* 31 bits */ 07397 i->dowmask = 0x7f; /* 7 bits */ 07398 /* on each call, use strsep() to move info to the next argument */ 07399 get_timerange(i, strsep(&info, "|,")); 07400 if (info) 07401 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07402 if (info) 07403 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07404 if (info) 07405 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07406 return 1; 07407 }
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 4593 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
04594 { 04595 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04596 }
Change hint for an extension.
Definition at line 4487 of file pbx.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::exten, and hints.
04488 { 04489 struct ast_hint *hint; 04490 04491 hint = ao2_find(hints, oe, 0); 04492 04493 if (!hint) { 04494 return -1; 04495 } 04496 04497 ao2_lock(hint); 04498 hint->exten = ne; 04499 ao2_unlock(hint); 04500 ao2_ref(hint, -1); 04501 04502 return 0; 04503 }
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 7409 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07410 { 07411 return ast_check_timing2(i, ast_tvnow()); 07412 }
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 7414 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().
07415 { 07416 struct ast_tm tm; 07417 07418 ast_localtime(&tv, &tm, i->timezone); 07419 07420 /* If it's not the right month, return */ 07421 if (!(i->monthmask & (1 << tm.tm_mon))) 07422 return 0; 07423 07424 /* If it's not that time of the month.... */ 07425 /* Warning, tm_mday has range 1..31! */ 07426 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07427 return 0; 07428 07429 /* If it's not the right day of the week */ 07430 if (!(i->dowmask & (1 << tm.tm_wday))) 07431 return 0; 07432 07433 /* Sanity check the hour just to be safe */ 07434 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07435 ast_log(LOG_WARNING, "Insane time...\n"); 07436 return 0; 07437 } 07438 07439 /* Now the tough part, we calculate if it fits 07440 in the right time based on min/hour */ 07441 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)))) 07442 return 0; 07443 07444 /* If we got this far, then we're good */ 07445 return 1; 07446 }
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 10203 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().
10204 { 10205 struct ast_app *app = NULL; 10206 int which = 0; 10207 char *ret = NULL; 10208 size_t wordlen = strlen(word); 10209 10210 AST_RWLIST_RDLOCK(&apps); 10211 AST_RWLIST_TRAVERSE(&apps, app, list) { 10212 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10213 ret = ast_strdup(app->name); 10214 break; 10215 } 10216 } 10217 AST_RWLIST_UNLOCK(&apps); 10218 10219 return ret; 10220 }
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 7648 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
07649 { 07650 int ret = -1; 07651 struct ast_context *c = find_context_locked(context); 07652 07653 if (c) { 07654 ret = ast_context_add_ignorepat2(c, value, registrar); 07655 ast_unlock_contexts(); 07656 } 07657 return ret; 07658 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 7660 of file pbx.c.
References ast_calloc, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().
07661 { 07662 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 07663 int length; 07664 char *pattern; 07665 length = sizeof(struct ast_ignorepat); 07666 length += strlen(value) + 1; 07667 if (!(ignorepat = ast_calloc(1, length))) 07668 return -1; 07669 /* The cast to char * is because we need to write the initial value. 07670 * The field is not supposed to be modified otherwise. Also, gcc 4.2 07671 * sees the cast as dereferencing a type-punned pointer and warns about 07672 * it. This is the workaround (we're telling gcc, yes, that's really 07673 * what we wanted to do). 07674 */ 07675 pattern = (char *) ignorepat->pattern; 07676 strcpy(pattern, value); 07677 ignorepat->next = NULL; 07678 ignorepat->registrar = registrar; 07679 ast_wrlock_context(con); 07680 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 07681 ignorepatl = ignorepatc; 07682 if (!strcasecmp(ignorepatc->pattern, value)) { 07683 /* Already there */ 07684 ast_unlock_context(con); 07685 errno = EEXIST; 07686 return -1; 07687 } 07688 } 07689 if (ignorepatl) 07690 ignorepatl->next = ignorepat; 07691 else 07692 con->ignorepats = ignorepat; 07693 ast_unlock_context(con); 07694 return 0; 07695 07696 }
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 7195 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07196 { 07197 int ret = -1; 07198 struct ast_context *c = find_context_locked(context); 07199 07200 if (c) { 07201 ret = ast_context_add_include2(c, include, registrar); 07202 ast_unlock_contexts(); 07203 } 07204 return ret; 07205 }
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 7463 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().
07465 { 07466 struct ast_include *new_include; 07467 char *c; 07468 struct ast_include *i, *il = NULL; /* include, include_last */ 07469 int length; 07470 char *p; 07471 07472 length = sizeof(struct ast_include); 07473 length += 2 * (strlen(value) + 1); 07474 07475 /* allocate new include structure ... */ 07476 if (!(new_include = ast_calloc(1, length))) 07477 return -1; 07478 /* Fill in this structure. Use 'p' for assignments, as the fields 07479 * in the structure are 'const char *' 07480 */ 07481 p = new_include->stuff; 07482 new_include->name = p; 07483 strcpy(p, value); 07484 p += strlen(value) + 1; 07485 new_include->rname = p; 07486 strcpy(p, value); 07487 /* Strip off timing info, and process if it is there */ 07488 if ( (c = strchr(p, ',')) ) { 07489 *c++ = '\0'; 07490 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07491 } 07492 new_include->next = NULL; 07493 new_include->registrar = registrar; 07494 07495 ast_wrlock_context(con); 07496 07497 /* ... go to last include and check if context is already included too... */ 07498 for (i = con->includes; i; i = i->next) { 07499 if (!strcasecmp(i->name, new_include->name)) { 07500 ast_destroy_timing(&(new_include->timing)); 07501 ast_free(new_include); 07502 ast_unlock_context(con); 07503 errno = EEXIST; 07504 return -1; 07505 } 07506 il = i; 07507 } 07508 07509 /* ... include new context into context list, unlock, return */ 07510 if (il) 07511 il->next = new_include; 07512 else 07513 con->includes = new_include; 07514 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07515 07516 ast_unlock_context(con); 07517 07518 return 0; 07519 }
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 7526 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07527 { 07528 int ret = -1; 07529 struct ast_context *c = find_context_locked(context); 07530 07531 if (c) { /* found, add switch to this context */ 07532 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07533 ast_unlock_contexts(); 07534 } 07535 return ret; 07536 }
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 7545 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().
07547 { 07548 struct ast_sw *new_sw; 07549 struct ast_sw *i; 07550 int length; 07551 char *p; 07552 07553 length = sizeof(struct ast_sw); 07554 length += strlen(value) + 1; 07555 if (data) 07556 length += strlen(data); 07557 length++; 07558 07559 /* allocate new sw structure ... */ 07560 if (!(new_sw = ast_calloc(1, length))) 07561 return -1; 07562 /* ... fill in this structure ... */ 07563 p = new_sw->stuff; 07564 new_sw->name = p; 07565 strcpy(new_sw->name, value); 07566 p += strlen(value) + 1; 07567 new_sw->data = p; 07568 if (data) { 07569 strcpy(new_sw->data, data); 07570 p += strlen(data) + 1; 07571 } else { 07572 strcpy(new_sw->data, ""); 07573 p++; 07574 } 07575 new_sw->eval = eval; 07576 new_sw->registrar = registrar; 07577 07578 /* ... try to lock this context ... */ 07579 ast_wrlock_context(con); 07580 07581 /* ... go to last sw and check if context is already swd too... */ 07582 AST_LIST_TRAVERSE(&con->alts, i, list) { 07583 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07584 ast_free(new_sw); 07585 ast_unlock_context(con); 07586 errno = EEXIST; 07587 return -1; 07588 } 07589 } 07590 07591 /* ... sw new context into context list, unlock, return */ 07592 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07593 07594 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07595 07596 ast_unlock_context(con); 07597 07598 return 0; 07599 }
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 8869 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), sla_destroy(), and unload_module().
08870 { 08871 ast_wrlock_contexts(); 08872 __ast_context_destroy(contexts, contexts_table, con,registrar); 08873 ast_unlock_contexts(); 08874 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2512 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_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
02513 { 02514 struct ast_context *tmp = NULL; 02515 struct fake_context item; 02516 02517 ast_copy_string(item.name, name, sizeof(item.name)); 02518 02519 ast_rdlock_contexts(); 02520 if( contexts_table ) { 02521 tmp = ast_hashtab_lookup(contexts_table,&item); 02522 } else { 02523 while ( (tmp = ast_walk_contexts(tmp)) ) { 02524 if (!name || !strcasecmp(name, tmp->name)) { 02525 break; 02526 } 02527 } 02528 } 02529 ast_unlock_contexts(); 02530 return tmp; 02531 }
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 6848 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 build_parkinglot(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), and set_config().
06849 { 06850 struct ast_context *tmp, **local_contexts; 06851 struct fake_context search; 06852 int length = sizeof(struct ast_context) + strlen(name) + 1; 06853 06854 if (!contexts_table) { 06855 contexts_table = ast_hashtab_create(17, 06856 ast_hashtab_compare_contexts, 06857 ast_hashtab_resize_java, 06858 ast_hashtab_newsize_java, 06859 ast_hashtab_hash_contexts, 06860 0); 06861 } 06862 06863 ast_copy_string(search.name, name, sizeof(search.name)); 06864 if (!extcontexts) { 06865 ast_rdlock_contexts(); 06866 local_contexts = &contexts; 06867 tmp = ast_hashtab_lookup(contexts_table, &search); 06868 ast_unlock_contexts(); 06869 if (tmp) { 06870 tmp->refcount++; 06871 return tmp; 06872 } 06873 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 06874 local_contexts = extcontexts; 06875 tmp = ast_hashtab_lookup(exttable, &search); 06876 if (tmp) { 06877 tmp->refcount++; 06878 return tmp; 06879 } 06880 } 06881 06882 if ((tmp = ast_calloc(1, length))) { 06883 ast_rwlock_init(&tmp->lock); 06884 ast_mutex_init(&tmp->macrolock); 06885 strcpy(tmp->name, name); 06886 tmp->root = NULL; 06887 tmp->root_table = NULL; 06888 tmp->registrar = ast_strdup(registrar); 06889 tmp->includes = NULL; 06890 tmp->ignorepats = NULL; 06891 tmp->refcount = 1; 06892 } else { 06893 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 06894 return NULL; 06895 } 06896 06897 if (!extcontexts) { 06898 ast_wrlock_contexts(); 06899 tmp->next = *local_contexts; 06900 *local_contexts = tmp; 06901 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 06902 ast_unlock_contexts(); 06903 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06904 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 06905 } else { 06906 tmp->next = *local_contexts; 06907 if (exttable) 06908 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 06909 06910 *local_contexts = tmp; 06911 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06912 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 06913 } 06914 return tmp; 06915 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 5444 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_mutex_lock, ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
05445 { 05446 struct ast_context *c = NULL; 05447 int ret = -1; 05448 struct fake_context item; 05449 05450 ast_rdlock_contexts(); 05451 05452 ast_copy_string(item.name, context, sizeof(item.name)); 05453 05454 c = ast_hashtab_lookup(contexts_table,&item); 05455 if (c) 05456 ret = 0; 05457 ast_unlock_contexts(); 05458 05459 /* if we found context, lock macrolock */ 05460 if (ret == 0) { 05461 ret = ast_mutex_lock(&c->macrolock); 05462 } 05463 05464 return ret; 05465 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
context | context to remove extension from | |
extension | which extension to remove | |
priority | priority of extension to remove (0 to remove all) | |
registrar | registrar of the extension |
0 | on success | |
-1 | on failure |
Definition at line 5252 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
05253 { 05254 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05255 }
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 5279 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), park_exec_full(), and unload_module().
05280 { 05281 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05282 }
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 5257 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().
05258 { 05259 int ret = -1; /* default error return */ 05260 struct ast_context *c = find_context_locked(context); 05261 05262 if (c) { /* ... remove extension ... */ 05263 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 05264 ast_unlock_contexts(); 05265 } 05266 return ret; 05267 }
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 5284 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().
05285 { 05286 struct ast_exten *exten, *prev_exten = NULL; 05287 struct ast_exten *peer; 05288 struct ast_exten ex, *exten2, *exten3; 05289 char dummy_name[1024]; 05290 struct ast_exten *previous_peer = NULL; 05291 struct ast_exten *next_peer = NULL; 05292 int found = 0; 05293 05294 if (!already_locked) 05295 ast_wrlock_context(con); 05296 05297 /* Handle this is in the new world */ 05298 05299 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05300 * peers, not just those matching the callerid. */ 05301 #ifdef NEED_DEBUG 05302 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05303 #endif 05304 #ifdef CONTEXT_DEBUG 05305 check_contexts(__FILE__, __LINE__); 05306 #endif 05307 /* find this particular extension */ 05308 ex.exten = dummy_name; 05309 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05310 ex.cidmatch = callerid; 05311 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05312 exten = ast_hashtab_lookup(con->root_table, &ex); 05313 if (exten) { 05314 if (priority == 0) { 05315 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05316 if (!exten2) 05317 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); 05318 if (con->pattern_tree) { 05319 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05320 05321 if (x->exten) { /* this test for safety purposes */ 05322 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05323 x->exten = 0; /* get rid of what will become a bad pointer */ 05324 } else { 05325 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05326 } 05327 } 05328 } else { 05329 ex.priority = priority; 05330 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05331 if (exten2) { 05332 05333 if (exten2->label) { /* if this exten has a label, remove that, too */ 05334 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05335 if (!exten3) 05336 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); 05337 } 05338 05339 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05340 if (!exten3) 05341 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); 05342 if (exten2 == exten && exten2->peer) { 05343 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05344 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05345 } 05346 if (ast_hashtab_size(exten->peer_table) == 0) { 05347 /* well, if the last priority of an exten is to be removed, 05348 then, the extension is removed, too! */ 05349 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05350 if (!exten3) 05351 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05352 if (con->pattern_tree) { 05353 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05354 if (x->exten) { /* this test for safety purposes */ 05355 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05356 x->exten = 0; /* get rid of what will become a bad pointer */ 05357 } 05358 } 05359 } 05360 } else { 05361 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05362 priority, exten->exten, con->name); 05363 } 05364 } 05365 } else { 05366 /* hmmm? this exten is not in this pattern tree? */ 05367 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05368 extension, con->name); 05369 } 05370 #ifdef NEED_DEBUG 05371 if (con->pattern_tree) { 05372 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05373 log_match_char_tree(con->pattern_tree, " "); 05374 } 05375 #endif 05376 05377 /* scan the extension list to find first matching extension-registrar */ 05378 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05379 if (!strcmp(exten->exten, extension) && 05380 (!registrar || !strcmp(exten->registrar, registrar)) && 05381 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05382 break; 05383 } 05384 if (!exten) { 05385 /* we can't find right extension */ 05386 if (!already_locked) 05387 ast_unlock_context(con); 05388 return -1; 05389 } 05390 05391 /* scan the priority list to remove extension with exten->priority == priority */ 05392 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05393 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))); 05394 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05395 if ((priority == 0 || peer->priority == priority) && 05396 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05397 (!registrar || !strcmp(peer->registrar, registrar) )) { 05398 found = 1; 05399 05400 /* we are first priority extension? */ 05401 if (!previous_peer) { 05402 /* 05403 * We are first in the priority chain, so must update the extension chain. 05404 * The next node is either the next priority or the next extension 05405 */ 05406 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05407 if (peer->peer) { 05408 /* move the peer_table and peer_label_table down to the next peer, if 05409 it is there */ 05410 peer->peer->peer_table = peer->peer_table; 05411 peer->peer->peer_label_table = peer->peer_label_table; 05412 peer->peer_table = NULL; 05413 peer->peer_label_table = NULL; 05414 } 05415 if (!prev_exten) { /* change the root... */ 05416 con->root = next_node; 05417 } else { 05418 prev_exten->next = next_node; /* unlink */ 05419 } 05420 if (peer->peer) { /* update the new head of the pri list */ 05421 peer->peer->next = peer->next; 05422 } 05423 } else { /* easy, we are not first priority in extension */ 05424 previous_peer->peer = peer->peer; 05425 } 05426 05427 /* now, free whole priority extension */ 05428 destroy_exten(peer); 05429 } else { 05430 previous_peer = peer; 05431 } 05432 } 05433 if (!already_locked) 05434 ast_unlock_context(con); 05435 return found ? 0 : -1; 05436 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7605 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07606 { 07607 int ret = -1; 07608 struct ast_context *c = find_context_locked(context); 07609 07610 if (c) { 07611 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 07612 ast_unlock_contexts(); 07613 } 07614 return ret; 07615 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7617 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().
07618 { 07619 struct ast_ignorepat *ip, *ipl = NULL; 07620 07621 ast_wrlock_context(con); 07622 07623 for (ip = con->ignorepats; ip; ip = ip->next) { 07624 if (!strcmp(ip->pattern, ignorepat) && 07625 (!registrar || (registrar == ip->registrar))) { 07626 if (ipl) { 07627 ipl->next = ip->next; 07628 ast_free(ip); 07629 } else { 07630 con->ignorepats = ip->next; 07631 ast_free(ip); 07632 } 07633 ast_unlock_context(con); 07634 return 0; 07635 } 07636 ipl = ip; 07637 } 07638 07639 ast_unlock_context(con); 07640 errno = EINVAL; 07641 return -1; 07642 }
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 5143 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05144 { 05145 int ret = -1; 05146 struct ast_context *c = find_context_locked(context); 05147 05148 if (c) { 05149 /* found, remove include from this context ... */ 05150 ret = ast_context_remove_include2(c, include, registrar); 05151 ast_unlock_contexts(); 05152 } 05153 return ret; 05154 }
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 5165 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().
05166 { 05167 struct ast_include *i, *pi = NULL; 05168 int ret = -1; 05169 05170 ast_wrlock_context(con); 05171 05172 /* find our include */ 05173 for (i = con->includes; i; pi = i, i = i->next) { 05174 if (!strcmp(i->name, include) && 05175 (!registrar || !strcmp(i->registrar, registrar))) { 05176 /* remove from list */ 05177 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05178 if (pi) 05179 pi->next = i->next; 05180 else 05181 con->includes = i->next; 05182 /* free include and return */ 05183 ast_destroy_timing(&(i->timing)); 05184 ast_free(i); 05185 ret = 0; 05186 break; 05187 } 05188 } 05189 05190 ast_unlock_context(con); 05191 05192 return ret; 05193 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 5200 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05201 { 05202 int ret = -1; /* default error return */ 05203 struct ast_context *c = find_context_locked(context); 05204 05205 if (c) { 05206 /* remove switch from this context ... */ 05207 ret = ast_context_remove_switch2(c, sw, data, registrar); 05208 ast_unlock_contexts(); 05209 } 05210 return ret; 05211 }
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 5221 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().
05222 { 05223 struct ast_sw *i; 05224 int ret = -1; 05225 05226 ast_wrlock_context(con); 05227 05228 /* walk switches */ 05229 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05230 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05231 (!registrar || !strcmp(i->registrar, registrar))) { 05232 /* found, remove from list */ 05233 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05234 AST_LIST_REMOVE_CURRENT(list); 05235 ast_free(i); /* free switch and return */ 05236 ret = 0; 05237 break; 05238 } 05239 } 05240 AST_LIST_TRAVERSE_SAFE_END; 05241 05242 ast_unlock_context(con); 05243 05244 return ret; 05245 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5472 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_mutex_unlock, ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
05473 { 05474 struct ast_context *c = NULL; 05475 int ret = -1; 05476 struct fake_context item; 05477 05478 ast_rdlock_contexts(); 05479 05480 ast_copy_string(item.name, context, sizeof(item.name)); 05481 05482 c = ast_hashtab_lookup(contexts_table,&item); 05483 if (c) 05484 ret = 0; 05485 ast_unlock_contexts(); 05486 05487 /* if we found context, unlock macrolock */ 05488 if (ret == 0) { 05489 ret = ast_mutex_unlock(&c->macrolock); 05490 } 05491 05492 return ret; 05493 }
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 10088 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().
10089 { 10090 struct ast_include *inc = NULL; 10091 int res = 0; 10092 10093 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10094 if (ast_context_find(inc->rname)) 10095 continue; 10096 10097 res = -1; 10098 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10099 ast_get_context_name(con), inc->rname); 10100 break; 10101 } 10102 10103 return res; 10104 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 3325 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().
03326 { 03327 struct ast_custom_function *acf = NULL; 03328 03329 AST_RWLIST_RDLOCK(&acf_root); 03330 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03331 if (!strcmp(name, acf->name)) 03332 break; 03333 } 03334 AST_RWLIST_UNLOCK(&acf_root); 03335 03336 return acf; 03337 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3339 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().
03340 { 03341 struct ast_custom_function *cur; 03342 03343 if (!acf) { 03344 return -1; 03345 } 03346 03347 AST_RWLIST_WRLOCK(&acf_root); 03348 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03349 #ifdef AST_XML_DOCS 03350 if (cur->docsrc == AST_XML_DOC) { 03351 ast_string_field_free_memory(acf); 03352 } 03353 #endif 03354 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03355 } 03356 AST_RWLIST_UNLOCK(&acf_root); 03357 03358 return cur ? 0 : -1; 03359 }
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 7448 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().
07449 { 07450 if (i->timezone) { 07451 ast_free(i->timezone); 07452 i->timezone = NULL; 07453 } 07454 return 0; 07455 }
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 4145 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_state2().
04146 { 04147 switch (devstate) { 04148 case AST_DEVICE_ONHOLD: 04149 return AST_EXTENSION_ONHOLD; 04150 case AST_DEVICE_BUSY: 04151 return AST_EXTENSION_BUSY; 04152 case AST_DEVICE_UNKNOWN: 04153 return AST_EXTENSION_NOT_INUSE; 04154 case AST_DEVICE_UNAVAILABLE: 04155 case AST_DEVICE_INVALID: 04156 return AST_EXTENSION_UNAVAILABLE; 04157 case AST_DEVICE_RINGINUSE: 04158 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04159 case AST_DEVICE_RINGING: 04160 return AST_EXTENSION_RINGING; 04161 case AST_DEVICE_INUSE: 04162 return AST_EXTENSION_INUSE; 04163 case AST_DEVICE_NOT_INUSE: 04164 return AST_EXTENSION_NOT_INUSE; 04165 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04166 break; 04167 } 04168 04169 return AST_EXTENSION_NOT_INUSE; 04170 }
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 4578 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(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().
04579 { 04580 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04581 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 7752 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().
07753 { 07754 if (!chan) 07755 return -1; 07756 07757 ast_channel_lock(chan); 07758 07759 if (!ast_strlen_zero(context)) 07760 ast_copy_string(chan->context, context, sizeof(chan->context)); 07761 if (!ast_strlen_zero(exten)) 07762 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07763 if (priority > -1) { 07764 chan->priority = priority; 07765 /* see flag description in channel.h for explanation */ 07766 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 07767 chan->priority--; 07768 } 07769 07770 ast_channel_unlock(chan); 07771 07772 return 0; 07773 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2489 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().
02490 { 02491 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02492 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02493 return extension_match_core(pattern, data, needmore); 02494 }
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 2291 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02292 { 02293 return ext_cmp(a, b); 02294 }
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 2484 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().
02485 { 02486 return extension_match_core(pattern, data, E_MATCH); 02487 }
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 4208 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().
04209 { 04210 struct ast_exten *e; 04211 04212 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04213 return -1; /* No hint, return -1 */ 04214 } 04215 04216 if (e->exten[0] == '_') { 04217 /* Create this hint on-the-fly */ 04218 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04219 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04220 e->registrar); 04221 if (!(e = ast_hint_extension(c, context, exten))) { 04222 /* Improbable, but not impossible */ 04223 return -1; 04224 } 04225 } 04226 04227 return ast_extension_state2(e); /* Check all devices in the hint */ 04228 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4173 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_get_extension_app(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), extensionstate_buf, and strsep().
Referenced by ast_add_hint(), ast_extension_state(), and handle_statechange().
04174 { 04175 struct ast_str *hint = ast_str_thread_get(&extensionstate_buf, 16); 04176 char *cur, *rest; 04177 struct ast_devstate_aggregate agg; 04178 04179 if (!e) 04180 return -1; 04181 04182 ast_devstate_aggregate_init(&agg); 04183 04184 ast_str_set(&hint, 0, "%s", ast_get_extension_app(e)); 04185 04186 rest = ast_str_buffer(hint); /* One or more devices separated with a & character */ 04187 04188 while ( (cur = strsep(&rest, "&")) ) { 04189 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04190 } 04191 04192 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04193 }
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 4196 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().
04197 { 04198 int i; 04199 04200 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04201 if (extension_states[i].extension_state == extension_state) 04202 return extension_states[i].text; 04203 } 04204 return "Unknown"; 04205 }
int ast_extension_state_add | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | callback, | |||
void * | data | |||
) |
Registers a state change callback.
context | which context to look in | |
exten | which extension to get state | |
callback | callback to call if state changed | |
data | to pass to callback |
-1 | on failure | |
ID | on success |
Definition at line 4304 of file pbx.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr, ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strdup, ast_state_cb::callback, ast_hint::callbacks, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_exten::exten, hints, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, and stateid.
Referenced by __init_manager(), handle_request_subscribe(), load_module(), and skinny_register().
04306 { 04307 struct ast_hint *hint; 04308 struct ast_state_cb *cblist; 04309 struct ast_exten *e; 04310 04311 /* If there's no context and extension: add callback to statecbs list */ 04312 if (!context && !exten) { 04313 ao2_lock(hints); 04314 04315 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 04316 if (cblist->callback == callback) { 04317 cblist->data = data; 04318 ao2_unlock(hints); 04319 return 0; 04320 } 04321 } 04322 04323 /* Now insert the callback */ 04324 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 04325 ao2_unlock(hints); 04326 return -1; 04327 } 04328 cblist->id = 0; 04329 cblist->callback = callback; 04330 cblist->data = data; 04331 04332 AST_LIST_INSERT_HEAD(&statecbs, cblist, entry); 04333 04334 ao2_unlock(hints); 04335 return 0; 04336 } 04337 04338 if (!context || !exten) 04339 return -1; 04340 04341 /* This callback type is for only one hint, so get the hint */ 04342 e = ast_hint_extension(NULL, context, exten); 04343 if (!e) { 04344 return -1; 04345 } 04346 04347 /* If this is a pattern, dynamically create a new extension for this 04348 * particular match. Note that this will only happen once for each 04349 * individual extension, because the pattern will no longer match first. 04350 */ 04351 if (e->exten[0] == '_') { 04352 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04353 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04354 e->registrar); 04355 e = ast_hint_extension(NULL, context, exten); 04356 if (!e || e->exten[0] == '_') { 04357 return -1; 04358 } 04359 } 04360 04361 /* Find the hint in the list of hints */ 04362 hint = ao2_find(hints, e, 0); 04363 04364 if (!hint) { 04365 return -1; 04366 } 04367 04368 /* Now insert the callback in the callback list */ 04369 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 04370 ao2_ref(hint, -1); 04371 return -1; 04372 } 04373 04374 cblist->id = stateid++; /* Unique ID for this callback */ 04375 cblist->callback = callback; /* Pointer to callback routine */ 04376 cblist->data = data; /* Data for the callback */ 04377 04378 ao2_lock(hint); 04379 AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry); 04380 ao2_unlock(hint); 04381 04382 ao2_ref(hint, -1); 04383 04384 return cblist->id; 04385 }
int ast_extension_state_del | ( | int | id, | |
ast_state_cb_type | callback | |||
) |
Deletes a registered state change callback by ID.
id | of the callback to delete | |
callback | callback |
0 | success | |
-1 | failure |
Definition at line 4404 of file pbx.c.
References ao2_callback, ao2_lock, ao2_ref, ao2_unlock, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_state_cb::callback, ast_state_cb::entry, find_hint_by_cb_id(), hints, and ast_state_cb::id.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
04405 { 04406 struct ast_state_cb *p_cur = NULL; 04407 int ret = -1; 04408 04409 if (!id && !callback) { 04410 return -1; 04411 } 04412 04413 if (!id) { /* id == 0 is a callback without extension */ 04414 ao2_lock(hints); 04415 AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) { 04416 if (p_cur->callback == callback) { 04417 AST_LIST_REMOVE_CURRENT(entry); 04418 break; 04419 } 04420 } 04421 AST_LIST_TRAVERSE_SAFE_END; 04422 ao2_unlock(hints); 04423 } else { /* callback with extension, find the callback based on ID */ 04424 struct ast_hint *hint; 04425 04426 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04427 04428 if (hint) { 04429 ao2_lock(hint); 04430 AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) { 04431 if (p_cur->id == id) { 04432 AST_LIST_REMOVE_CURRENT(entry); 04433 ret = 0; 04434 break; 04435 } 04436 } 04437 AST_LIST_TRAVERSE_SAFE_END; 04438 04439 ao2_unlock(hint); 04440 ao2_ref(hint, -1); 04441 } 04442 } 04443 04444 if (p_cur) { 04445 ast_free(p_cur); 04446 } 04447 04448 return ret; 04449 }
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 4583 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().
04584 { 04585 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04586 }
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 4588 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
04589 { 04590 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04591 }
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 3483 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().
03484 { 03485 char *copy = ast_strdupa(function); 03486 char *args = func_args(copy); 03487 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03488 int res; 03489 struct ast_module_user *u = NULL; 03490 03491 if (acfptr == NULL) { 03492 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03493 } else if (!acfptr->read && !acfptr->read2) { 03494 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03495 } else if (acfptr->read) { 03496 if (acfptr->mod) { 03497 u = __ast_module_user_add(acfptr->mod, chan); 03498 } 03499 res = acfptr->read(chan, copy, args, workspace, len); 03500 if (acfptr->mod && u) { 03501 __ast_module_user_remove(acfptr->mod, u); 03502 } 03503 return res; 03504 } else { 03505 struct ast_str *str = ast_str_create(16); 03506 if (acfptr->mod) { 03507 u = __ast_module_user_add(acfptr->mod, chan); 03508 } 03509 res = acfptr->read2(chan, copy, args, &str, 0); 03510 if (acfptr->mod && u) { 03511 __ast_module_user_remove(acfptr->mod, u); 03512 } 03513 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03514 ast_free(str); 03515 return res; 03516 } 03517 return -1; 03518 }
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 3520 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().
03521 { 03522 char *copy = ast_strdupa(function); 03523 char *args = func_args(copy); 03524 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03525 int res; 03526 struct ast_module_user *u = NULL; 03527 03528 if (acfptr == NULL) { 03529 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03530 } else if (!acfptr->read && !acfptr->read2) { 03531 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03532 } else { 03533 if (acfptr->mod) { 03534 u = __ast_module_user_add(acfptr->mod, chan); 03535 } 03536 if (acfptr->read2) { 03537 /* ast_str enabled */ 03538 ast_str_reset(*str); 03539 res = acfptr->read2(chan, copy, args, str, maxlen); 03540 } else { 03541 /* Legacy function pointer, allocate buffer for result */ 03542 int maxsize = ast_str_size(*str); 03543 if (maxlen > -1) { 03544 if (maxlen == 0) { 03545 if (acfptr->read_max) { 03546 maxsize = acfptr->read_max; 03547 } else { 03548 maxsize = VAR_BUF_SIZE; 03549 } 03550 } else { 03551 maxsize = maxlen; 03552 } 03553 ast_str_make_space(str, maxsize); 03554 } 03555 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03556 } 03557 if (acfptr->mod && u) { 03558 __ast_module_user_remove(acfptr->mod, u); 03559 } 03560 return res; 03561 } 03562 return -1; 03563 }
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 3565 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().
03566 { 03567 char *copy = ast_strdupa(function); 03568 char *args = func_args(copy); 03569 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03570 03571 if (acfptr == NULL) 03572 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03573 else if (!acfptr->write) 03574 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03575 else { 03576 int res; 03577 struct ast_module_user *u = NULL; 03578 if (acfptr->mod) 03579 u = __ast_module_user_add(acfptr->mod, chan); 03580 res = acfptr->write(chan, copy, args, value); 03581 if (acfptr->mod && u) 03582 __ast_module_user_remove(acfptr->mod, u); 03583 return res; 03584 } 03585 03586 return -1; 03587 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 9940 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(), 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(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09941 { 09942 return con ? con->name : NULL; 09943 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 9978 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
09979 { 09980 return c ? c->registrar : NULL; 09981 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10008 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_parking_ext_valid(), ast_str_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
10009 { 10010 return e ? e->app : NULL; 10011 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10013 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
10014 { 10015 return e ? e->data : NULL; 10016 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10003 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10004 { 10005 return e ? e->cidmatch : NULL; 10006 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 9945 of file pbx.c.
References exten.
Referenced by handle_show_hint(), handle_show_hints(), and hints_data_provider_get().
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 9955 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 9998 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09999 { 10000 return e ? e->matchcid : 0; 10001 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 9950 of file pbx.c.
References exten.
Referenced by ast_add_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), 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 9970 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 9983 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09984 { 09985 return e ? e->registrar : NULL; 09986 }
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 4540 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().
04541 { 04542 struct ast_exten *e = ast_hint_extension(c, context, exten); 04543 04544 if (e) { 04545 if (hint) 04546 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04547 if (name) { 04548 const char *tmp = ast_get_extension_app_data(e); 04549 if (tmp) 04550 ast_copy_string(name, tmp, namesize); 04551 } 04552 return -1; 04553 } 04554 return 0; 04555 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9965 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().
09966 { 09967 return ip ? ip->pattern : NULL; 09968 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9993 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().
09994 { 09995 return ip ? ip->registrar : NULL; 09996 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 9960 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().
09961 { 09962 return inc ? inc->name : NULL; 09963 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 9988 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().
09989 { 09990 return i ? i->registrar : NULL; 09991 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10023 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().
10024 { 10025 return sw ? sw->data : NULL; 10026 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10028 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10029 { 10030 return sw->eval; 10031 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10018 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().
10019 { 10020 return sw ? sw->name : NULL; 10021 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10033 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().
10034 { 10035 return sw ? sw->registrar : NULL; 10036 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10128 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10129 { 10130 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10131 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1046 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01047 { 01048 const struct ast_context *ac = ah_a; 01049 const struct ast_context *bc = ah_b; 01050 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01051 return 1; 01052 /* assume context names are registered in a string table! */ 01053 return strcmp(ac->name, bc->name); 01054 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1089 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().
01090 { 01091 const struct ast_context *ac = obj; 01092 return ast_hashtab_hash_string(ac->name); 01093 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
Definition at line 4136 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(), ast_get_hint(), and ast_str_get_hint().
04137 { 04138 struct ast_exten *e; 04139 ast_rdlock_contexts(); 04140 e = ast_hint_extension_nolock(c, context, exten); 04141 ast_unlock_contexts(); 04142 return e; 04143 }
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 4130 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().
04131 { 04132 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04133 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04134 }
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 7698 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().
07699 { 07700 struct ast_context *con = ast_context_find(context); 07701 if (con) { 07702 struct ast_ignorepat *pat; 07703 for (pat = con->ignorepats; pat; pat = pat->next) { 07704 if (ast_extension_match(pat->pattern, pattern)) 07705 return 1; 07706 } 07707 } 07708 07709 return 0; 07710 }
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 4598 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), collect_digits(), dahdi_r2_on_dnis_digit_received(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_ss_thread(), readexten_exec(), and skinny_ss().
04599 { 04600 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04601 }
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 7047 of file pbx.c.
References __ast_internal_context_destroy(), ao2_find, AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, 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_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_rdlock_contexts(), ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::list, ast_context::name, ast_context::next, store_hint::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07048 { 07049 double ft; 07050 struct ast_context *tmp, *oldcontextslist; 07051 struct ast_hashtab *oldtable; 07052 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 07053 struct store_hint *this; 07054 struct ast_hint *hint; 07055 struct ast_exten *exten; 07056 int length; 07057 struct ast_state_cb *thiscb; 07058 struct ast_hashtab_iter *iter; 07059 struct ao2_iterator i; 07060 07061 /* it is very important that this function hold the hint list lock _and_ the conlock 07062 during its operation; not only do we need to ensure that the list of contexts 07063 and extensions does not change, but also that no hint callbacks (watchers) are 07064 added or removed during the merge/delete process 07065 07066 in addition, the locks _must_ be taken in this order, because there are already 07067 other code paths that use this order 07068 */ 07069 07070 struct timeval begintime, writelocktime, endlocktime, enddeltime; 07071 07072 begintime = ast_tvnow(); 07073 ast_rdlock_contexts(); 07074 iter = ast_hashtab_start_traversal(contexts_table); 07075 while ((tmp = ast_hashtab_next(iter))) { 07076 context_merge(extcontexts, exttable, tmp, registrar); 07077 } 07078 ast_hashtab_end_traversal(iter); 07079 07080 ao2_lock(hints); 07081 writelocktime = ast_tvnow(); 07082 07083 /* preserve all watchers for hints */ 07084 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07085 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 07086 if (!AST_LIST_EMPTY(&hint->callbacks)) { 07087 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 07088 if (!(this = ast_calloc(1, length))) { 07089 continue; 07090 } 07091 ao2_lock(hint); 07092 07093 if (hint->exten == NULL) { 07094 ao2_unlock(hint); 07095 continue; 07096 } 07097 07098 /* this removes all the callbacks from the hint into this. */ 07099 AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry); 07100 this->laststate = hint->laststate; 07101 this->context = this->data; 07102 strcpy(this->data, hint->exten->parent->name); 07103 this->exten = this->data + strlen(this->context) + 1; 07104 strcpy(this->exten, hint->exten->exten); 07105 ao2_unlock(hint); 07106 AST_LIST_INSERT_HEAD(&store, this, list); 07107 } 07108 } 07109 07110 /* save the old table and list */ 07111 oldtable = contexts_table; 07112 oldcontextslist = contexts; 07113 07114 /* move in the new table and list */ 07115 contexts_table = exttable; 07116 contexts = *extcontexts; 07117 07118 /* restore the watchers for hints that can be found; notify those that 07119 cannot be restored 07120 */ 07121 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 07122 struct pbx_find_info q = { .stacklen = 0 }; 07123 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 07124 /* If this is a pattern, dynamically create a new extension for this 07125 * particular match. Note that this will only happen once for each 07126 * individual extension, because the pattern will no longer match first. 07127 */ 07128 if (exten && exten->exten[0] == '_') { 07129 ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL, 07130 0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar); 07131 /* rwlocks are not recursive locks */ 07132 exten = ast_hint_extension_nolock(NULL, this->context, this->exten); 07133 } 07134 07135 /* Find the hint in the list of hints */ 07136 hint = ao2_find(hints, exten, 0); 07137 if (!exten || !hint) { 07138 /* this hint has been removed, notify the watchers */ 07139 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 07140 thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data); 07141 ast_free(thiscb); 07142 } 07143 } else { 07144 ao2_lock(hint); 07145 AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry); 07146 hint->laststate = this->laststate; 07147 ao2_unlock(hint); 07148 } 07149 ast_free(this); 07150 if (hint) { 07151 ao2_ref(hint, -1); 07152 } 07153 } 07154 07155 ao2_unlock(hints); 07156 ast_unlock_contexts(); 07157 endlocktime = ast_tvnow(); 07158 07159 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 07160 is now freely using the new stuff instead */ 07161 07162 ast_hashtab_destroy(oldtable, NULL); 07163 07164 for (tmp = oldcontextslist; tmp; ) { 07165 struct ast_context *next; /* next starting point */ 07166 next = tmp->next; 07167 __ast_internal_context_destroy(tmp); 07168 tmp = next; 07169 } 07170 enddeltime = ast_tvnow(); 07171 07172 ft = ast_tvdiff_us(writelocktime, begintime); 07173 ft /= 1000000.0; 07174 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07175 07176 ft = ast_tvdiff_us(endlocktime, writelocktime); 07177 ft /= 1000000.0; 07178 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07179 07180 ft = ast_tvdiff_us(enddeltime, endlocktime); 07181 ft /= 1000000.0; 07182 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07183 07184 ft = ast_tvdiff_us(enddeltime, begintime); 07185 ft /= 1000000.0; 07186 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07187 return; 07188 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10193 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().
10194 { 10195 return pbx_parseable_goto(chan, goto_string, 0); 10196 }
int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 10243 of file pbx.c.
References ao2_container_alloc, hint_cmp(), hint_hash(), and hints.
Referenced by main().
10244 { 10245 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 10246 10247 return hints ? 0 : -1; 10248 }
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 8541 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_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().
08542 { 08543 struct ast_channel *chan; 08544 struct app_tmp *tmp; 08545 int res = -1, cdr_res = -1; 08546 struct outgoing_helper oh; 08547 08548 memset(&oh, 0, sizeof(oh)); 08549 oh.vars = vars; 08550 oh.account = account; 08551 08552 if (locked_channel) 08553 *locked_channel = NULL; 08554 if (ast_strlen_zero(app)) { 08555 res = -1; 08556 goto outgoing_app_cleanup; 08557 } 08558 if (synchronous) { 08559 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08560 if (chan) { 08561 ast_set_variables(chan, vars); 08562 if (account) 08563 ast_cdr_setaccount(chan, account); 08564 if (chan->_state == AST_STATE_UP) { 08565 res = 0; 08566 ast_verb(4, "Channel %s was answered.\n", chan->name); 08567 tmp = ast_calloc(1, sizeof(*tmp)); 08568 if (!tmp) 08569 res = -1; 08570 else { 08571 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 08572 if (appdata) 08573 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 08574 tmp->chan = chan; 08575 if (synchronous > 1) { 08576 if (locked_channel) 08577 ast_channel_unlock(chan); 08578 ast_pbx_run_app(tmp); 08579 } else { 08580 if (locked_channel) 08581 ast_channel_lock(chan); 08582 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 08583 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 08584 ast_free(tmp); 08585 if (locked_channel) 08586 ast_channel_unlock(chan); 08587 ast_hangup(chan); 08588 res = -1; 08589 } else { 08590 if (locked_channel) 08591 *locked_channel = chan; 08592 } 08593 } 08594 } 08595 } else { 08596 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08597 if (chan->cdr) { /* update the cdr */ 08598 /* here we update the status of the call, which sould be busy. 08599 * if that fails then we set the status to failed */ 08600 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08601 ast_cdr_failed(chan->cdr); 08602 } 08603 ast_hangup(chan); 08604 } 08605 } 08606 08607 if (res < 0) { /* the call failed for some reason */ 08608 if (*reason == 0) { /* if the call failed (not busy or no answer) 08609 * update the cdr with the failed message */ 08610 cdr_res = ast_pbx_outgoing_cdr_failed(); 08611 if (cdr_res != 0) { 08612 res = cdr_res; 08613 goto outgoing_app_cleanup; 08614 } 08615 } 08616 } 08617 08618 } else { 08619 struct async_stat *as; 08620 if (!(as = ast_calloc(1, sizeof(*as)))) { 08621 res = -1; 08622 goto outgoing_app_cleanup; 08623 } 08624 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08625 if (!chan) { 08626 ast_free(as); 08627 res = -1; 08628 goto outgoing_app_cleanup; 08629 } 08630 as->chan = chan; 08631 ast_copy_string(as->app, app, sizeof(as->app)); 08632 if (appdata) 08633 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 08634 as->timeout = timeout; 08635 ast_set_variables(chan, vars); 08636 if (account) 08637 ast_cdr_setaccount(chan, account); 08638 /* Start a new thread, and get something handling this channel. */ 08639 if (locked_channel) 08640 ast_channel_lock(chan); 08641 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08642 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08643 ast_free(as); 08644 if (locked_channel) 08645 ast_channel_unlock(chan); 08646 ast_hangup(chan); 08647 res = -1; 08648 goto outgoing_app_cleanup; 08649 } else { 08650 if (locked_channel) 08651 *locked_channel = chan; 08652 } 08653 res = 0; 08654 } 08655 outgoing_app_cleanup: 08656 ast_variables_destroy(vars); 08657 return res; 08658 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 8348 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_release(), ast_dummy_channel_alloc(), and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
08349 { 08350 /* allocate a channel */ 08351 struct ast_channel *chan = ast_dummy_channel_alloc(); 08352 08353 if (!chan) 08354 return -1; /* failure */ 08355 08356 chan->cdr = ast_cdr_alloc(); 08357 if (!chan->cdr) { 08358 /* allocation of the cdr failed */ 08359 chan = ast_channel_release(chan); /* free the channel */ 08360 return -1; /* return failure */ 08361 } 08362 08363 /* allocation of the cdr was successful */ 08364 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 08365 ast_cdr_start(chan->cdr); /* record the start and stop time */ 08366 ast_cdr_end(chan->cdr); 08367 ast_cdr_failed(chan->cdr); /* set the status to failed */ 08368 ast_cdr_detach(chan->cdr); /* post and free the record */ 08369 chan->cdr = NULL; 08370 chan = ast_channel_release(chan); /* free the channel */ 08371 08372 return 0; /* success */ 08373 }
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 8375 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().
08376 { 08377 struct ast_channel *chan; 08378 struct async_stat *as; 08379 int res = -1, cdr_res = -1; 08380 struct outgoing_helper oh; 08381 08382 if (synchronous) { 08383 oh.context = context; 08384 oh.exten = exten; 08385 oh.priority = priority; 08386 oh.cid_num = cid_num; 08387 oh.cid_name = cid_name; 08388 oh.account = account; 08389 oh.vars = vars; 08390 oh.parent_channel = NULL; 08391 08392 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08393 if (channel) { 08394 *channel = chan; 08395 if (chan) 08396 ast_channel_lock(chan); 08397 } 08398 if (chan) { 08399 if (chan->_state == AST_STATE_UP) { 08400 res = 0; 08401 ast_verb(4, "Channel %s was answered.\n", chan->name); 08402 08403 if (synchronous > 1) { 08404 if (channel) 08405 ast_channel_unlock(chan); 08406 if (ast_pbx_run(chan)) { 08407 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08408 if (channel) 08409 *channel = NULL; 08410 ast_hangup(chan); 08411 chan = NULL; 08412 res = -1; 08413 } 08414 } else { 08415 if (ast_pbx_start(chan)) { 08416 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 08417 if (channel) { 08418 *channel = NULL; 08419 ast_channel_unlock(chan); 08420 } 08421 ast_hangup(chan); 08422 res = -1; 08423 } 08424 chan = NULL; 08425 } 08426 } else { 08427 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08428 08429 if (chan->cdr) { /* update the cdr */ 08430 /* here we update the status of the call, which sould be busy. 08431 * if that fails then we set the status to failed */ 08432 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08433 ast_cdr_failed(chan->cdr); 08434 } 08435 08436 if (channel) { 08437 *channel = NULL; 08438 ast_channel_unlock(chan); 08439 } 08440 ast_hangup(chan); 08441 chan = NULL; 08442 } 08443 } 08444 08445 if (res < 0) { /* the call failed for some reason */ 08446 if (*reason == 0) { /* if the call failed (not busy or no answer) 08447 * update the cdr with the failed message */ 08448 cdr_res = ast_pbx_outgoing_cdr_failed(); 08449 if (cdr_res != 0) { 08450 res = cdr_res; 08451 goto outgoing_exten_cleanup; 08452 } 08453 } 08454 08455 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08456 /* check if "failed" exists */ 08457 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08458 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 08459 if (chan) { 08460 char failed_reason[4] = ""; 08461 if (!ast_strlen_zero(context)) 08462 ast_copy_string(chan->context, context, sizeof(chan->context)); 08463 set_ext_pri(chan, "failed", 1); 08464 ast_set_variables(chan, vars); 08465 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08466 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08467 if (account) 08468 ast_cdr_setaccount(chan, account); 08469 if (ast_pbx_run(chan)) { 08470 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08471 ast_hangup(chan); 08472 } 08473 chan = NULL; 08474 } 08475 } 08476 } 08477 } else { 08478 if (!(as = ast_calloc(1, sizeof(*as)))) { 08479 res = -1; 08480 goto outgoing_exten_cleanup; 08481 } 08482 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 08483 if (channel) { 08484 *channel = chan; 08485 if (chan) 08486 ast_channel_lock(chan); 08487 } 08488 if (!chan) { 08489 ast_free(as); 08490 res = -1; 08491 goto outgoing_exten_cleanup; 08492 } 08493 as->chan = chan; 08494 ast_copy_string(as->context, context, sizeof(as->context)); 08495 set_ext_pri(as->chan, exten, priority); 08496 as->timeout = timeout; 08497 ast_set_variables(chan, vars); 08498 if (account) 08499 ast_cdr_setaccount(chan, account); 08500 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08501 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08502 ast_free(as); 08503 if (channel) { 08504 *channel = NULL; 08505 ast_channel_unlock(chan); 08506 } 08507 ast_hangup(chan); 08508 res = -1; 08509 goto outgoing_exten_cleanup; 08510 } 08511 res = 0; 08512 } 08513 outgoing_exten_cleanup: 08514 ast_variables_destroy(vars); 08515 return res; 08516 }
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 5059 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().
05060 { 05061 return ast_pbx_run_args(c, NULL); 05062 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 8526 of file pbx.c.
References app_tmp::app, app, ast_free, ast_hangup(), ast_log(), ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, ast_channel::name, pbx_exec(), and pbx_findapp().
Referenced by ast_pbx_outgoing_app().
08527 { 08528 struct app_tmp *tmp = data; 08529 struct ast_app *app; 08530 app = pbx_findapp(tmp->app); 08531 if (app) { 08532 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 08533 pbx_exec(tmp->chan, app, tmp->data); 08534 } else 08535 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 08536 ast_hangup(tmp->chan); 08537 ast_free(tmp); 08538 return NULL; 08539 }
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 5044 of file pbx.c.
References __ast_pbx_run(), args, AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
Referenced by ast_pbx_run(), dial_exec_full(), and handle_gosub().
05045 { 05046 enum ast_pbx_result res = AST_PBX_SUCCESS; 05047 05048 if (increase_call_count(c)) { 05049 return AST_PBX_CALL_LIMIT; 05050 } 05051 05052 res = __ast_pbx_run(c, args); 05053 05054 decrease_call_count(); 05055 05056 return res; 05057 }
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 5022 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, 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_parkinglot(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), ss7_start_call(), unistim_new(), and usbradio_new().
05023 { 05024 pthread_t t; 05025 05026 if (!c) { 05027 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05028 return AST_PBX_FAILED; 05029 } 05030 05031 if (increase_call_count(c)) 05032 return AST_PBX_CALL_LIMIT; 05033 05034 /* Start a new thread, and get something handling this channel. */ 05035 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05036 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05037 decrease_call_count(); 05038 return AST_PBX_FAILED; 05039 } 05040 05041 return AST_PBX_SUCCESS; 05042 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5069 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05070 { 05071 return totalcalls; 05072 }
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 9927 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().
09928 { 09929 return ast_rwlock_rdlock(&con->lock); 09930 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 9909 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09910 { 09911 return ast_mutex_lock(&conlock); 09912 }
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 5496 of file pbx.c.
References ast_app::arguments, ast_calloc, ast_free, 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_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().
05497 { 05498 struct ast_app *tmp, *cur = NULL; 05499 char tmps[80]; 05500 int length, res; 05501 #ifdef AST_XML_DOCS 05502 char *tmpxml; 05503 #endif 05504 05505 AST_RWLIST_WRLOCK(&apps); 05506 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 05507 if (!(res = strcasecmp(app, tmp->name))) { 05508 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 05509 AST_RWLIST_UNLOCK(&apps); 05510 return -1; 05511 } else if (res < 0) 05512 break; 05513 } 05514 05515 length = sizeof(*tmp) + strlen(app) + 1; 05516 05517 if (!(tmp = ast_calloc(1, length))) { 05518 AST_RWLIST_UNLOCK(&apps); 05519 return -1; 05520 } 05521 05522 if (ast_string_field_init(tmp, 128)) { 05523 AST_RWLIST_UNLOCK(&apps); 05524 ast_free(tmp); 05525 return -1; 05526 } 05527 05528 #ifdef AST_XML_DOCS 05529 /* Try to lookup the docs in our XML documentation database */ 05530 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05531 /* load synopsis */ 05532 tmpxml = ast_xmldoc_build_synopsis("application", app); 05533 ast_string_field_set(tmp, synopsis, tmpxml); 05534 ast_free(tmpxml); 05535 05536 /* load description */ 05537 tmpxml = ast_xmldoc_build_description("application", app); 05538 ast_string_field_set(tmp, description, tmpxml); 05539 ast_free(tmpxml); 05540 05541 /* load syntax */ 05542 tmpxml = ast_xmldoc_build_syntax("application", app); 05543 ast_string_field_set(tmp, syntax, tmpxml); 05544 ast_free(tmpxml); 05545 05546 /* load arguments */ 05547 tmpxml = ast_xmldoc_build_arguments("application", app); 05548 ast_string_field_set(tmp, arguments, tmpxml); 05549 ast_free(tmpxml); 05550 05551 /* load seealso */ 05552 tmpxml = ast_xmldoc_build_seealso("application", app); 05553 ast_string_field_set(tmp, seealso, tmpxml); 05554 ast_free(tmpxml); 05555 tmp->docsrc = AST_XML_DOC; 05556 } else { 05557 #endif 05558 ast_string_field_set(tmp, synopsis, synopsis); 05559 ast_string_field_set(tmp, description, description); 05560 #ifdef AST_XML_DOCS 05561 tmp->docsrc = AST_STATIC_DOC; 05562 } 05563 #endif 05564 05565 strcpy(tmp->name, app); 05566 tmp->execute = execute; 05567 tmp->module = mod; 05568 05569 /* Store in alphabetical order */ 05570 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 05571 if (strcasecmp(tmp->name, cur->name) < 0) { 05572 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 05573 break; 05574 } 05575 } 05576 AST_RWLIST_TRAVERSE_SAFE_END; 05577 if (!cur) 05578 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 05579 05580 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 05581 05582 AST_RWLIST_UNLOCK(&apps); 05583 05584 return 0; 05585 }
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 5591 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().
05592 { 05593 struct ast_switch *tmp; 05594 05595 AST_RWLIST_WRLOCK(&switches); 05596 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05597 if (!strcasecmp(tmp->name, sw->name)) { 05598 AST_RWLIST_UNLOCK(&switches); 05599 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05600 return -1; 05601 } 05602 } 05603 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05604 AST_RWLIST_UNLOCK(&switches); 05605 05606 return 0; 05607 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 4506 of file pbx.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, AST_EXTENSION_DEACTIVATED, ast_free, AST_LIST_REMOVE_HEAD, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_state_cb::entry, ast_exten::exten, ast_hint::exten, hints, ast_context::name, and ast_exten::parent.
Referenced by destroy_exten().
04507 { 04508 /* Cleanup the Notifys if hint is removed */ 04509 struct ast_hint *hint; 04510 struct ast_state_cb *cblist; 04511 04512 if (!e) { 04513 return -1; 04514 } 04515 04516 hint = ao2_find(hints, e, 0); 04517 04518 if (!hint) { 04519 return -1; 04520 } 04521 ao2_lock(hint); 04522 04523 while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) { 04524 /* Notify with -1 and remove all callbacks */ 04525 cblist->callback(hint->exten->parent->name, hint->exten->exten, 04526 AST_EXTENSION_DEACTIVATED, cblist->data); 04527 ast_free(cblist); 04528 } 04529 04530 hint->exten = NULL; 04531 ao2_unlink(hints, hint); 04532 ao2_unlock(hint); 04533 ao2_ref(hint, -1); 04534 04535 return 0; 04536 }
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 4603 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().
04604 { 04605 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04606 }
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 4558 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().
04559 { 04560 struct ast_exten *e = ast_hint_extension(c, context, exten); 04561 04562 if (!e) { 04563 return 0; 04564 } 04565 04566 if (hint) { 04567 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 04568 } 04569 if (name) { 04570 const char *tmp = ast_get_extension_app_data(e); 04571 if (tmp) { 04572 ast_str_set(name, namesize, "%s", tmp); 04573 } 04574 } 04575 return -1; 04576 }
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 2987 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().
02988 { 02989 const char not_found = '\0'; 02990 char *tmpvar; 02991 const char *ret; 02992 const char *s; /* the result */ 02993 int offset, length; 02994 int i, need_substring; 02995 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02996 02997 if (c) { 02998 ast_channel_lock(c); 02999 places[0] = &c->varshead; 03000 } 03001 /* 03002 * Make a copy of var because parse_variable_name() modifies the string. 03003 * Then if called directly, we might need to run substring() on the result; 03004 * remember this for later in 'need_substring', 'offset' and 'length' 03005 */ 03006 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03007 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03008 03009 /* 03010 * Look first into predefined variables, then into variable lists. 03011 * Variable 's' points to the result, according to the following rules: 03012 * s == ¬_found (set at the beginning) means that we did not find a 03013 * matching variable and need to look into more places. 03014 * If s != ¬_found, s is a valid result string as follows: 03015 * s = NULL if the variable does not have a value; 03016 * you typically do this when looking for an unset predefined variable. 03017 * s = workspace if the result has been assembled there; 03018 * typically done when the result is built e.g. with an snprintf(), 03019 * so we don't need to do an additional copy. 03020 * s != workspace in case we have a string, that needs to be copied 03021 * (the ast_copy_string is done once for all at the end). 03022 * Typically done when the result is already available in some string. 03023 */ 03024 s = ¬_found; /* default value */ 03025 if (c) { /* This group requires a valid channel */ 03026 /* Names with common parts are looked up a piece at a time using strncmp. */ 03027 if (!strncmp(var, "CALL", 4)) { 03028 if (!strncmp(var + 4, "ING", 3)) { 03029 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03030 ast_str_set(str, maxlen, "%d", 03031 ast_party_id_presentation(&c->caller.id)); 03032 s = ast_str_buffer(*str); 03033 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03034 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03035 s = ast_str_buffer(*str); 03036 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03037 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03038 s = ast_str_buffer(*str); 03039 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03040 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03041 s = ast_str_buffer(*str); 03042 } 03043 } 03044 } else if (!strcmp(var, "HINT")) { 03045 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03046 } else if (!strcmp(var, "HINTNAME")) { 03047 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03048 } else if (!strcmp(var, "EXTEN")) { 03049 s = c->exten; 03050 } else if (!strcmp(var, "CONTEXT")) { 03051 s = c->context; 03052 } else if (!strcmp(var, "PRIORITY")) { 03053 ast_str_set(str, maxlen, "%d", c->priority); 03054 s = ast_str_buffer(*str); 03055 } else if (!strcmp(var, "CHANNEL")) { 03056 s = c->name; 03057 } else if (!strcmp(var, "UNIQUEID")) { 03058 s = c->uniqueid; 03059 } else if (!strcmp(var, "HANGUPCAUSE")) { 03060 ast_str_set(str, maxlen, "%d", c->hangupcause); 03061 s = ast_str_buffer(*str); 03062 } 03063 } 03064 if (s == ¬_found) { /* look for more */ 03065 if (!strcmp(var, "EPOCH")) { 03066 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03067 s = ast_str_buffer(*str); 03068 } else if (!strcmp(var, "SYSTEMNAME")) { 03069 s = ast_config_AST_SYSTEM_NAME; 03070 } else if (!strcmp(var, "ENTITYID")) { 03071 char workspace[20]; 03072 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03073 s = workspace; 03074 } 03075 } 03076 /* if not found, look into chanvars or global vars */ 03077 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03078 struct ast_var_t *variables; 03079 if (!places[i]) 03080 continue; 03081 if (places[i] == &globals) 03082 ast_rwlock_rdlock(&globalslock); 03083 AST_LIST_TRAVERSE(places[i], variables, entries) { 03084 if (!strcasecmp(ast_var_name(variables), var)) { 03085 s = ast_var_value(variables); 03086 break; 03087 } 03088 } 03089 if (places[i] == &globals) 03090 ast_rwlock_unlock(&globalslock); 03091 } 03092 if (s == ¬_found || s == NULL) { 03093 ast_debug(5, "Result of '%s' is NULL\n", var); 03094 ret = NULL; 03095 } else { 03096 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03097 if (s != ast_str_buffer(*str)) { 03098 ast_str_set(str, maxlen, "%s", s); 03099 } 03100 ret = ast_str_buffer(*str); 03101 if (need_substring) { 03102 ret = ast_str_substring(*str, offset, length); 03103 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03104 } 03105 } 03106 03107 if (c) { 03108 ast_channel_unlock(c); 03109 } 03110 return ret; 03111 }
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 3765 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().
03766 { 03767 size_t used; 03768 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 03769 }
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 3589 of file pbx.c.
References ast_channel_release(), 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().
03590 { 03591 /* Substitutes variables into buf, based on string templ */ 03592 char *cp4 = NULL; 03593 const char *tmp, *whereweare; 03594 int orig_size = 0; 03595 int offset, offset2, isfunction; 03596 const char *nextvar, *nextexp, *nextthing; 03597 const char *vars, *vare; 03598 char *finalvars; 03599 int pos, brackets, needsub, len; 03600 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03601 03602 ast_str_reset(*buf); 03603 whereweare = tmp = templ; 03604 while (!ast_strlen_zero(whereweare)) { 03605 /* Assume we're copying the whole remaining string */ 03606 pos = strlen(whereweare); 03607 nextvar = NULL; 03608 nextexp = NULL; 03609 nextthing = strchr(whereweare, '$'); 03610 if (nextthing) { 03611 switch (nextthing[1]) { 03612 case '{': 03613 nextvar = nextthing; 03614 pos = nextvar - whereweare; 03615 break; 03616 case '[': 03617 nextexp = nextthing; 03618 pos = nextexp - whereweare; 03619 break; 03620 default: 03621 pos = 1; 03622 } 03623 } 03624 03625 if (pos) { 03626 /* Copy that many bytes */ 03627 ast_str_append_substr(buf, maxlen, whereweare, pos); 03628 03629 templ += pos; 03630 whereweare += pos; 03631 } 03632 03633 if (nextvar) { 03634 /* We have a variable. Find the start and end, and determine 03635 if we are going to have to recursively call ourselves on the 03636 contents */ 03637 vars = vare = nextvar + 2; 03638 brackets = 1; 03639 needsub = 0; 03640 03641 /* Find the end of it */ 03642 while (brackets && *vare) { 03643 if ((vare[0] == '$') && (vare[1] == '{')) { 03644 needsub++; 03645 } else if (vare[0] == '{') { 03646 brackets++; 03647 } else if (vare[0] == '}') { 03648 brackets--; 03649 } else if ((vare[0] == '$') && (vare[1] == '[')) 03650 needsub++; 03651 vare++; 03652 } 03653 if (brackets) 03654 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03655 len = vare - vars - 1; 03656 03657 /* Skip totally over variable string */ 03658 whereweare += (len + 3); 03659 03660 /* Store variable name (and truncate) */ 03661 ast_str_set_substr(&substr1, 0, vars, len); 03662 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03663 03664 /* Substitute if necessary */ 03665 if (needsub) { 03666 size_t used; 03667 if (!substr2) { 03668 substr2 = ast_str_create(16); 03669 } 03670 03671 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03672 finalvars = ast_str_buffer(substr2); 03673 } else { 03674 finalvars = ast_str_buffer(substr1); 03675 } 03676 03677 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03678 if (isfunction) { 03679 /* Evaluate function */ 03680 if (c || !headp) { 03681 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03682 } else { 03683 struct varshead old; 03684 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03685 if (bogus) { 03686 memcpy(&old, &bogus->varshead, sizeof(old)); 03687 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03688 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03689 /* Don't deallocate the varshead that was passed in */ 03690 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03691 ast_channel_release(bogus); 03692 } else { 03693 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03694 } 03695 } 03696 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03697 } else { 03698 /* Retrieve variable value */ 03699 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 03700 cp4 = ast_str_buffer(substr3); 03701 } 03702 if (cp4) { 03703 ast_str_substring(substr3, offset, offset2); 03704 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03705 } 03706 } else if (nextexp) { 03707 /* We have an expression. Find the start and end, and determine 03708 if we are going to have to recursively call ourselves on the 03709 contents */ 03710 vars = vare = nextexp + 2; 03711 brackets = 1; 03712 needsub = 0; 03713 03714 /* Find the end of it */ 03715 while (brackets && *vare) { 03716 if ((vare[0] == '$') && (vare[1] == '[')) { 03717 needsub++; 03718 brackets++; 03719 vare++; 03720 } else if (vare[0] == '[') { 03721 brackets++; 03722 } else if (vare[0] == ']') { 03723 brackets--; 03724 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03725 needsub++; 03726 vare++; 03727 } 03728 vare++; 03729 } 03730 if (brackets) 03731 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03732 len = vare - vars - 1; 03733 03734 /* Skip totally over expression */ 03735 whereweare += (len + 3); 03736 03737 /* Store variable name (and truncate) */ 03738 ast_str_set_substr(&substr1, 0, vars, len); 03739 03740 /* Substitute if necessary */ 03741 if (needsub) { 03742 size_t used; 03743 if (!substr2) { 03744 substr2 = ast_str_create(16); 03745 } 03746 03747 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03748 finalvars = ast_str_buffer(substr2); 03749 } else { 03750 finalvars = ast_str_buffer(substr1); 03751 } 03752 03753 if (ast_str_expr(&substr3, 0, c, finalvars)) { 03754 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 03755 } 03756 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03757 } 03758 } 03759 *used = ast_str_strlen(*buf) - orig_size; 03760 ast_free(substr1); 03761 ast_free(substr2); 03762 ast_free(substr3); 03763 }
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 3771 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().
03772 { 03773 size_t used; 03774 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 03775 }
static const char* ast_str_substring | ( | struct ast_str * | value, | |
int | offset, | |||
int | length | |||
) | [static] |
Definition at line 2922 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().
02923 { 02924 int lr; /* length of the input string after the copy */ 02925 02926 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 02927 02928 /* Quick check if no need to do anything */ 02929 if (offset == 0 && length >= lr) /* take the whole string */ 02930 return ast_str_buffer(value); 02931 02932 if (offset < 0) { /* translate negative offset into positive ones */ 02933 offset = lr + offset; 02934 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02935 offset = 0; 02936 } 02937 02938 /* too large offset result in empty string so we know what to return */ 02939 if (offset >= lr) { 02940 ast_str_reset(value); 02941 return ast_str_buffer(value); 02942 } 02943 02944 if (offset > 0) { 02945 /* Go ahead and chop off the beginning */ 02946 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 02947 lr -= offset; 02948 } 02949 02950 if (length >= 0 && length < lr) { /* truncate if necessary */ 02951 char *tmp = ast_str_buffer(value); 02952 tmp[length] = '\0'; 02953 ast_str_update(value); 02954 } else if (length < 0) { 02955 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 02956 char *tmp = ast_str_buffer(value); 02957 tmp[lr + length] = '\0'; 02958 ast_str_update(value); 02959 } else { 02960 ast_str_reset(value); 02961 } 02962 } else { 02963 /* Nothing to do, but update the buffer length */ 02964 ast_str_update(value); 02965 } 02966 02967 return ast_str_buffer(value); 02968 }
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 9932 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().
09933 { 09934 return ast_rwlock_unlock(&con->lock); 09935 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 9914 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09915 { 09916 return ast_mutex_unlock(&conlock); 09917 }
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 6827 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().
06828 { 06829 struct ast_app *tmp; 06830 06831 AST_RWLIST_WRLOCK(&apps); 06832 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 06833 if (!strcasecmp(app, tmp->name)) { 06834 unreference_cached_app(tmp); 06835 AST_RWLIST_REMOVE_CURRENT(list); 06836 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 06837 ast_string_field_free_memory(tmp); 06838 ast_free(tmp); 06839 break; 06840 } 06841 } 06842 AST_RWLIST_TRAVERSE_SAFE_END; 06843 AST_RWLIST_UNLOCK(&apps); 06844 06845 return tmp ? 0 : -1; 06846 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 5609 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().
05610 { 05611 AST_RWLIST_WRLOCK(&switches); 05612 AST_RWLIST_REMOVE(&switches, sw, list); 05613 AST_RWLIST_UNLOCK(&switches); 05614 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 10046 of file pbx.c.
References exten, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
10048 { 10049 if (!exten) 10050 return con ? con->root : NULL; 10051 else 10052 return exten->next; 10053 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 10079 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10081 { 10082 if (!ip) 10083 return con ? con->ignorepats : NULL; 10084 else 10085 return ip->next; 10086 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 10070 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
10072 { 10073 if (!inc) 10074 return con ? con->includes : NULL; 10075 else 10076 return inc->next; 10077 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 10055 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, AST_LIST_NEXT, and ast_sw::list.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10057 { 10058 if (!sw) 10059 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10060 else 10061 return AST_LIST_NEXT(sw, list); 10062 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 10041 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 10064 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 9922 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().
09923 { 09924 return ast_rwlock_wrlock(&con->lock); 09925 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 9904 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), and complete_dialplan_remove_include().
09905 { 09906 return ast_mutex_lock(&conlock); 09907 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 8287 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().
08288 { 08289 struct async_stat *as = data; 08290 struct ast_channel *chan = as->chan; 08291 int timeout = as->timeout; 08292 int res; 08293 struct ast_frame *f; 08294 struct ast_app *app; 08295 08296 while (timeout && (chan->_state != AST_STATE_UP)) { 08297 res = ast_waitfor(chan, timeout); 08298 if (res < 1) 08299 break; 08300 if (timeout > -1) 08301 timeout = res; 08302 f = ast_read(chan); 08303 if (!f) 08304 break; 08305 if (f->frametype == AST_FRAME_CONTROL) { 08306 if ((f->subclass.integer == AST_CONTROL_BUSY) || 08307 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 08308 ast_frfree(f); 08309 break; 08310 } 08311 } 08312 ast_frfree(f); 08313 } 08314 if (chan->_state == AST_STATE_UP) { 08315 if (!ast_strlen_zero(as->app)) { 08316 app = pbx_findapp(as->app); 08317 if (app) { 08318 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 08319 pbx_exec(chan, app, as->appdata); 08320 } else 08321 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 08322 } else { 08323 if (!ast_strlen_zero(as->context)) 08324 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 08325 if (!ast_strlen_zero(as->exten)) 08326 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 08327 if (as->priority > 0) 08328 chan->priority = as->priority; 08329 /* Run the PBX */ 08330 if (ast_pbx_run(chan)) { 08331 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 08332 } else { 08333 /* PBX will have taken care of this */ 08334 chan = NULL; 08335 } 08336 } 08337 } 08338 ast_free(as); 08339 if (chan) 08340 ast_hangup(chan); 08341 return NULL; 08342 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1585 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().
01586 { 01587 char extenstr[40]; 01588 struct ast_str *my_prefix = ast_str_alloca(1024); 01589 01590 extenstr[0] = '\0'; 01591 01592 if (node && node->exten) 01593 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01594 01595 if (strlen(node->x) > 1) { 01596 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01597 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01598 node->exten ? node->exten->exten : "", extenstr); 01599 } else { 01600 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01601 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01602 node->exten ? node->exten->exten : "", extenstr); 01603 } 01604 01605 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01606 01607 if (node->next_char) 01608 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01609 01610 if (node->alt_char) 01611 cli_match_char_tree(node->alt_char, prefix, fd); 01612 }
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 4624 of file pbx.c.
References ast_channel::_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.
04625 { 04626 int digit; 04627 04628 buf[pos] = '\0'; /* make sure it is properly terminated */ 04629 while (ast_matchmore_extension(c, c->context, buf, 1, 04630 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04631 /* As long as we're willing to wait, and as long as it's not defined, 04632 keep reading digits until we can't possibly get a right answer anymore. */ 04633 digit = ast_waitfordigit(c, waittime); 04634 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04635 c->_softhangup &= ~AST_SOFTHANGUP_ASYNCGOTO; 04636 } else { 04637 if (!digit) /* No entry */ 04638 break; 04639 if (digit < 0) /* Error, maybe a hangup */ 04640 return -1; 04641 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 04642 buf[pos++] = digit; 04643 buf[pos] = '\0'; 04644 } 04645 waittime = c->pbx->dtimeoutms; 04646 } 04647 } 04648 return 0; 04649 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 1033 of file pbx.c.
Referenced by add_exten_to_pattern_tree().
01034 { 01035 const char *ac = a; 01036 const char *bc = b; 01037 if ((*ac) < (*bc)) 01038 return -1; 01039 else if ((*ac) == (*bc)) 01040 return 0; 01041 else 01042 return 1; 01043 }
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 5794 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().
05795 { 05796 struct ast_hint *hint; 05797 char *ret = NULL; 05798 int which = 0; 05799 int wordlen; 05800 struct ao2_iterator i; 05801 05802 if (pos != 3) 05803 return NULL; 05804 05805 wordlen = strlen(word); 05806 05807 /* walk through all hints */ 05808 i = ao2_iterator_init(hints, 0); 05809 for (hint = ao2_iterator_next(&i); hint; ao2_unlock(hint), ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 05810 ao2_lock(hint); 05811 if (!strncasecmp(word, hint->exten ? ast_get_extension_name(hint->exten) : "", wordlen) && ++which > state) { 05812 ret = ast_strdup(ast_get_extension_name(hint->exten)); 05813 ao2_unlock(hint); 05814 break; 05815 } 05816 } 05817 ao2_iterator_destroy(&i); 05818 05819 return ret; 05820 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 5995 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().
05997 { 05998 struct ast_context *c = NULL; 05999 char *ret = NULL; 06000 int which = 0; 06001 int wordlen; 06002 06003 /* we are do completion of [exten@]context on second position only */ 06004 if (pos != 2) 06005 return NULL; 06006 06007 ast_rdlock_contexts(); 06008 06009 wordlen = strlen(word); 06010 06011 /* walk through all contexts and return the n-th match */ 06012 while ( (c = ast_walk_contexts(c)) ) { 06013 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06014 ret = ast_strdup(ast_get_context_name(c)); 06015 break; 06016 } 06017 } 06018 06019 ast_unlock_contexts(); 06020 06021 return ret; 06022 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 6963 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().
06964 { 06965 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 06966 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 06967 struct ast_hashtab_iter *exten_iter; 06968 struct ast_hashtab_iter *prio_iter; 06969 int insert_count = 0; 06970 int first = 1; 06971 06972 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 06973 the current registrar, and copy them to the new context. If the new context does not 06974 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 06975 only create the empty matching context if the old one meets the criteria */ 06976 06977 if (context->root_table) { 06978 exten_iter = ast_hashtab_start_traversal(context->root_table); 06979 while ((exten_item=ast_hashtab_next(exten_iter))) { 06980 if (new) { 06981 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 06982 } else { 06983 new_exten_item = NULL; 06984 } 06985 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 06986 while ((prio_item=ast_hashtab_next(prio_iter))) { 06987 int res1; 06988 char *dupdstr; 06989 06990 if (new_exten_item) { 06991 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 06992 } else { 06993 new_prio_item = NULL; 06994 } 06995 if (strcmp(prio_item->registrar,registrar) == 0) { 06996 continue; 06997 } 06998 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 06999 if (!new) { 07000 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 */ 07001 } 07002 07003 /* copy in the includes, switches, and ignorepats */ 07004 if (first) { /* but, only need to do this once */ 07005 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07006 first = 0; 07007 } 07008 07009 if (!new) { 07010 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07011 return; /* no sense continuing. */ 07012 } 07013 /* we will not replace existing entries in the new context with stuff from the old context. 07014 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07015 07016 dupdstr = ast_strdup(prio_item->data); 07017 07018 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07019 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07020 if (!res1 && new_exten_item && new_prio_item){ 07021 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07022 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07023 } else { 07024 /* 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, 07025 and no double frees take place, either! */ 07026 insert_count++; 07027 } 07028 } 07029 ast_hashtab_end_traversal(prio_iter); 07030 } 07031 ast_hashtab_end_traversal(exten_iter); 07032 } 07033 07034 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07035 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07036 /* we could have given it the registrar of the other module who incremented the refcount, 07037 but that's not available, so we give it the registrar we know about */ 07038 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07039 07040 /* copy in the includes, switches, and ignorepats */ 07041 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07042 } 07043 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 6930 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().
06931 { 06932 struct ast_include *i; 06933 struct ast_ignorepat *ip; 06934 struct ast_sw *sw; 06935 06936 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); 06937 /* copy in the includes, switches, and ignorepats */ 06938 /* walk through includes */ 06939 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 06940 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 06941 continue; /* not mine */ 06942 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 06943 } 06944 06945 /* walk through switches */ 06946 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 06947 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 06948 continue; /* not mine */ 06949 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)); 06950 } 06951 06952 /* walk thru ignorepats ... */ 06953 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 06954 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 06955 continue; /* not mine */ 06956 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 06957 } 06958 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2085 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().
02086 { 02087 struct ast_hashtab_iter *t1; 02088 struct ast_exten *e1; 02089 #ifdef NEED_DEBUG 02090 int biggest_bucket, resizes, numobjs, numbucks; 02091 02092 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02093 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02094 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02095 numobjs, numbucks, biggest_bucket, resizes); 02096 #endif 02097 t1 = ast_hashtab_start_traversal(con->root_table); 02098 while ((e1 = ast_hashtab_next(t1))) { 02099 if (e1->exten) { 02100 add_exten_to_pattern_tree(con, e1, 0); 02101 } else { 02102 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02103 } 02104 } 02105 ast_hashtab_end_traversal(t1); 02106 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 4980 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().
04981 { 04982 ast_mutex_lock(&maxcalllock); 04983 if (countcalls > 0) 04984 countcalls--; 04985 ast_mutex_unlock(&maxcalllock); 04986 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 4988 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().
04989 { 04990 if (e->priority == PRIORITY_HINT) 04991 ast_remove_hint(e); 04992 04993 if (e->peer_table) 04994 ast_hashtab_destroy(e->peer_table,0); 04995 if (e->peer_label_table) 04996 ast_hashtab_destroy(e->peer_label_table, 0); 04997 if (e->datad) 04998 e->datad(e->data); 04999 ast_free(e); 05000 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2108 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().
02109 { 02110 /* destroy all the alternates */ 02111 if (pattern_tree->alt_char) { 02112 destroy_pattern_tree(pattern_tree->alt_char); 02113 pattern_tree->alt_char = 0; 02114 } 02115 /* destroy all the nexts */ 02116 if (pattern_tree->next_char) { 02117 destroy_pattern_tree(pattern_tree->next_char); 02118 pattern_tree->next_char = 0; 02119 } 02120 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02121 ast_free(pattern_tree); 02122 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 9795 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.
09796 { 09797 const char *device; 09798 struct statechange *sc; 09799 09800 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 09801 if (ast_strlen_zero(device)) { 09802 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 09803 return; 09804 } 09805 09806 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 09807 return; 09808 strcpy(sc->dev, device); 09809 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 09810 ast_free(sc); 09811 } 09812 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3113 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03114 { 03115 struct pbx_exception *exception = data; 03116 ast_string_field_free_memory(exception); 03117 ast_free(exception); 03118 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 2258 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02259 { 02260 /* make sure non-patterns come first. 02261 * If a is not a pattern, it either comes first or 02262 * we do a more complex pattern comparison. 02263 */ 02264 int ret = 0; 02265 02266 if (a[0] != '_') 02267 return (b[0] == '_') ? -1 : strcmp(a, b); 02268 02269 /* Now we know a is a pattern; if b is not, a comes first */ 02270 if (b[0] != '_') 02271 return 1; 02272 02273 /* ok we need full pattern sorting routine. 02274 * skip past the underscores */ 02275 ++a; ++b; 02276 do { 02277 unsigned char bitwise[2][32] = { { 0, } }; 02278 ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]); 02279 if (ret == 0) { 02280 /* Are the classes different, even though they score the same? */ 02281 ret = memcmp(bitwise[0], bitwise[1], 32); 02282 } 02283 } while (!ret && a && b); 02284 if (ret == 0) { 02285 return 0; 02286 } else { 02287 return (ret > 0) ? 1 : -1; 02288 } 02289 }
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 2178 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
02179 { 02180 int c, cmin = 0xff, count = 0; 02181 const char *end; 02182 02183 /* load value and advance pointer */ 02184 c = *(*p)++; 02185 02186 /* always return unless we have a set of chars */ 02187 switch (toupper(c)) { 02188 default: /* ordinary character */ 02189 bitwise[c / 8] = 1 << (c % 8); 02190 return 0x0100 | (c & 0xff); 02191 02192 case 'N': /* 2..9 */ 02193 bitwise[6] = 0xfc; 02194 bitwise[7] = 0x03; 02195 return 0x0800 | '2'; 02196 02197 case 'X': /* 0..9 */ 02198 bitwise[6] = 0xff; 02199 bitwise[7] = 0x03; 02200 return 0x0A00 | '0'; 02201 02202 case 'Z': /* 1..9 */ 02203 bitwise[6] = 0xfe; 02204 bitwise[7] = 0x03; 02205 return 0x0900 | '1'; 02206 02207 case '.': /* wildcard */ 02208 return 0x18000; 02209 02210 case '!': /* earlymatch */ 02211 return 0x28000; /* less specific than NULL */ 02212 02213 case '\0': /* empty string */ 02214 *p = NULL; 02215 return 0x30000; 02216 02217 case '[': /* pattern */ 02218 break; 02219 } 02220 /* locate end of set */ 02221 end = strchr(*p, ']'); 02222 02223 if (end == NULL) { 02224 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02225 return 0x40000; /* XXX make this entry go last... */ 02226 } 02227 02228 for (; *p < end ; (*p)++) { 02229 unsigned char c1, c2; /* first-last char in range */ 02230 c1 = (unsigned char)((*p)[0]); 02231 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02232 c2 = (unsigned char)((*p)[2]); 02233 *p += 2; /* skip a total of 3 chars */ 02234 } else { /* individual character */ 02235 c2 = c1; 02236 } 02237 if (c1 < cmin) { 02238 cmin = c1; 02239 } 02240 for (; c1 <= c2; c1++) { 02241 unsigned char mask = 1 << (c1 % 8); 02242 /*!\note If two patterns score the same, the one with the lowest 02243 * ascii values will compare as coming first. */ 02244 /* Flag the character as included (used) and count it. */ 02245 if (!(bitwise[ c1 / 8 ] & mask)) { 02246 bitwise[ c1 / 8 ] |= mask; 02247 count += 0x100; 02248 } 02249 } 02250 } 02251 (*p)++; 02252 return count == 0 ? 0x30000 : (count | cmin); 02253 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 7844 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
07845 { 07846 int count = 0; 07847 int insquares = 0; 07848 07849 while (*src && (count < len - 1)) { 07850 if (*src == '[') { 07851 insquares = 1; 07852 } else if (*src == ']') { 07853 insquares = 0; 07854 } else if (*src == ' ' && !insquares) { 07855 src++; 07856 continue; 07857 } 07858 *dst = *src; 07859 dst++; 07860 src++; 07861 count++; 07862 } 07863 *dst = '\0'; 07864 07865 return count; 07866 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2471 of file pbx.c.
References _extension_match_core(), ast_add_profile(), and ast_mark().
Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().
02472 { 02473 int i; 02474 static int prof_id = -2; /* marker for 'unallocated' id */ 02475 if (prof_id == -2) { 02476 prof_id = ast_add_profile("ext_match", 0); 02477 } 02478 ast_mark(prof_id, 1); 02479 i = _extension_match_core(pattern, data, mode); 02480 ast_mark(prof_id, 0); 02481 return i; 02482 }
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 5104 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05105 { 05106 struct ast_context *c = NULL; 05107 struct fake_context item; 05108 05109 ast_copy_string(item.name, context, sizeof(item.name)); 05110 05111 c = ast_hashtab_lookup(contexts_table,&item); 05112 05113 return c; 05114 }
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 5121 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_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
05122 { 05123 struct ast_context *c = NULL; 05124 struct fake_context item; 05125 05126 ast_copy_string(item.name, context, sizeof(item.name)); 05127 05128 ast_rdlock_contexts(); 05129 c = ast_hashtab_lookup(contexts_table,&item); 05130 05131 if (!c) 05132 ast_unlock_contexts(); 05133 05134 return c; 05135 }
static int find_hint_by_cb_id | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Remove a watcher from the callback list.
Definition at line 4388 of file pbx.c.
References AST_LIST_TRAVERSE, ast_hint::callbacks, CMP_MATCH, CMP_STOP, ast_state_cb::entry, and ast_state_cb::id.
Referenced by ast_extension_state_del().
04389 { 04390 const struct ast_hint *hint = obj; 04391 int *id = arg; 04392 struct ast_state_cb *cb; 04393 04394 AST_LIST_TRAVERSE(&hint->callbacks, cb, entry) { 04395 if (cb->id == *id) { 04396 return CMP_MATCH | CMP_STOP; 04397 } 04398 } 04399 04400 return 0; 04401 }
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 3465 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03466 { 03467 char *args = strchr(function, '('); 03468 03469 if (!args) { 03470 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 03471 } else { 03472 char *p; 03473 *args++ = '\0'; 03474 if ((p = strrchr(args, ')'))) { 03475 *p = '\0'; 03476 } else { 03477 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 03478 } 03479 } 03480 return args; 03481 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static] |
Definition at line 1614 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, and match_char::next_char.
01615 { 01616 /* find the exten at the end of the rope */ 01617 struct match_char *node2 = node; 01618 01619 for (node2 = node; node2; node2 = node2->next_char) { 01620 if (node2->exten) { 01621 #ifdef NEED_DEBUG_HERE 01622 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01623 #endif 01624 return node2->exten; 01625 } 01626 } 01627 #ifdef NEED_DEBUG_HERE 01628 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01629 #endif 01630 return 0; 01631 }
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 7234 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and strsep().
Referenced by ast_build_timing().
07235 { 07236 int start, end; /* start and ending position */ 07237 unsigned int mask = 0; 07238 char *part; 07239 07240 /* Check for whole range */ 07241 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 07242 return (1 << max) - 1; 07243 } 07244 07245 while ((part = strsep(&src, "&"))) { 07246 /* Get start and ending position */ 07247 char *endpart = strchr(part, '-'); 07248 if (endpart) { 07249 *endpart++ = '\0'; 07250 } 07251 /* Find the start */ 07252 if ((start = lookup_name(part, names, max)) < 0) { 07253 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 07254 continue; 07255 } 07256 if (endpart) { /* find end of range */ 07257 if ((end = lookup_name(endpart, names, max)) < 0) { 07258 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 07259 continue; 07260 } 07261 } else { 07262 end = start; 07263 } 07264 /* Fill the mask. Remember that ranges are cyclic */ 07265 mask |= (1 << end); /* initialize with last element */ 07266 while (start != end) { 07267 mask |= (1 << start); 07268 if (++start >= max) { 07269 start = 0; 07270 } 07271 } 07272 } 07273 return mask; 07274 }
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 7277 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, ast_timing::minmask, and strsep().
Referenced by ast_build_timing().
07278 { 07279 char *endpart, *part; 07280 int x; 07281 int st_h, st_m; 07282 int endh, endm; 07283 int minute_start, minute_end; 07284 07285 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 07286 memset(i->minmask, 0, sizeof(i->minmask)); 07287 07288 /* 1-minute per bit */ 07289 /* Star is all times */ 07290 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 07291 /* 48, because each hour takes 2 integers; 30 bits each */ 07292 for (x = 0; x < 48; x++) { 07293 i->minmask[x] = 0x3fffffff; /* 30 bits */ 07294 } 07295 return; 07296 } 07297 /* Otherwise expect a range */ 07298 while ((part = strsep(×, "&"))) { 07299 if (!(endpart = strchr(part, '-'))) { 07300 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07301 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 07302 continue; 07303 } 07304 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 07305 continue; 07306 } 07307 *endpart++ = '\0'; 07308 /* why skip non digits? Mostly to skip spaces */ 07309 while (*endpart && !isdigit(*endpart)) { 07310 endpart++; 07311 } 07312 if (!*endpart) { 07313 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 07314 continue; 07315 } 07316 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07317 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 07318 continue; 07319 } 07320 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 07321 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 07322 continue; 07323 } 07324 minute_start = st_h * 60 + st_m; 07325 minute_end = endh * 60 + endm; 07326 /* Go through the time and enable each appropriate bit */ 07327 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 07328 i->minmask[x / 30] |= (1 << (x % 30)); 07329 } 07330 /* Do the last one */ 07331 i->minmask[x / 30] |= (1 << (x % 30)); 07332 } 07333 /* All done */ 07334 return; 07335 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 6320 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.
06321 { 06322 char *exten = NULL, *context = NULL; 06323 /* Variables used for different counters */ 06324 struct dialplan_counters counters; 06325 const char *incstack[AST_PBX_MAX_STACK]; 06326 06327 switch (cmd) { 06328 case CLI_INIT: 06329 e->command = "dialplan debug"; 06330 e->usage = 06331 "Usage: dialplan debug [context]\n" 06332 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 06333 return NULL; 06334 case CLI_GENERATE: 06335 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06336 } 06337 06338 memset(&counters, 0, sizeof(counters)); 06339 06340 if (a->argc != 2 && a->argc != 3) 06341 return CLI_SHOWUSAGE; 06342 06343 /* we obtain [exten@]context? if yes, split them ... */ 06344 /* note: we ignore the exten totally here .... */ 06345 if (a->argc == 3) { 06346 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06347 context = ast_strdupa(a->argv[2]); 06348 exten = strsep(&context, "@"); 06349 /* change empty strings to NULL */ 06350 if (ast_strlen_zero(exten)) 06351 exten = NULL; 06352 } else { /* no '@' char, only context given */ 06353 context = ast_strdupa(a->argv[2]); 06354 } 06355 if (ast_strlen_zero(context)) 06356 context = NULL; 06357 } 06358 /* else Show complete dial plan, context and exten are NULL */ 06359 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06360 06361 /* check for input failure and throw some error messages */ 06362 if (context && !counters.context_existence) { 06363 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06364 return CLI_FAILURE; 06365 } 06366 06367 06368 ast_cli(a->fd,"-= %d %s. =-\n", 06369 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06370 06371 /* everything ok */ 06372 return CLI_SUCCESS; 06373 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6691 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.
06692 { 06693 struct ast_channel *chan; 06694 const char *chan_name, *var_name, *var_value; 06695 06696 switch (cmd) { 06697 case CLI_INIT: 06698 e->command = "dialplan set chanvar"; 06699 e->usage = 06700 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 06701 " Set channel variable <varname> to <value>\n"; 06702 return NULL; 06703 case CLI_GENERATE: 06704 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 06705 } 06706 06707 if (a->argc != e->args + 3) 06708 return CLI_SHOWUSAGE; 06709 06710 chan_name = a->argv[e->args]; 06711 var_name = a->argv[e->args + 1]; 06712 var_value = a->argv[e->args + 2]; 06713 06714 if (!(chan = ast_channel_get_by_name(chan_name))) { 06715 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 06716 return CLI_FAILURE; 06717 } 06718 06719 pbx_builtin_setvar_helper(chan, var_name, var_value); 06720 06721 chan = ast_channel_unref(chan); 06722 06723 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 06724 06725 return CLI_SUCCESS; 06726 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6728 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.
06729 { 06730 int oldval = 0; 06731 06732 switch (cmd) { 06733 case CLI_INIT: 06734 e->command = "dialplan set extenpatternmatchnew true"; 06735 e->usage = 06736 "Usage: dialplan set extenpatternmatchnew true|false\n" 06737 " Use the NEW extension pattern matching algorithm, true or false.\n"; 06738 return NULL; 06739 case CLI_GENERATE: 06740 return NULL; 06741 } 06742 06743 if (a->argc != 4) 06744 return CLI_SHOWUSAGE; 06745 06746 oldval = pbx_set_extenpatternmatchnew(1); 06747 06748 if (oldval) 06749 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 06750 else 06751 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 06752 06753 return CLI_SUCCESS; 06754 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6669 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.
06670 { 06671 switch (cmd) { 06672 case CLI_INIT: 06673 e->command = "dialplan set global"; 06674 e->usage = 06675 "Usage: dialplan set global <name> <value>\n" 06676 " Set global dialplan variable <name> to <value>\n"; 06677 return NULL; 06678 case CLI_GENERATE: 06679 return NULL; 06680 } 06681 06682 if (a->argc != e->args + 2) 06683 return CLI_SHOWUSAGE; 06684 06685 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 06686 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 06687 06688 return CLI_SUCCESS; 06689 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5695 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.
05696 { 05697 struct ast_app *aa; 05698 int app, no_registered_app = 1; 05699 05700 switch (cmd) { 05701 case CLI_INIT: 05702 e->command = "core show application"; 05703 e->usage = 05704 "Usage: core show application <application> [<application> [<application> [...]]]\n" 05705 " Describes a particular application.\n"; 05706 return NULL; 05707 case CLI_GENERATE: 05708 /* 05709 * There is a possibility to show informations about more than one 05710 * application at one time. You can type 'show application Dial Echo' and 05711 * you will see informations about these two applications ... 05712 */ 05713 return ast_complete_applications(a->line, a->word, a->n); 05714 } 05715 05716 if (a->argc < 4) { 05717 return CLI_SHOWUSAGE; 05718 } 05719 05720 AST_RWLIST_RDLOCK(&apps); 05721 AST_RWLIST_TRAVERSE(&apps, aa, list) { 05722 /* Check for each app that was supplied as an argument */ 05723 for (app = 3; app < a->argc; app++) { 05724 if (strcasecmp(aa->name, a->argv[app])) { 05725 continue; 05726 } 05727 05728 /* We found it! */ 05729 no_registered_app = 0; 05730 05731 print_app_docs(aa, a->fd); 05732 } 05733 } 05734 AST_RWLIST_UNLOCK(&apps); 05735 05736 /* we found at least one app? no? */ 05737 if (no_registered_app) { 05738 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 05739 return CLI_FAILURE; 05740 } 05741 05742 return CLI_SUCCESS; 05743 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5909 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.
05910 { 05911 struct ast_app *aa; 05912 int like = 0, describing = 0; 05913 int total_match = 0; /* Number of matches in like clause */ 05914 int total_apps = 0; /* Number of apps registered */ 05915 static const char * const choices[] = { "like", "describing", NULL }; 05916 05917 switch (cmd) { 05918 case CLI_INIT: 05919 e->command = "core show applications [like|describing]"; 05920 e->usage = 05921 "Usage: core show applications [{like|describing} <text>]\n" 05922 " List applications which are currently available.\n" 05923 " If 'like', <text> will be a substring of the app name\n" 05924 " If 'describing', <text> will be a substring of the description\n"; 05925 return NULL; 05926 case CLI_GENERATE: 05927 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 05928 } 05929 05930 AST_RWLIST_RDLOCK(&apps); 05931 05932 if (AST_RWLIST_EMPTY(&apps)) { 05933 ast_cli(a->fd, "There are no registered applications\n"); 05934 AST_RWLIST_UNLOCK(&apps); 05935 return CLI_SUCCESS; 05936 } 05937 05938 /* core list applications like <keyword> */ 05939 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 05940 like = 1; 05941 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 05942 describing = 1; 05943 } 05944 05945 /* core list applications describing <keyword1> [<keyword2>] [...] */ 05946 if ((!like) && (!describing)) { 05947 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 05948 } else { 05949 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 05950 } 05951 05952 AST_RWLIST_TRAVERSE(&apps, aa, list) { 05953 int printapp = 0; 05954 total_apps++; 05955 if (like) { 05956 if (strcasestr(aa->name, a->argv[4])) { 05957 printapp = 1; 05958 total_match++; 05959 } 05960 } else if (describing) { 05961 if (aa->description) { 05962 /* Match all words on command line */ 05963 int i; 05964 printapp = 1; 05965 for (i = 4; i < a->argc; i++) { 05966 if (!strcasestr(aa->description, a->argv[i])) { 05967 printapp = 0; 05968 } else { 05969 total_match++; 05970 } 05971 } 05972 } 05973 } else { 05974 printapp = 1; 05975 } 05976 05977 if (printapp) { 05978 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 05979 } 05980 } 05981 if ((!like) && (!describing)) { 05982 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 05983 } else { 05984 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 05985 } 05986 05987 AST_RWLIST_UNLOCK(&apps); 05988 05989 return CLI_SUCCESS; 05990 }
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 6634 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.
06635 { 06636 struct ast_channel *chan = NULL; 06637 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 06638 06639 switch (cmd) { 06640 case CLI_INIT: 06641 e->command = "dialplan show chanvar"; 06642 e->usage = 06643 "Usage: dialplan show chanvar <channel>\n" 06644 " List current channel variables and their values\n"; 06645 return NULL; 06646 case CLI_GENERATE: 06647 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 06648 } 06649 06650 if (a->argc != e->args + 1) 06651 return CLI_SHOWUSAGE; 06652 06653 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 06654 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 06655 return CLI_FAILURE; 06656 } 06657 06658 pbx_builtin_serialize_variables(chan, &vars); 06659 06660 if (ast_str_strlen(vars)) { 06661 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 06662 } 06663 06664 chan = ast_channel_unref(chan); 06665 06666 return CLI_SUCCESS; 06667 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6253 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.
06254 { 06255 char *exten = NULL, *context = NULL; 06256 /* Variables used for different counters */ 06257 struct dialplan_counters counters; 06258 const char *incstack[AST_PBX_MAX_STACK]; 06259 06260 switch (cmd) { 06261 case CLI_INIT: 06262 e->command = "dialplan show"; 06263 e->usage = 06264 "Usage: dialplan show [[exten@]context]\n" 06265 " Show dialplan\n"; 06266 return NULL; 06267 case CLI_GENERATE: 06268 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06269 } 06270 06271 memset(&counters, 0, sizeof(counters)); 06272 06273 if (a->argc != 2 && a->argc != 3) 06274 return CLI_SHOWUSAGE; 06275 06276 /* we obtain [exten@]context? if yes, split them ... */ 06277 if (a->argc == 3) { 06278 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06279 context = ast_strdupa(a->argv[2]); 06280 exten = strsep(&context, "@"); 06281 /* change empty strings to NULL */ 06282 if (ast_strlen_zero(exten)) 06283 exten = NULL; 06284 } else { /* no '@' char, only context given */ 06285 context = ast_strdupa(a->argv[2]); 06286 } 06287 if (ast_strlen_zero(context)) 06288 context = NULL; 06289 } 06290 /* else Show complete dial plan, context and exten are NULL */ 06291 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06292 06293 /* check for input failure and throw some error messages */ 06294 if (context && !counters.context_existence) { 06295 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06296 return CLI_FAILURE; 06297 } 06298 06299 if (exten && !counters.extension_existence) { 06300 if (context) 06301 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 06302 exten, context); 06303 else 06304 ast_cli(a->fd, 06305 "There is no existence of '%s' extension in all contexts\n", 06306 exten); 06307 return CLI_FAILURE; 06308 } 06309 06310 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 06311 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 06312 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 06313 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06314 06315 /* everything ok */ 06316 return CLI_SUCCESS; 06317 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3218 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.
03219 { 03220 struct ast_custom_function *acf; 03221 /* Maximum number of characters added by terminal coloring is 22 */ 03222 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03223 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03224 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03225 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03226 char *ret = NULL; 03227 int which = 0; 03228 int wordlen; 03229 03230 switch (cmd) { 03231 case CLI_INIT: 03232 e->command = "core show function"; 03233 e->usage = 03234 "Usage: core show function <function>\n" 03235 " Describe a particular dialplan function.\n"; 03236 return NULL; 03237 case CLI_GENERATE: 03238 wordlen = strlen(a->word); 03239 /* case-insensitive for convenience in this 'complete' function */ 03240 AST_RWLIST_RDLOCK(&acf_root); 03241 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03242 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03243 ret = ast_strdup(acf->name); 03244 break; 03245 } 03246 } 03247 AST_RWLIST_UNLOCK(&acf_root); 03248 03249 return ret; 03250 } 03251 03252 if (a->argc < 4) { 03253 return CLI_SHOWUSAGE; 03254 } 03255 03256 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03257 ast_cli(a->fd, "No function by that name registered.\n"); 03258 return CLI_FAILURE; 03259 } 03260 03261 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03262 if (!(syntax = ast_malloc(syntax_size))) { 03263 ast_cli(a->fd, "Memory allocation failure!\n"); 03264 return CLI_FAILURE; 03265 } 03266 03267 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03268 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03269 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03270 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03271 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03272 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03273 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03274 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03275 #ifdef AST_XML_DOCS 03276 if (acf->docsrc == AST_XML_DOC) { 03277 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03278 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03279 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03280 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03281 } else 03282 #endif 03283 { 03284 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03285 synopsis = ast_malloc(synopsis_size); 03286 03287 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03288 description = ast_malloc(description_size); 03289 03290 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03291 arguments = ast_malloc(arguments_size); 03292 03293 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03294 seealso = ast_malloc(seealso_size); 03295 03296 /* check allocated memory. */ 03297 if (!synopsis || !description || !arguments || !seealso) { 03298 ast_free(synopsis); 03299 ast_free(description); 03300 ast_free(arguments); 03301 ast_free(seealso); 03302 ast_free(syntax); 03303 return CLI_FAILURE; 03304 } 03305 03306 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03307 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03308 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03309 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03310 } 03311 03312 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03313 infotitle, syntitle, synopsis, destitle, description, 03314 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03315 03316 ast_free(arguments); 03317 ast_free(synopsis); 03318 ast_free(description); 03319 ast_free(seealso); 03320 ast_free(syntax); 03321 03322 return CLI_SUCCESS; 03323 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3176 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.
03177 { 03178 struct ast_custom_function *acf; 03179 int count_acf = 0; 03180 int like = 0; 03181 03182 switch (cmd) { 03183 case CLI_INIT: 03184 e->command = "core show functions [like]"; 03185 e->usage = 03186 "Usage: core show functions [like <text>]\n" 03187 " List builtin functions, optionally only those matching a given string\n"; 03188 return NULL; 03189 case CLI_GENERATE: 03190 return NULL; 03191 } 03192 03193 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03194 like = 1; 03195 } else if (a->argc != 3) { 03196 return CLI_SHOWUSAGE; 03197 } 03198 03199 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03200 03201 AST_RWLIST_RDLOCK(&acf_root); 03202 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03203 if (!like || strstr(acf->name, a->argv[4])) { 03204 count_acf++; 03205 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03206 S_OR(acf->name, ""), 03207 S_OR(acf->syntax, ""), 03208 S_OR(acf->synopsis, "")); 03209 } 03210 } 03211 AST_RWLIST_UNLOCK(&acf_root); 03212 03213 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03214 03215 return CLI_SUCCESS; 03216 }
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 6576 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.
06577 { 06578 int i = 0; 06579 struct ast_var_t *newvariable; 06580 06581 switch (cmd) { 06582 case CLI_INIT: 06583 e->command = "dialplan show globals"; 06584 e->usage = 06585 "Usage: dialplan show globals\n" 06586 " List current global dialplan variables and their values\n"; 06587 return NULL; 06588 case CLI_GENERATE: 06589 return NULL; 06590 } 06591 06592 ast_rwlock_rdlock(&globalslock); 06593 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 06594 i++; 06595 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 06596 } 06597 ast_rwlock_unlock(&globalslock); 06598 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 06599 06600 return CLI_SUCCESS; 06601 }
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 5823 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_LIST_TRAVERSE, 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.
05824 { 05825 struct ast_hint *hint; 05826 int watchers; 05827 int num = 0, extenlen; 05828 struct ast_state_cb *watcher; 05829 struct ao2_iterator i; 05830 05831 switch (cmd) { 05832 case CLI_INIT: 05833 e->command = "core show hint"; 05834 e->usage = 05835 "Usage: core show hint <exten>\n" 05836 " List registered hint\n"; 05837 return NULL; 05838 case CLI_GENERATE: 05839 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 05840 } 05841 05842 if (a->argc < 4) 05843 return CLI_SHOWUSAGE; 05844 05845 if (ao2_container_count(hints) == 0) { 05846 ast_cli(a->fd, "There are no registered dialplan hints\n"); 05847 return CLI_SUCCESS; 05848 } 05849 05850 extenlen = strlen(a->argv[3]); 05851 i = ao2_iterator_init(hints, 0); 05852 for (hint = ao2_iterator_next(&i); hint; ao2_unlock(hint), ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 05853 ao2_lock(hint); 05854 if (!strncasecmp(hint->exten ? ast_get_extension_name(hint->exten) : "", a->argv[3], extenlen)) { 05855 watchers = 0; 05856 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 05857 watchers++; 05858 } 05859 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 05860 ast_get_extension_name(hint->exten), 05861 ast_get_context_name(ast_get_extension_context(hint->exten)), 05862 ast_get_extension_app(hint->exten), 05863 ast_extension_state2str(hint->laststate), watchers); 05864 num++; 05865 } 05866 } 05867 ao2_iterator_destroy(&i); 05868 if (!num) 05869 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 05870 else 05871 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 05872 return CLI_SUCCESS; 05873 }
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 5746 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_LIST_TRAVERSE, 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.
05747 { 05748 struct ast_hint *hint; 05749 int num = 0; 05750 int watchers; 05751 struct ast_state_cb *watcher; 05752 struct ao2_iterator i; 05753 05754 switch (cmd) { 05755 case CLI_INIT: 05756 e->command = "core show hints"; 05757 e->usage = 05758 "Usage: core show hints\n" 05759 " List registered hints\n"; 05760 return NULL; 05761 case CLI_GENERATE: 05762 return NULL; 05763 } 05764 05765 if (ao2_container_count(hints) == 0) { 05766 ast_cli(a->fd, "There are no registered dialplan hints\n"); 05767 return CLI_SUCCESS; 05768 } 05769 /* ... we have hints ... */ 05770 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 05771 05772 i = ao2_iterator_init(hints, 0); 05773 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 05774 05775 watchers = 0; 05776 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 05777 watchers++; 05778 } 05779 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 05780 ast_get_extension_name(hint->exten), 05781 ast_get_context_name(ast_get_extension_context(hint->exten)), 05782 ast_get_extension_app(hint->exten), 05783 ast_extension_state2str(hint->laststate), watchers); 05784 num++; 05785 } 05786 05787 ao2_iterator_destroy(&i); 05788 ast_cli(a->fd, "----------------\n"); 05789 ast_cli(a->fd, "- %d hints registered\n", num); 05790 return CLI_SUCCESS; 05791 }
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 5877 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.
05878 { 05879 struct ast_switch *sw; 05880 05881 switch (cmd) { 05882 case CLI_INIT: 05883 e->command = "core show switches"; 05884 e->usage = 05885 "Usage: core show switches\n" 05886 " List registered switches\n"; 05887 return NULL; 05888 case CLI_GENERATE: 05889 return NULL; 05890 } 05891 05892 AST_RWLIST_RDLOCK(&switches); 05893 05894 if (AST_RWLIST_EMPTY(&switches)) { 05895 AST_RWLIST_UNLOCK(&switches); 05896 ast_cli(a->fd, "There are no registered alternative switches\n"); 05897 return CLI_SUCCESS; 05898 } 05899 05900 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 05901 AST_RWLIST_TRAVERSE(&switches, sw, list) 05902 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 05903 05904 AST_RWLIST_UNLOCK(&switches); 05905 05906 return CLI_SUCCESS; 05907 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4230 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_extension_state2(), ast_free, ast_get_extension_app(), AST_LIST_TRAVERSE, ast_rdlock_contexts(), ast_str_create(), ast_str_set(), ast_unlock_contexts(), ast_hint::callbacks, statechange::dev, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, ast_context::name, ast_exten::parent, parse(), str, and strsep().
04231 { 04232 struct ast_hint *hint; 04233 struct ast_str *str; 04234 struct statechange *sc = datap; 04235 struct ao2_iterator i; 04236 04237 if (!(str = ast_str_create(1024))) { 04238 return -1; 04239 } 04240 04241 04242 i = ao2_iterator_init(hints, 0); 04243 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 04244 struct ast_state_cb *cblist; 04245 char *cur, *parse; 04246 int state; 04247 04248 ast_str_set(&str, 0, "%s", ast_get_extension_app(hint->exten)); 04249 parse = str->str; 04250 04251 while ( (cur = strsep(&parse, "&")) ) { 04252 if (!strcasecmp(cur, sc->dev)) { 04253 break; 04254 } 04255 } 04256 04257 if (!cur) { 04258 continue; 04259 } 04260 04261 /* Get device state for this hint */ 04262 state = ast_extension_state2(hint->exten); 04263 04264 if ((state == -1) || (state == hint->laststate)) { 04265 continue; 04266 } 04267 04268 /* Device state changed since last check - notify the watchers */ 04269 04270 ast_rdlock_contexts(); 04271 ao2_lock(hints); 04272 ao2_lock(hint); 04273 04274 if (hint->exten == NULL) { 04275 /* the extension has been destroyed */ 04276 ao2_unlock(hint); 04277 ao2_unlock(hints); 04278 ast_unlock_contexts(); 04279 continue; 04280 } 04281 04282 /* For general callbacks */ 04283 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 04284 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 04285 } 04286 04287 /* For extension callbacks */ 04288 AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) { 04289 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 04290 } 04291 04292 hint->laststate = state; /* record we saw the change */ 04293 ao2_unlock(hint); 04294 ao2_unlock(hints); 04295 ast_unlock_contexts(); 04296 } 04297 ao2_iterator_destroy(&i); 04298 ast_free(str); 04299 ast_free(sc); 04300 return 0; 04301 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6756 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.
06757 { 06758 int oldval = 0; 06759 06760 switch (cmd) { 06761 case CLI_INIT: 06762 e->command = "dialplan set extenpatternmatchnew false"; 06763 e->usage = 06764 "Usage: dialplan set extenpatternmatchnew true|false\n" 06765 " Use the NEW extension pattern matching algorithm, true or false.\n"; 06766 return NULL; 06767 case CLI_GENERATE: 06768 return NULL; 06769 } 06770 06771 if (a->argc != 4) 06772 return CLI_SHOWUSAGE; 06773 06774 oldval = pbx_set_extenpatternmatchnew(0); 06775 06776 if (!oldval) 06777 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 06778 else 06779 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 06780 06781 return CLI_SUCCESS; 06782 }
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 1075 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01076 { 01077 const struct ast_exten *ac = ah_a; 01078 const struct ast_exten *bc = ah_b; 01079 return ac->priority != bc->priority; 01080 }
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1056 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01057 { 01058 const struct ast_exten *ac = ah_a; 01059 const struct ast_exten *bc = ah_b; 01060 int x = strcmp(ac->exten, bc->exten); 01061 if (x) { /* if exten names are diff, then return */ 01062 return x; 01063 } 01064 01065 /* but if they are the same, do the cidmatch values match? */ 01066 if (ac->matchcid && bc->matchcid) { 01067 return strcmp(ac->cidmatch,bc->cidmatch); 01068 } else if (!ac->matchcid && !bc->matchcid) { 01069 return 0; /* if there's no matchcid on either side, then this is a match */ 01070 } else { 01071 return 1; /* if there's matchcid on one but not the other, they are different */ 01072 } 01073 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1095 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().
01096 { 01097 const struct ast_exten *ac = obj; 01098 unsigned int x = ast_hashtab_hash_string(ac->exten); 01099 unsigned int y = 0; 01100 if (ac->matchcid) 01101 y = ast_hashtab_hash_string(ac->cidmatch); 01102 return x+y; 01103 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1111 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01112 { 01113 const struct ast_exten *ac = obj; 01114 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01115 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1105 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01106 { 01107 const struct ast_exten *ac = obj; 01108 return ast_hashtab_hash_int(ac->priority); 01109 }
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 10222 of file pbx.c.
References ast_get_extension_name(), ast_str_case_hash(), and ast_hint::exten.
Referenced by ast_pbx_init().
10223 { 10224 const struct ast_hint *hint = obj; 10225 10226 int res = -1; 10227 10228 if (ast_get_extension_name(hint->exten)) { 10229 res = ast_str_case_hash(ast_get_extension_name(hint->exten)); 10230 } 10231 10232 return res; 10233 }
static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 9818 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_LIST_TRAVERSE, ast_hint::callbacks, ast_hint::exten, hints, and ast_hint::laststate.
09820 { 09821 struct ast_data *data_hint; 09822 struct ast_hint *hint; 09823 int watchers; 09824 struct ast_state_cb *watcher; 09825 struct ao2_iterator i; 09826 09827 if (ao2_container_count(hints) == 0) { 09828 return 0; 09829 } 09830 09831 i = ao2_iterator_init(hints, 0); 09832 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 09833 watchers = 0; 09834 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 09835 watchers++; 09836 } 09837 data_hint = ast_data_add_node(data_root, "hint"); 09838 if (!data_hint) { 09839 continue; 09840 } 09841 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 09842 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 09843 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 09844 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 09845 ast_data_add_int(data_hint, "watchers", watchers); 09846 09847 if (!ast_data_search_match(search, data_hint)) { 09848 ast_data_remove_node(data_root, data_hint); 09849 } 09850 } 09851 ao2_iterator_destroy(&i); 09852 09853 return 0; 09854 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1451 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01452 { 01453 if (!i->hastime) 01454 return 1; 01455 01456 return ast_check_timing(&(i->timing)); 01457 }
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 4933 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().
04934 { 04935 int failed = 0; 04936 double curloadavg; 04937 #if defined(HAVE_SYSINFO) 04938 long curfreemem; 04939 struct sysinfo sys_info; 04940 #endif 04941 04942 ast_mutex_lock(&maxcalllock); 04943 if (option_maxcalls) { 04944 if (countcalls >= option_maxcalls) { 04945 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 04946 failed = -1; 04947 } 04948 } 04949 if (option_maxload) { 04950 getloadavg(&curloadavg, 1); 04951 if (curloadavg >= option_maxload) { 04952 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 04953 failed = -1; 04954 } 04955 } 04956 #if defined(HAVE_SYSINFO) 04957 if (option_minmemfree) { 04958 if (!sysinfo(&sys_info)) { 04959 /* make sure that the free system memory is above the configured low watermark 04960 * convert the amount of freeram from mem_units to MB */ 04961 curfreemem = sys_info.freeram / sys_info.mem_unit; 04962 curfreemem /= 1024 * 1024; 04963 if (curfreemem < option_minmemfree) { 04964 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 04965 failed = -1; 04966 } 04967 } 04968 } 04969 #endif 04970 04971 if (!failed) { 04972 countcalls++; 04973 totalcalls++; 04974 } 04975 ast_mutex_unlock(&maxcalllock); 04976 04977 return failed; 04978 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1868 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01869 { 01870 struct match_char *curr, *lcurr; 01871 01872 /* insert node into the tree at "current", so the alt_char list from current is 01873 sorted in increasing value as you go to the leaves */ 01874 if (!(*parent_ptr)) { 01875 *parent_ptr = node; 01876 return; 01877 } 01878 01879 if ((*parent_ptr)->specificity > node->specificity) { 01880 /* insert at head */ 01881 node->alt_char = (*parent_ptr); 01882 *parent_ptr = node; 01883 return; 01884 } 01885 01886 lcurr = *parent_ptr; 01887 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01888 if (curr->specificity > node->specificity) { 01889 node->alt_char = curr; 01890 lcurr->alt_char = node; 01891 break; 01892 } 01893 lcurr = curr; 01894 } 01895 01896 if (!curr) { 01897 lcurr->alt_char = node; 01898 } 01899 01900 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 9865 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().
09866 { 09867 int x; 09868 09869 /* Initialize the PBX */ 09870 ast_verb(1, "Asterisk PBX Core Initializing\n"); 09871 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 09872 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 09873 } 09874 09875 ast_verb(1, "Registering builtin applications:\n"); 09876 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 09877 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 09878 __ast_custom_function_register(&exception_function, NULL); 09879 __ast_custom_function_register(&testtime_function, NULL); 09880 09881 /* Register builtin applications */ 09882 for (x = 0; x < ARRAY_LEN(builtins); x++) { 09883 ast_verb(1, "[%s]\n", builtins[x].name); 09884 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 09885 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 09886 return -1; 09887 } 09888 } 09889 09890 /* Register manager application */ 09891 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 09892 09893 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 09894 AST_EVENT_IE_END))) { 09895 return -1; 09896 } 09897 09898 return 0; 09899 }
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 7211 of file pbx.c.
Referenced by get_range().
07212 { 07213 int i; 07214 07215 if (names && *s > '9') { 07216 for (i = 0; names[i]; i++) { 07217 if (!strcasecmp(s, names[i])) { 07218 return i; 07219 } 07220 } 07221 } 07222 07223 /* Allow months and weekdays to be specified as numbers, as well */ 07224 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 07225 /* What the array offset would have been: "1" would be at offset 0 */ 07226 return i - 1; 07227 } 07228 return -1; /* error return */ 07229 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 6376 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan_helper().
06377 { 06378 astman_send_listack(s, m, "DialPlan list will follow", "start"); 06379 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 6522 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().
06523 { 06524 const char *exten, *context; 06525 const char *id = astman_get_header(m, "ActionID"); 06526 char idtext[256]; 06527 int res; 06528 06529 /* Variables used for different counters */ 06530 struct dialplan_counters counters; 06531 06532 if (!ast_strlen_zero(id)) 06533 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 06534 else 06535 idtext[0] = '\0'; 06536 06537 memset(&counters, 0, sizeof(counters)); 06538 06539 exten = astman_get_header(m, "Extension"); 06540 context = astman_get_header(m, "Context"); 06541 06542 res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 06543 06544 if (context && !counters.context_existence) { 06545 char errorbuf[BUFSIZ]; 06546 06547 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 06548 astman_send_error(s, m, errorbuf); 06549 return 0; 06550 } 06551 if (exten && !counters.extension_existence) { 06552 char errorbuf[BUFSIZ]; 06553 06554 if (context) 06555 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 06556 else 06557 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 06558 astman_send_error(s, m, errorbuf); 06559 return 0; 06560 } 06561 06562 astman_append(s, "Event: ShowDialPlanComplete\r\n" 06563 "EventList: Complete\r\n" 06564 "ListItems: %d\r\n" 06565 "ListExtensions: %d\r\n" 06566 "ListPriorities: %d\r\n" 06567 "ListContexts: %d\r\n" 06568 "%s" 06569 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 06570 06571 /* everything ok */ 06572 return 0; 06573 }
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 6385 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().
06389 { 06390 struct ast_context *c; 06391 int res = 0, old_total_exten = dpc->total_exten; 06392 06393 if (ast_strlen_zero(exten)) 06394 exten = NULL; 06395 if (ast_strlen_zero(context)) 06396 context = NULL; 06397 06398 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 06399 06400 /* try to lock contexts */ 06401 if (ast_rdlock_contexts()) { 06402 astman_send_error(s, m, "Failed to lock contexts"); 06403 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 06404 return -1; 06405 } 06406 06407 c = NULL; /* walk all contexts ... */ 06408 while ( (c = ast_walk_contexts(c)) ) { 06409 struct ast_exten *e; 06410 struct ast_include *i; 06411 struct ast_ignorepat *ip; 06412 06413 if (context && strcmp(ast_get_context_name(c), context) != 0) 06414 continue; /* not the name we want */ 06415 06416 dpc->context_existence = 1; 06417 06418 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 06419 06420 if (ast_rdlock_context(c)) { /* failed to lock */ 06421 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 06422 continue; 06423 } 06424 06425 /* XXX note- an empty context is not printed */ 06426 e = NULL; /* walk extensions in context */ 06427 while ( (e = ast_walk_context_extensions(c, e)) ) { 06428 struct ast_exten *p; 06429 06430 /* looking for extension? is this our extension? */ 06431 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 06432 /* not the one we are looking for, continue */ 06433 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 06434 continue; 06435 } 06436 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 06437 06438 dpc->extension_existence = 1; 06439 06440 /* may we print context info? */ 06441 dpc->total_context++; 06442 dpc->total_exten++; 06443 06444 p = NULL; /* walk next extension peers */ 06445 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06446 int prio = ast_get_extension_priority(p); 06447 06448 dpc->total_prio++; 06449 if (!dpc->total_items++) 06450 manager_dpsendack(s, m); 06451 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06452 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 06453 06454 /* XXX maybe make this conditional, if p != e ? */ 06455 if (ast_get_extension_label(p)) 06456 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 06457 06458 if (prio == PRIORITY_HINT) { 06459 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 06460 } else { 06461 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)); 06462 } 06463 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 06464 } 06465 } 06466 06467 i = NULL; /* walk included and write info ... */ 06468 while ( (i = ast_walk_context_includes(c, i)) ) { 06469 if (exten) { 06470 /* Check all includes for the requested extension */ 06471 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 06472 } else { 06473 if (!dpc->total_items++) 06474 manager_dpsendack(s, m); 06475 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06476 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)); 06477 astman_append(s, "\r\n"); 06478 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 06479 } 06480 } 06481 06482 ip = NULL; /* walk ignore patterns and write info ... */ 06483 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06484 const char *ipname = ast_get_ignorepat_name(ip); 06485 char ignorepat[AST_MAX_EXTENSION]; 06486 06487 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06488 if (!exten || ast_extension_match(ignorepat, exten)) { 06489 if (!dpc->total_items++) 06490 manager_dpsendack(s, m); 06491 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06492 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 06493 astman_append(s, "\r\n"); 06494 } 06495 } 06496 if (!rinclude) { 06497 struct ast_sw *sw = NULL; 06498 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06499 if (!dpc->total_items++) 06500 manager_dpsendack(s, m); 06501 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06502 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)); 06503 astman_append(s, "\r\n"); 06504 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 06505 } 06506 } 06507 06508 ast_unlock_context(c); 06509 } 06510 ast_unlock_contexts(); 06511 06512 if (dpc->total_exten == old_total_exten) { 06513 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 06514 /* Nothing new under the sun */ 06515 return -1; 06516 } else { 06517 return res; 06518 } 06519 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2539 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02540 { 02541 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02542 failing to get a number should count as a match, otherwise not */ 02543 02544 if (ast_strlen_zero(callerid)) { 02545 return ast_strlen_zero(cidpattern) ? 1 : 0; 02546 } 02547 02548 return ast_extension_match(cidpattern, callerid); 02549 }
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 1692 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().
01693 { 01694 struct match_char *p; /* note minimal stack storage requirements */ 01695 struct ast_exten pattern = { .label = label }; 01696 #ifdef DEBUG_THIS 01697 if (tree) 01698 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01699 else 01700 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01701 #endif 01702 for (p = tree; p; p = p->alt_char) { 01703 if (p->is_pattern) { 01704 if (p->x[0] == 'N') { 01705 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01706 #define NEW_MATCHER_CHK_MATCH \ 01707 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01708 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01709 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01710 if (!p->deleted) { \ 01711 if (action == E_FINDLABEL) { \ 01712 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01713 ast_debug(4, "Found label in preferred extension\n"); \ 01714 return; \ 01715 } \ 01716 } else { \ 01717 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01718 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01719 } \ 01720 } \ 01721 } \ 01722 } 01723 01724 #define NEW_MATCHER_RECURSE \ 01725 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01726 || p->next_char->x[0] == '!')) { \ 01727 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01728 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01729 if (score->exten) { \ 01730 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01731 return; /* the first match is all we need */ \ 01732 } \ 01733 } else { \ 01734 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01735 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01736 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01737 "NULL"); \ 01738 return; /* the first match is all we need */ \ 01739 } \ 01740 } \ 01741 } else if (p->next_char && !*(str + 1)) { \ 01742 score->canmatch = 1; \ 01743 score->canmatch_exten = get_canmatch_exten(p); \ 01744 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01745 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01746 return; \ 01747 } \ 01748 } 01749 01750 NEW_MATCHER_CHK_MATCH; 01751 NEW_MATCHER_RECURSE; 01752 } 01753 } else if (p->x[0] == 'Z') { 01754 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01755 NEW_MATCHER_CHK_MATCH; 01756 NEW_MATCHER_RECURSE; 01757 } 01758 } else if (p->x[0] == 'X') { 01759 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01760 NEW_MATCHER_CHK_MATCH; 01761 NEW_MATCHER_RECURSE; 01762 } 01763 } else if (p->x[0] == '.' && p->x[1] == 0) { 01764 /* how many chars will the . match against? */ 01765 int i = 0; 01766 const char *str2 = str; 01767 while (*str2 && *str2 != '/') { 01768 str2++; 01769 i++; 01770 } 01771 if (p->exten && *str2 != '/') { 01772 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01773 if (score->exten) { 01774 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01775 return; /* the first match is all we need */ 01776 } 01777 } 01778 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01779 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01780 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01781 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01782 return; /* the first match is all we need */ 01783 } 01784 } 01785 } else if (p->x[0] == '!' && p->x[1] == 0) { 01786 /* how many chars will the . match against? */ 01787 int i = 1; 01788 const char *str2 = str; 01789 while (*str2 && *str2 != '/') { 01790 str2++; 01791 i++; 01792 } 01793 if (p->exten && *str2 != '/') { 01794 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01795 if (score->exten) { 01796 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01797 return; /* the first match is all we need */ 01798 } 01799 } 01800 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01801 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01802 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01803 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01804 return; /* the first match is all we need */ 01805 } 01806 } 01807 } else if (p->x[0] == '/' && p->x[1] == 0) { 01808 /* the pattern in the tree includes the cid match! */ 01809 if (p->next_char && callerid && *callerid) { 01810 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01811 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01812 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01813 return; /* the first match is all we need */ 01814 } 01815 } 01816 } else if (strchr(p->x, *str)) { 01817 ast_debug(4, "Nothing strange about this match\n"); 01818 NEW_MATCHER_CHK_MATCH; 01819 NEW_MATCHER_RECURSE; 01820 } 01821 } else if (strchr(p->x, *str)) { 01822 ast_debug(4, "Nothing strange about this match\n"); 01823 NEW_MATCHER_CHK_MATCH; 01824 NEW_MATCHER_RECURSE; 01825 } 01826 } 01827 ast_debug(4, "return at end of func\n"); 01828 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 2853 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
02854 { 02855 int parens = 0; 02856 02857 *offset = 0; 02858 *length = INT_MAX; 02859 *isfunc = 0; 02860 for (; *var; var++) { 02861 if (*var == '(') { 02862 (*isfunc)++; 02863 parens++; 02864 } else if (*var == ')') { 02865 parens--; 02866 } else if (*var == ':' && parens == 0) { 02867 *var++ = '\0'; 02868 sscanf(var, "%30d:%30d", offset, length); 02869 return 1; /* offset:length valid */ 02870 } 02871 } 02872 return 0; 02873 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 9694 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().
09695 { 09696 struct ast_var_t *vardata; 09697 09698 ast_rwlock_wrlock(&globalslock); 09699 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 09700 ast_var_delete(vardata); 09701 ast_rwlock_unlock(&globalslock); 09702 }
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 9456 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(), crement_function_read(), dahdi_hangup(), dahdi_r2_answer(), dahdi_r2_get_channel_category(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sig_pri_call(), sig_pri_hangup(), sig_ss7_call(), sig_ss7_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().
09457 { 09458 struct ast_var_t *variables; 09459 const char *ret = NULL; 09460 int i; 09461 struct varshead *places[2] = { NULL, &globals }; 09462 09463 if (!name) 09464 return NULL; 09465 09466 if (chan) { 09467 ast_channel_lock(chan); 09468 places[0] = &chan->varshead; 09469 } 09470 09471 for (i = 0; i < 2; i++) { 09472 if (!places[i]) 09473 continue; 09474 if (places[i] == &globals) 09475 ast_rwlock_rdlock(&globalslock); 09476 AST_LIST_TRAVERSE(places[i], variables, entries) { 09477 if (!strcmp(name, ast_var_name(variables))) { 09478 ret = ast_var_value(variables); 09479 break; 09480 } 09481 } 09482 if (places[i] == &globals) 09483 ast_rwlock_unlock(&globalslock); 09484 if (ret) 09485 break; 09486 } 09487 09488 if (chan) 09489 ast_channel_unlock(chan); 09490 09491 return ret; 09492 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9716 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
09717 { 09718 char *condition, *branch1, *branch2, *branch; 09719 char *stringp; 09720 09721 if (ast_strlen_zero(data)) { 09722 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 09723 return 0; 09724 } 09725 09726 stringp = ast_strdupa(data); 09727 condition = strsep(&stringp,"?"); 09728 branch1 = strsep(&stringp,":"); 09729 branch2 = strsep(&stringp,""); 09730 branch = pbx_checkcondition(condition) ? branch1 : branch2; 09731 09732 if (ast_strlen_zero(branch)) { 09733 ast_debug(1, "Not taking any branch\n"); 09734 return 0; 09735 } 09736 09737 return pbx_builtin_goto(chan, branch); 09738 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9652 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.
09653 { 09654 char *name; 09655 char *value; 09656 char *channel; 09657 char tmp[VAR_BUF_SIZE]; 09658 static int deprecation_warning = 0; 09659 09660 if (ast_strlen_zero(data)) { 09661 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 09662 return 0; 09663 } 09664 tmp[0] = 0; 09665 if (!deprecation_warning) { 09666 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 09667 deprecation_warning = 1; 09668 } 09669 09670 value = ast_strdupa(data); 09671 name = strsep(&value,"="); 09672 channel = strsep(&value,","); 09673 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 09674 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 09675 if (chan2) { 09676 char *s = alloca(strlen(value) + 4); 09677 if (s) { 09678 sprintf(s, "${%s}", value); 09679 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 09680 } 09681 chan2 = ast_channel_unref(chan2); 09682 } 09683 pbx_builtin_setvar_helper(chan, name, tmp); 09684 } 09685 09686 return(0); 09687 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 8990 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
08991 { 08992 const char *options = data; 08993 int answer = 1; 08994 08995 /* Some channels can receive DTMF in unanswered state; some cannot */ 08996 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 08997 answer = 0; 08998 } 08999 09000 /* If the channel is hungup, stop waiting */ 09001 if (ast_check_hangup(chan)) { 09002 return -1; 09003 } else if (chan->_state != AST_STATE_UP && answer) { 09004 __ast_answer(chan, 0, 1); 09005 } 09006 09007 return AST_PBX_INCOMPLETE; 09008 }
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 9494 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().
09495 { 09496 struct ast_var_t *newvariable; 09497 struct varshead *headp; 09498 09499 if (name[strlen(name)-1] == ')') { 09500 char *function = ast_strdupa(name); 09501 09502 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 09503 ast_func_write(chan, function, value); 09504 return; 09505 } 09506 09507 if (chan) { 09508 ast_channel_lock(chan); 09509 headp = &chan->varshead; 09510 } else { 09511 ast_rwlock_wrlock(&globalslock); 09512 headp = &globals; 09513 } 09514 09515 if (value) { 09516 if (headp == &globals) 09517 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09518 newvariable = ast_var_assign(name, value); 09519 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09520 } 09521 09522 if (chan) 09523 ast_channel_unlock(chan); 09524 else 09525 ast_rwlock_unlock(&globalslock); 09526 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason | |||
) |
Definition at line 3125 of file pbx.c.
References ast_calloc_with_stringfields, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run().
03126 { 03127 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03128 struct pbx_exception *exception = NULL; 03129 03130 if (!ds) { 03131 ds = ast_datastore_alloc(&exception_store_info, NULL); 03132 if (!ds) 03133 return -1; 03134 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03135 ast_datastore_free(ds); 03136 return -1; 03137 } 03138 ds->data = exception; 03139 ast_channel_datastore_add(chan, ds); 03140 } else 03141 exception = ds->data; 03142 03143 ast_string_field_set(exception, reason, reason); 03144 ast_string_field_set(exception, context, chan->context); 03145 ast_string_field_set(exception, exten, chan->exten); 03146 exception->priority = chan->priority; 03147 set_ext_pri(chan, "e", 0); 03148 return 0; 03149 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9777 of file pbx.c.
References ast_say_character_str(), and ast_channel::language.
09778 { 09779 int res = 0; 09780 09781 if (data) 09782 res = ast_say_character_str(chan, data, "", chan->language); 09783 return res; 09784 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9768 of file pbx.c.
References ast_say_digit_str(), and ast_channel::language.
09769 { 09770 int res = 0; 09771 09772 if (data) 09773 res = ast_say_digit_str(chan, data, "", chan->language); 09774 return res; 09775 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9740 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), ast_channel::language, LOG_WARNING, and strsep().
09741 { 09742 char tmp[256]; 09743 char *number = tmp; 09744 char *options; 09745 09746 if (ast_strlen_zero(data)) { 09747 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 09748 return -1; 09749 } 09750 ast_copy_string(tmp, data, sizeof(tmp)); 09751 strsep(&number, ","); 09752 options = strsep(&number, ","); 09753 if (options) { 09754 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 09755 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 09756 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 09757 return -1; 09758 } 09759 } 09760 09761 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 09762 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 09763 } 09764 09765 return 0; 09766 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9786 of file pbx.c.
References ast_say_phonetic_str(), and ast_channel::language.
09787 { 09788 int res = 0; 09789 09790 if (data) 09791 res = ast_say_phonetic_str(chan, data, "", chan->language); 09792 return res; 09793 }
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 9425 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().
09426 { 09427 struct ast_var_t *variables; 09428 const char *var, *val; 09429 int total = 0; 09430 09431 if (!chan) 09432 return 0; 09433 09434 ast_str_reset(*buf); 09435 09436 ast_channel_lock(chan); 09437 09438 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 09439 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 09440 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 09441 ) { 09442 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 09443 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 09444 break; 09445 } else 09446 total++; 09447 } else 09448 break; 09449 } 09450 09451 ast_channel_unlock(chan); 09452 09453 return total; 09454 }
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 9586 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), strsep(), and value.
Referenced by ast_compile_ael2(), and rpt_exec().
09587 { 09588 char *name, *value, *mydata; 09589 09590 if (ast_compat_app_set) { 09591 return pbx_builtin_setvar_multiple(chan, data); 09592 } 09593 09594 if (ast_strlen_zero(data)) { 09595 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 09596 return 0; 09597 } 09598 09599 mydata = ast_strdupa(data); 09600 name = strsep(&mydata, "="); 09601 value = mydata; 09602 if (!value) { 09603 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 09604 return 0; 09605 } 09606 09607 if (strchr(name, ' ')) { 09608 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 09609 } 09610 09611 pbx_builtin_setvar_helper(chan, name, value); 09612 09613 return 0; 09614 }
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 9528 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_cel_fabricate_channel_from_event(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), 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(), 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(), 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_parkinglot(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sig_pri_new_ast_channel(), sig_ss7_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(), ss7_start_call(), 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().
09529 { 09530 struct ast_var_t *newvariable; 09531 struct varshead *headp; 09532 const char *nametail = name; 09533 09534 if (name[strlen(name) - 1] == ')') { 09535 char *function = ast_strdupa(name); 09536 09537 return ast_func_write(chan, function, value); 09538 } 09539 09540 if (chan) { 09541 ast_channel_lock(chan); 09542 headp = &chan->varshead; 09543 } else { 09544 ast_rwlock_wrlock(&globalslock); 09545 headp = &globals; 09546 } 09547 09548 /* For comparison purposes, we have to strip leading underscores */ 09549 if (*nametail == '_') { 09550 nametail++; 09551 if (*nametail == '_') 09552 nametail++; 09553 } 09554 09555 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 09556 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 09557 /* there is already such a variable, delete it */ 09558 AST_LIST_REMOVE_CURRENT(entries); 09559 ast_var_delete(newvariable); 09560 break; 09561 } 09562 } 09563 AST_LIST_TRAVERSE_SAFE_END; 09564 09565 if (value) { 09566 if (headp == &globals) 09567 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09568 newvariable = ast_var_assign(name, value); 09569 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09570 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 09571 "Channel: %s\r\n" 09572 "Variable: %s\r\n" 09573 "Value: %s\r\n" 09574 "Uniqueid: %s\r\n", 09575 chan ? chan->name : "none", name, value, 09576 chan ? chan->uniqueid : "none"); 09577 } 09578 09579 if (chan) 09580 ast_channel_unlock(chan); 09581 else 09582 ast_rwlock_unlock(&globalslock); 09583 return 0; 09584 }
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 9616 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().
09617 { 09618 char *data; 09619 int x; 09620 AST_DECLARE_APP_ARGS(args, 09621 AST_APP_ARG(pair)[24]; 09622 ); 09623 AST_DECLARE_APP_ARGS(pair, 09624 AST_APP_ARG(name); 09625 AST_APP_ARG(value); 09626 ); 09627 09628 if (ast_strlen_zero(vdata)) { 09629 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 09630 return 0; 09631 } 09632 09633 data = ast_strdupa(vdata); 09634 AST_STANDARD_APP_ARGS(args, data); 09635 09636 for (x = 0; x < args.argc; x++) { 09637 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 09638 if (pair.argc == 2) { 09639 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 09640 if (strchr(pair.name, ' ')) 09641 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); 09642 } else if (!chan) { 09643 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 09644 } else { 09645 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 09646 } 09647 } 09648 09649 return 0; 09650 }
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 9704 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().
09705 { 09706 int res; 09707 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 09708 return 0; 09709 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 09710 return res; 09711 } else { /* Strings are true */ 09712 return 1; 09713 } 09714 }
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 1379 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 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().
01382 { 01383 int res; 01384 struct ast_module_user *u = NULL; 01385 const char *saved_c_appl; 01386 const char *saved_c_data; 01387 01388 if (c->cdr && !ast_check_hangup(c)) 01389 ast_cdr_setapp(c->cdr, app->name, data); 01390 01391 /* save channel values */ 01392 saved_c_appl= c->appl; 01393 saved_c_data= c->data; 01394 01395 c->appl = app->name; 01396 c->data = data; 01397 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01398 01399 if (app->module) 01400 u = __ast_module_user_add(app->module, c); 01401 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01402 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01403 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01404 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01405 app->name, (char *) data); 01406 } 01407 res = app->execute(c, S_OR(data, "")); 01408 if (app->module && u) 01409 __ast_module_user_remove(app->module, u); 01410 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01411 /* restore channel values */ 01412 c->appl = saved_c_appl; 01413 c->data = saved_c_data; 01414 return res; 01415 }
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 4022 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().
04025 { 04026 struct ast_exten *e; 04027 struct ast_app *app; 04028 int res; 04029 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04030 char passdata[EXT_DATA_SIZE]; 04031 04032 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04033 04034 ast_rdlock_contexts(); 04035 if (found) 04036 *found = 0; 04037 04038 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04039 if (e) { 04040 if (found) 04041 *found = 1; 04042 if (matching_action) { 04043 ast_unlock_contexts(); 04044 return -1; /* success, we found it */ 04045 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04046 res = e->priority; 04047 ast_unlock_contexts(); 04048 return res; /* the priority we were looking for */ 04049 } else { /* spawn */ 04050 if (!e->cached_app) 04051 e->cached_app = pbx_findapp(e->app); 04052 app = e->cached_app; 04053 ast_unlock_contexts(); 04054 if (!app) { 04055 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04056 return -1; 04057 } 04058 if (c->context != context) 04059 ast_copy_string(c->context, context, sizeof(c->context)); 04060 if (c->exten != exten) 04061 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04062 c->priority = priority; 04063 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 04064 #ifdef CHANNEL_TRACE 04065 ast_channel_trace_update(c); 04066 #endif 04067 ast_debug(1, "Launching '%s'\n", app->name); 04068 if (VERBOSITY_ATLEAST(3)) { 04069 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04070 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04071 exten, context, priority, 04072 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04073 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04074 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04075 "in new stack"); 04076 } 04077 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04078 "Channel: %s\r\n" 04079 "Context: %s\r\n" 04080 "Extension: %s\r\n" 04081 "Priority: %d\r\n" 04082 "Application: %s\r\n" 04083 "AppData: %s\r\n" 04084 "Uniqueid: %s\r\n", 04085 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 04086 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04087 } 04088 } else if (q.swo) { /* not found here, but in another switch */ 04089 if (found) 04090 *found = 1; 04091 ast_unlock_contexts(); 04092 if (matching_action) { 04093 return -1; 04094 } else { 04095 if (!q.swo->exec) { 04096 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04097 res = -1; 04098 } 04099 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04100 } 04101 } else { /* not found anywhere, see what happened */ 04102 ast_unlock_contexts(); 04103 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04104 switch (q.status) { 04105 case STATUS_NO_CONTEXT: 04106 if (!matching_action && !combined_find_spawn) 04107 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04108 break; 04109 case STATUS_NO_EXTENSION: 04110 if (!matching_action && !combined_find_spawn) 04111 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04112 break; 04113 case STATUS_NO_PRIORITY: 04114 if (!matching_action && !combined_find_spawn) 04115 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04116 break; 04117 case STATUS_NO_LABEL: 04118 if (context && !combined_find_spawn) 04119 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04120 break; 04121 default: 04122 ast_debug(1, "Shouldn't happen!\n"); 04123 } 04124 04125 return (matching_action) ? 0 : -1; 04126 } 04127 }
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 2551 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), 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, contexts_table, 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(), 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, fake_context::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(), ast_parking_ext_valid(), check_goto(), check_pval_item(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().
02555 { 02556 int x, res; 02557 struct ast_context *tmp = NULL; 02558 struct ast_exten *e = NULL, *eroot = NULL; 02559 struct ast_include *i = NULL; 02560 struct ast_sw *sw = NULL; 02561 struct ast_exten pattern = {NULL, }; 02562 struct scoreboard score = {0, }; 02563 struct ast_str *tmpdata = NULL; 02564 02565 pattern.label = label; 02566 pattern.priority = priority; 02567 #ifdef NEED_DEBUG_HERE 02568 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02569 #endif 02570 02571 /* Initialize status if appropriate */ 02572 if (q->stacklen == 0) { 02573 q->status = STATUS_NO_CONTEXT; 02574 q->swo = NULL; 02575 q->data = NULL; 02576 q->foundcontext = NULL; 02577 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02578 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02579 return NULL; 02580 } 02581 02582 /* Check first to see if we've already been checked */ 02583 for (x = 0; x < q->stacklen; x++) { 02584 if (!strcasecmp(q->incstack[x], context)) 02585 return NULL; 02586 } 02587 02588 if (bypass) { /* bypass means we only look there */ 02589 tmp = bypass; 02590 } else { /* look in contexts */ 02591 struct fake_context item; 02592 02593 ast_copy_string(item.name, context, sizeof(item.name)); 02594 02595 tmp = ast_hashtab_lookup(contexts_table, &item); 02596 if (!tmp) { 02597 return NULL; 02598 } 02599 } 02600 02601 if (q->status < STATUS_NO_EXTENSION) 02602 q->status = STATUS_NO_EXTENSION; 02603 02604 /* Do a search for matching extension */ 02605 02606 eroot = NULL; 02607 score.total_specificity = 0; 02608 score.exten = 0; 02609 score.total_length = 0; 02610 if (!tmp->pattern_tree && tmp->root_table) { 02611 create_match_char_tree(tmp); 02612 #ifdef NEED_DEBUG 02613 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02614 log_match_char_tree(tmp->pattern_tree," "); 02615 #endif 02616 } 02617 #ifdef NEED_DEBUG 02618 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02619 log_match_char_tree(tmp->pattern_tree, ":: "); 02620 #endif 02621 02622 do { 02623 if (!ast_strlen_zero(overrideswitch)) { 02624 char *osw = ast_strdupa(overrideswitch), *name; 02625 struct ast_switch *asw; 02626 ast_switch_f *aswf = NULL; 02627 char *datap; 02628 int eval = 0; 02629 02630 name = strsep(&osw, "/"); 02631 asw = pbx_findswitch(name); 02632 02633 if (!asw) { 02634 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02635 break; 02636 } 02637 02638 if (osw && strchr(osw, '$')) { 02639 eval = 1; 02640 } 02641 02642 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02643 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02644 break; 02645 } else if (eval) { 02646 /* Substitute variables now */ 02647 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02648 datap = ast_str_buffer(tmpdata); 02649 } else { 02650 datap = osw; 02651 } 02652 02653 /* equivalent of extension_match_core() at the switch level */ 02654 if (action == E_CANMATCH) 02655 aswf = asw->canmatch; 02656 else if (action == E_MATCHMORE) 02657 aswf = asw->matchmore; 02658 else /* action == E_MATCH */ 02659 aswf = asw->exists; 02660 if (!aswf) { 02661 res = 0; 02662 } else { 02663 if (chan) { 02664 ast_autoservice_start(chan); 02665 } 02666 res = aswf(chan, context, exten, priority, callerid, datap); 02667 if (chan) { 02668 ast_autoservice_stop(chan); 02669 } 02670 } 02671 if (res) { /* Got a match */ 02672 q->swo = asw; 02673 q->data = datap; 02674 q->foundcontext = context; 02675 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02676 return NULL; 02677 } 02678 } 02679 } while (0); 02680 02681 if (extenpatternmatchnew) { 02682 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02683 eroot = score.exten; 02684 02685 if (score.last_char == '!' && action == E_MATCHMORE) { 02686 /* We match an extension ending in '!'. 02687 * The decision in this case is final and is NULL (no match). 02688 */ 02689 #ifdef NEED_DEBUG_HERE 02690 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02691 #endif 02692 return NULL; 02693 } 02694 02695 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02696 q->status = STATUS_SUCCESS; 02697 #ifdef NEED_DEBUG_HERE 02698 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02699 #endif 02700 return score.canmatch_exten; 02701 } 02702 02703 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02704 if (score.node) { 02705 struct ast_exten *z = trie_find_next_match(score.node); 02706 if (z) { 02707 #ifdef NEED_DEBUG_HERE 02708 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02709 #endif 02710 } else { 02711 if (score.canmatch_exten) { 02712 #ifdef NEED_DEBUG_HERE 02713 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02714 #endif 02715 return score.canmatch_exten; 02716 } else { 02717 #ifdef NEED_DEBUG_HERE 02718 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02719 #endif 02720 } 02721 } 02722 return z; 02723 } 02724 #ifdef NEED_DEBUG_HERE 02725 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02726 #endif 02727 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02728 } 02729 02730 if (eroot) { 02731 /* found entry, now look for the right priority */ 02732 if (q->status < STATUS_NO_PRIORITY) 02733 q->status = STATUS_NO_PRIORITY; 02734 e = NULL; 02735 if (action == E_FINDLABEL && label ) { 02736 if (q->status < STATUS_NO_LABEL) 02737 q->status = STATUS_NO_LABEL; 02738 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02739 } else { 02740 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02741 } 02742 if (e) { /* found a valid match */ 02743 q->status = STATUS_SUCCESS; 02744 q->foundcontext = context; 02745 #ifdef NEED_DEBUG_HERE 02746 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02747 #endif 02748 return e; 02749 } 02750 } 02751 } else { /* the old/current default exten pattern match algorithm */ 02752 02753 /* scan the list trying to match extension and CID */ 02754 eroot = NULL; 02755 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02756 int match = extension_match_core(eroot->exten, exten, action); 02757 /* 0 on fail, 1 on match, 2 on earlymatch */ 02758 02759 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02760 continue; /* keep trying */ 02761 if (match == 2 && action == E_MATCHMORE) { 02762 /* We match an extension ending in '!'. 02763 * The decision in this case is final and is NULL (no match). 02764 */ 02765 return NULL; 02766 } 02767 /* found entry, now look for the right priority */ 02768 if (q->status < STATUS_NO_PRIORITY) 02769 q->status = STATUS_NO_PRIORITY; 02770 e = NULL; 02771 if (action == E_FINDLABEL && label ) { 02772 if (q->status < STATUS_NO_LABEL) 02773 q->status = STATUS_NO_LABEL; 02774 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02775 } else { 02776 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02777 } 02778 if (e) { /* found a valid match */ 02779 q->status = STATUS_SUCCESS; 02780 q->foundcontext = context; 02781 return e; 02782 } 02783 } 02784 } 02785 02786 /* Check alternative switches */ 02787 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02788 struct ast_switch *asw = pbx_findswitch(sw->name); 02789 ast_switch_f *aswf = NULL; 02790 char *datap; 02791 02792 if (!asw) { 02793 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02794 continue; 02795 } 02796 02797 /* Substitute variables now */ 02798 if (sw->eval) { 02799 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02800 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02801 continue; 02802 } 02803 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02804 } 02805 02806 /* equivalent of extension_match_core() at the switch level */ 02807 if (action == E_CANMATCH) 02808 aswf = asw->canmatch; 02809 else if (action == E_MATCHMORE) 02810 aswf = asw->matchmore; 02811 else /* action == E_MATCH */ 02812 aswf = asw->exists; 02813 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02814 if (!aswf) 02815 res = 0; 02816 else { 02817 if (chan) 02818 ast_autoservice_start(chan); 02819 res = aswf(chan, context, exten, priority, callerid, datap); 02820 if (chan) 02821 ast_autoservice_stop(chan); 02822 } 02823 if (res) { /* Got a match */ 02824 q->swo = asw; 02825 q->data = datap; 02826 q->foundcontext = context; 02827 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02828 return NULL; 02829 } 02830 } 02831 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02832 /* Now try any includes we have in this context */ 02833 for (i = tmp->includes; i; i = i->next) { 02834 if (include_valid(i)) { 02835 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02836 #ifdef NEED_DEBUG_HERE 02837 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02838 #endif 02839 return e; 02840 } 02841 if (q->swo) 02842 return NULL; 02843 } 02844 } 02845 return NULL; 02846 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 1423 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_app::list, and ast_app::name.
Referenced by 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().
01424 { 01425 struct ast_app *tmp; 01426 01427 AST_RWLIST_RDLOCK(&apps); 01428 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01429 if (!strcasecmp(tmp->name, app)) 01430 break; 01431 } 01432 AST_RWLIST_UNLOCK(&apps); 01433 01434 return tmp; 01435 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 1437 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().
01438 { 01439 struct ast_switch *asw; 01440 01441 AST_RWLIST_RDLOCK(&switches); 01442 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01443 if (!strcasecmp(asw->name, sw)) 01444 break; 01445 } 01446 AST_RWLIST_UNLOCK(&switches); 01447 01448 return asw; 01449 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 10138 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().
10139 { 10140 char *exten, *pri, *context; 10141 char *stringp; 10142 int ipri; 10143 int mode = 0; 10144 10145 if (ast_strlen_zero(goto_string)) { 10146 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 10147 return -1; 10148 } 10149 stringp = ast_strdupa(goto_string); 10150 context = strsep(&stringp, ","); /* guaranteed non-null */ 10151 exten = strsep(&stringp, ","); 10152 pri = strsep(&stringp, ","); 10153 if (!exten) { /* Only a priority in this one */ 10154 pri = context; 10155 exten = NULL; 10156 context = NULL; 10157 } else if (!pri) { /* Only an extension and priority in this one */ 10158 pri = exten; 10159 exten = context; 10160 context = NULL; 10161 } 10162 if (*pri == '+') { 10163 mode = 1; 10164 pri++; 10165 } else if (*pri == '-') { 10166 mode = -1; 10167 pri++; 10168 } 10169 if (sscanf(pri, "%30d", &ipri) != 1) { 10170 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 10171 exten ? exten : chan->exten, pri, 10172 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 10173 if (ipri < 1) { 10174 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 10175 return -1; 10176 } else 10177 mode = 0; 10178 } 10179 /* At this point we have a priority and maybe an extension and a context */ 10180 10181 if (mode) 10182 ipri = chan->priority + (ipri * mode); 10183 10184 if (async) 10185 ast_async_goto(chan, context, exten, ipri); 10186 else 10187 ast_explicit_goto(chan, context, exten, ipri); 10188 10189 return 0; 10190 10191 }
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 2976 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().
02977 { 02978 struct ast_str *str = ast_str_create(16); 02979 const char *cret; 02980 02981 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 02982 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 02983 *ret = cret ? workspace : NULL; 02984 ast_free(str); 02985 }
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 5074 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05075 { 05076 int oldval = autofallthrough; 05077 autofallthrough = newval; 05078 return oldval; 05079 }
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 5081 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05082 { 05083 int oldval = extenpatternmatchnew; 05084 extenpatternmatchnew = newval; 05085 return oldval; 05086 }
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 5088 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05089 { 05090 if (overrideswitch) { 05091 ast_free(overrideswitch); 05092 } 05093 if (!ast_strlen_zero(newval)) { 05094 overrideswitch = ast_strdup(newval); 05095 } else { 05096 overrideswitch = NULL; 05097 } 05098 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 3985 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
03986 { 03987 const char *tmp; 03988 03989 /* Nothing more to do */ 03990 if (!e->data) { 03991 *passdata = '\0'; 03992 return; 03993 } 03994 03995 /* No variables or expressions in e->data, so why scan it? */ 03996 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 03997 ast_copy_string(passdata, e->data, datalen); 03998 return; 03999 } 04000 04001 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 04002 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3973 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), rotate_file(), rpt_do_lstats(), rpt_exec(), substituted(), and write_cdr().
03974 { 03975 size_t used; 03976 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 03977 }
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 3777 of file pbx.c.
References ast_channel_release(), 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().
03778 { 03779 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03780 char *cp4 = NULL; 03781 const char *tmp, *whereweare, *orig_cp2 = cp2; 03782 int length, offset, offset2, isfunction; 03783 char *workspace = NULL; 03784 char *ltmp = NULL, *var = NULL; 03785 char *nextvar, *nextexp, *nextthing; 03786 char *vars, *vare; 03787 int pos, brackets, needsub, len; 03788 03789 *cp2 = 0; /* just in case nothing ends up there */ 03790 whereweare=tmp=cp1; 03791 while (!ast_strlen_zero(whereweare) && count) { 03792 /* Assume we're copying the whole remaining string */ 03793 pos = strlen(whereweare); 03794 nextvar = NULL; 03795 nextexp = NULL; 03796 nextthing = strchr(whereweare, '$'); 03797 if (nextthing) { 03798 switch (nextthing[1]) { 03799 case '{': 03800 nextvar = nextthing; 03801 pos = nextvar - whereweare; 03802 break; 03803 case '[': 03804 nextexp = nextthing; 03805 pos = nextexp - whereweare; 03806 break; 03807 default: 03808 pos = 1; 03809 } 03810 } 03811 03812 if (pos) { 03813 /* Can't copy more than 'count' bytes */ 03814 if (pos > count) 03815 pos = count; 03816 03817 /* Copy that many bytes */ 03818 memcpy(cp2, whereweare, pos); 03819 03820 count -= pos; 03821 cp2 += pos; 03822 whereweare += pos; 03823 *cp2 = 0; 03824 } 03825 03826 if (nextvar) { 03827 /* We have a variable. Find the start and end, and determine 03828 if we are going to have to recursively call ourselves on the 03829 contents */ 03830 vars = vare = nextvar + 2; 03831 brackets = 1; 03832 needsub = 0; 03833 03834 /* Find the end of it */ 03835 while (brackets && *vare) { 03836 if ((vare[0] == '$') && (vare[1] == '{')) { 03837 needsub++; 03838 } else if (vare[0] == '{') { 03839 brackets++; 03840 } else if (vare[0] == '}') { 03841 brackets--; 03842 } else if ((vare[0] == '$') && (vare[1] == '[')) 03843 needsub++; 03844 vare++; 03845 } 03846 if (brackets) 03847 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03848 len = vare - vars - 1; 03849 03850 /* Skip totally over variable string */ 03851 whereweare += (len + 3); 03852 03853 if (!var) 03854 var = alloca(VAR_BUF_SIZE); 03855 03856 /* Store variable name (and truncate) */ 03857 ast_copy_string(var, vars, len + 1); 03858 03859 /* Substitute if necessary */ 03860 if (needsub) { 03861 size_t used; 03862 if (!ltmp) 03863 ltmp = alloca(VAR_BUF_SIZE); 03864 03865 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03866 vars = ltmp; 03867 } else { 03868 vars = var; 03869 } 03870 03871 if (!workspace) 03872 workspace = alloca(VAR_BUF_SIZE); 03873 03874 workspace[0] = '\0'; 03875 03876 parse_variable_name(vars, &offset, &offset2, &isfunction); 03877 if (isfunction) { 03878 /* Evaluate function */ 03879 if (c || !headp) 03880 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03881 else { 03882 struct varshead old; 03883 struct ast_channel *c = ast_dummy_channel_alloc(); 03884 if (c) { 03885 memcpy(&old, &c->varshead, sizeof(old)); 03886 memcpy(&c->varshead, headp, sizeof(c->varshead)); 03887 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03888 /* Don't deallocate the varshead that was passed in */ 03889 memcpy(&c->varshead, &old, sizeof(c->varshead)); 03890 c = ast_channel_release(c); 03891 } else { 03892 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03893 } 03894 } 03895 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03896 } else { 03897 /* Retrieve variable value */ 03898 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03899 } 03900 if (cp4) { 03901 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03902 03903 length = strlen(cp4); 03904 if (length > count) 03905 length = count; 03906 memcpy(cp2, cp4, length); 03907 count -= length; 03908 cp2 += length; 03909 *cp2 = 0; 03910 } 03911 } else if (nextexp) { 03912 /* We have an expression. Find the start and end, and determine 03913 if we are going to have to recursively call ourselves on the 03914 contents */ 03915 vars = vare = nextexp + 2; 03916 brackets = 1; 03917 needsub = 0; 03918 03919 /* Find the end of it */ 03920 while (brackets && *vare) { 03921 if ((vare[0] == '$') && (vare[1] == '[')) { 03922 needsub++; 03923 brackets++; 03924 vare++; 03925 } else if (vare[0] == '[') { 03926 brackets++; 03927 } else if (vare[0] == ']') { 03928 brackets--; 03929 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03930 needsub++; 03931 vare++; 03932 } 03933 vare++; 03934 } 03935 if (brackets) 03936 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03937 len = vare - vars - 1; 03938 03939 /* Skip totally over expression */ 03940 whereweare += (len + 3); 03941 03942 if (!var) 03943 var = alloca(VAR_BUF_SIZE); 03944 03945 /* Store variable name (and truncate) */ 03946 ast_copy_string(var, vars, len + 1); 03947 03948 /* Substitute if necessary */ 03949 if (needsub) { 03950 size_t used; 03951 if (!ltmp) 03952 ltmp = alloca(VAR_BUF_SIZE); 03953 03954 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03955 vars = ltmp; 03956 } else { 03957 vars = var; 03958 } 03959 03960 length = ast_expr(vars, cp2, count, c); 03961 03962 if (length) { 03963 ast_debug(1, "Expression result is '%s'\n", cp2); 03964 count -= length; 03965 cp2 += length; 03966 *cp2 = 0; 03967 } 03968 } 03969 } 03970 *used = cp2 - orig_cp2; 03971 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3979 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by dundi_lookup_local(), and loopback_subst().
03980 { 03981 size_t used; 03982 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 03983 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5002 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05003 { 05004 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05005 answer this channel and get it going. 05006 */ 05007 /* NOTE: 05008 The launcher of this function _MUST_ increment 'countcalls' 05009 before invoking the function; it will be decremented when the 05010 PBX has finished running on the channel 05011 */ 05012 struct ast_channel *c = data; 05013 05014 __ast_pbx_run(c, NULL); 05015 decrease_call_count(); 05016 05017 pthread_exit(NULL); 05018 05019 return NULL; 05020 }
static void print_app_docs | ( | struct ast_app * | aa, | |
int | fd | |||
) | [static] |
Definition at line 5620 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().
05621 { 05622 /* Maximum number of characters added by terminal coloring is 22 */ 05623 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 05624 char seealsotitle[40]; 05625 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 05626 char *seealso = NULL; 05627 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 05628 05629 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 05630 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 05631 05632 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 05633 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 05634 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 05635 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 05636 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 05637 05638 #ifdef AST_XML_DOCS 05639 if (aa->docsrc == AST_XML_DOC) { 05640 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 05641 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 05642 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 05643 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 05644 05645 if (!synopsis || !description || !arguments || !seealso) { 05646 goto return_cleanup; 05647 } 05648 } else 05649 #endif 05650 { 05651 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05652 synopsis = ast_malloc(synopsis_size); 05653 05654 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05655 description = ast_malloc(description_size); 05656 05657 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05658 arguments = ast_malloc(arguments_size); 05659 05660 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05661 seealso = ast_malloc(seealso_size); 05662 05663 if (!synopsis || !description || !arguments || !seealso) { 05664 goto return_cleanup; 05665 } 05666 05667 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 05668 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 05669 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 05670 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 05671 } 05672 05673 /* Handle the syntax the same for both XML and raw docs */ 05674 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05675 if (!(syntax = ast_malloc(syntax_size))) { 05676 goto return_cleanup; 05677 } 05678 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 05679 05680 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 05681 infotitle, syntitle, synopsis, destitle, description, 05682 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 05683 05684 return_cleanup: 05685 ast_free(description); 05686 ast_free(arguments); 05687 ast_free(synopsis); 05688 ast_free(seealso); 05689 ast_free(syntax); 05690 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 6035 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().
06036 { 06037 int prio = ast_get_extension_priority(e); 06038 if (prio == PRIORITY_HINT) { 06039 snprintf(buf, buflen, "hint: %s", 06040 ast_get_extension_app(e)); 06041 } else { 06042 snprintf(buf, buflen, "%d. %s(%s)", 06043 prio, ast_get_extension_app(e), 06044 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06045 } 06046 }
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 4609 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_raise_exception(), and pbx_builtin_waitexten().
04610 { 04611 ast_channel_lock(c); 04612 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04613 c->priority = pri; 04614 ast_channel_unlock(c); 04615 }
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 6200 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().
06201 { 06202 struct ast_context *c = NULL; 06203 int res = 0, old_total_exten = dpc->total_exten; 06204 06205 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 06206 06207 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 06208 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 06209 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 06210 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 06211 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 06212 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 06213 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 06214 ast_rdlock_contexts(); 06215 06216 /* walk all contexts ... */ 06217 while ( (c = ast_walk_contexts(c)) ) { 06218 int context_info_printed = 0; 06219 06220 if (context && strcmp(ast_get_context_name(c), context)) 06221 continue; /* skip this one, name doesn't match */ 06222 06223 dpc->context_existence = 1; 06224 06225 if (!c->pattern_tree) 06226 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 06227 06228 ast_rdlock_context(c); 06229 06230 dpc->total_context++; 06231 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06232 ast_get_context_name(c), ast_get_context_registrar(c)); 06233 context_info_printed = 1; 06234 06235 if (c->pattern_tree) 06236 { 06237 cli_match_char_tree(c->pattern_tree, " ", fd); 06238 } else { 06239 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 06240 } 06241 06242 ast_unlock_context(c); 06243 06244 /* if we print something in context, make an empty line */ 06245 if (context_info_printed) 06246 ast_cli(fd, "\n"); 06247 } 06248 ast_unlock_contexts(); 06249 06250 return (dpc->total_exten == old_total_exten) ? -1 : res; 06251 }
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 6049 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().
06050 { 06051 struct ast_context *c = NULL; 06052 int res = 0, old_total_exten = dpc->total_exten; 06053 06054 ast_rdlock_contexts(); 06055 06056 /* walk all contexts ... */ 06057 while ( (c = ast_walk_contexts(c)) ) { 06058 struct ast_exten *e; 06059 struct ast_include *i; 06060 struct ast_ignorepat *ip; 06061 char buf[256], buf2[256]; 06062 int context_info_printed = 0; 06063 06064 if (context && strcmp(ast_get_context_name(c), context)) 06065 continue; /* skip this one, name doesn't match */ 06066 06067 dpc->context_existence = 1; 06068 06069 ast_rdlock_context(c); 06070 06071 /* are we looking for exten too? if yes, we print context 06072 * only if we find our extension. 06073 * Otherwise print context even if empty ? 06074 * XXX i am not sure how the rinclude is handled. 06075 * I think it ought to go inside. 06076 */ 06077 if (!exten) { 06078 dpc->total_context++; 06079 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06080 ast_get_context_name(c), ast_get_context_registrar(c)); 06081 context_info_printed = 1; 06082 } 06083 06084 /* walk extensions ... */ 06085 e = NULL; 06086 while ( (e = ast_walk_context_extensions(c, e)) ) { 06087 struct ast_exten *p; 06088 06089 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06090 continue; /* skip, extension match failed */ 06091 06092 dpc->extension_existence = 1; 06093 06094 /* may we print context info? */ 06095 if (!context_info_printed) { 06096 dpc->total_context++; 06097 if (rinclude) { /* TODO Print more info about rinclude */ 06098 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06099 ast_get_context_name(c), ast_get_context_registrar(c)); 06100 } else { 06101 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06102 ast_get_context_name(c), ast_get_context_registrar(c)); 06103 } 06104 context_info_printed = 1; 06105 } 06106 dpc->total_prio++; 06107 06108 /* write extension name and first peer */ 06109 if (e->matchcid) 06110 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06111 else 06112 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06113 06114 print_ext(e, buf2, sizeof(buf2)); 06115 06116 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06117 ast_get_extension_registrar(e)); 06118 06119 dpc->total_exten++; 06120 /* walk next extension peers */ 06121 p = e; /* skip the first one, we already got it */ 06122 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06123 const char *el = ast_get_extension_label(p); 06124 dpc->total_prio++; 06125 if (el) 06126 snprintf(buf, sizeof(buf), " [%s]", el); 06127 else 06128 buf[0] = '\0'; 06129 print_ext(p, buf2, sizeof(buf2)); 06130 06131 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 06132 ast_get_extension_registrar(p)); 06133 } 06134 } 06135 06136 /* walk included and write info ... */ 06137 i = NULL; 06138 while ( (i = ast_walk_context_includes(c, i)) ) { 06139 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 06140 if (exten) { 06141 /* Check all includes for the requested extension */ 06142 if (includecount >= AST_PBX_MAX_STACK) { 06143 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 06144 } else { 06145 int dupe = 0; 06146 int x; 06147 for (x = 0; x < includecount; x++) { 06148 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 06149 dupe++; 06150 break; 06151 } 06152 } 06153 if (!dupe) { 06154 includes[includecount] = ast_get_include_name(i); 06155 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 06156 } else { 06157 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 06158 } 06159 } 06160 } else { 06161 ast_cli(fd, " Include => %-45s [%s]\n", 06162 buf, ast_get_include_registrar(i)); 06163 } 06164 } 06165 06166 /* walk ignore patterns and write info ... */ 06167 ip = NULL; 06168 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06169 const char *ipname = ast_get_ignorepat_name(ip); 06170 char ignorepat[AST_MAX_EXTENSION]; 06171 snprintf(buf, sizeof(buf), "'%s'", ipname); 06172 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06173 if (!exten || ast_extension_match(ignorepat, exten)) { 06174 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 06175 buf, ast_get_ignorepat_registrar(ip)); 06176 } 06177 } 06178 if (!rinclude) { 06179 struct ast_sw *sw = NULL; 06180 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06181 snprintf(buf, sizeof(buf), "'%s/%s'", 06182 ast_get_switch_name(sw), 06183 ast_get_switch_data(sw)); 06184 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 06185 buf, ast_get_switch_registrar(sw)); 06186 } 06187 } 06188 06189 ast_unlock_context(c); 06190 06191 /* if we print something in context, make an empty line */ 06192 if (context_info_printed) 06193 ast_cli(fd, "\n"); 06194 } 06195 ast_unlock_contexts(); 06196 06197 return (dpc->total_exten == old_total_exten) ? -1 : res; 06198 }
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 2886 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
02887 { 02888 char *ret = workspace; 02889 int lr; /* length of the input string after the copy */ 02890 02891 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 02892 02893 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 02894 02895 /* Quick check if no need to do anything */ 02896 if (offset == 0 && length >= lr) /* take the whole string */ 02897 return ret; 02898 02899 if (offset < 0) { /* translate negative offset into positive ones */ 02900 offset = lr + offset; 02901 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02902 offset = 0; 02903 } 02904 02905 /* too large offset result in empty string so we know what to return */ 02906 if (offset >= lr) 02907 return ret + lr; /* the final '\0' */ 02908 02909 ret += offset; /* move to the start position */ 02910 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 02911 ret[length] = '\0'; 02912 else if (length < 0) { 02913 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 02914 ret[lr + length - offset] = '\0'; 02915 else 02916 ret[0] = '\0'; 02917 } 02918 02919 return ret; 02920 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static] |
Definition at line 1633 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().
01634 { 01635 struct match_char *m3; 01636 struct match_char *m4; 01637 struct ast_exten *e3; 01638 01639 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01640 return node->exten; 01641 } 01642 01643 if (node && node->x[0] == '!' && !node->x[1]) { 01644 return node->exten; 01645 } 01646 01647 if (!node || !node->next_char) { 01648 return NULL; 01649 } 01650 01651 m3 = node->next_char; 01652 01653 if (m3->exten) { 01654 return m3->exten; 01655 } 01656 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01657 if (m4->exten) { 01658 return m4->exten; 01659 } 01660 } 01661 for (m4 = m3; m4; m4 = m4->alt_char) { 01662 e3 = trie_find_next_match(m3); 01663 if (e3) { 01664 return e3; 01665 } 01666 } 01667 01668 return NULL; 01669 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 6808 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().
06809 { 06810 struct ast_context *context = NULL; 06811 struct ast_exten *eroot = NULL, *e = NULL; 06812 06813 ast_rdlock_contexts(); 06814 while ((context = ast_walk_contexts(context))) { 06815 while ((eroot = ast_walk_context_extensions(context, eroot))) { 06816 while ((e = ast_walk_extension_priorities(eroot, e))) { 06817 if (e->cached_app == app) 06818 e->cached_app = NULL; 06819 } 06820 } 06821 } 06822 ast_unlock_contexts(); 06823 06824 return; 06825 }
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 1538 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().
01539 { 01540 /* if this extension is marked as deleted, then skip this -- if it never shows 01541 on the scoreboard, it will never be found, nor will halt the traversal. */ 01542 if (deleted) 01543 return; 01544 board->total_specificity = spec; 01545 board->total_length = length; 01546 board->exten = exten; 01547 board->last_char = last; 01548 board->node = node; 01549 #ifdef NEED_DEBUG_HERE 01550 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01551 #endif 01552 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
const void * | data | |||
) | [static] |
Definition at line 8876 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().
08877 { 08878 int res; 08879 struct ast_frame *f; 08880 double waitsec; 08881 int waittime; 08882 08883 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 08884 waitsec = -1; 08885 if (waitsec > -1) { 08886 waittime = waitsec * 1000.0; 08887 ast_safe_sleep(chan, waittime); 08888 } else do { 08889 res = ast_waitfor(chan, -1); 08890 if (res < 0) 08891 return; 08892 f = ast_read(chan); 08893 if (f) 08894 ast_frfree(f); 08895 } while(f); 08896 }
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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static] |
Lock for the ast_context list This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643.
Definition at line 1178 of file pbx.c.
Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().
struct ast_context* contexts [static] |
Definition at line 1171 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 1172 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_merge_contexts_and_delete(), find_context(), find_context_locked(), and pbx_find_extension().
int countcalls [static] |
Definition at line 1129 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 3171 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 3120 of file pbx.c.
Referenced by acf_exception_read(), and pbx_builtin_raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1122 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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RWLOCK_INITIALIZER } [static] |
Definition at line 1118 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().
const int HASH_EXTENHINT_SIZE = 563 [static] |
struct ao2_container* hints [static] |
Definition at line 1191 of file pbx.c.
Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add(), 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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static] |
Definition at line 1128 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 1123 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 9861 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] |
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 9104 of file pbx.c.
Referenced by load_pbx().
int totalcalls [static] |
Definition at line 1130 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] |