Thu Apr 3 08:22:15 2014

Asterisk developer's documentation


pbx.c File Reference

Core PBX routines. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <sys/sysinfo.h>
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/cel.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
#include "asterisk/astobj2.h"
Include dependency graph for pbx.c:

Go to the source code of this file.

Data Structures

struct  acf_root
struct  app_tmp
struct  apps
struct  ast_app
 ast_app: A registered application More...
struct  ast_context
 ast_context: An extension context More...
struct  ast_custom_escalating_function
 Extra information for an ast_custom_function holding privilege escalation information. Kept in a separate structure for ABI compatibility. More...
struct  ast_exten
 ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More...
struct  ast_hint
 Structure for dial plan hints. More...
struct  ast_ignorepat
 ast_ignorepat: Ignore patterns in dial plan More...
struct  ast_include
 ast_include: include= support in extensions.conf More...
struct  ast_state_cb
 ast_state_cb: An extension state notify register item More...
struct  ast_sw
 ast_sw: Switch statement in extensions.conf More...
struct  async_stat
struct  cfextension_states
struct  dialplan_counters
 Counters for the show dialplan manager command. More...
struct  escalation_root
struct  fake_context
struct  match_char
 match_char: forms a syntax tree for quick matching of extension patterns More...
struct  pattern_node
struct  pbx_builtin
 Declaration of builtin applications. More...
struct  pbx_exception
struct  scoreboard
struct  statechange
struct  store_hint
struct  store_hints
struct  switches

Defines

#define 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 BITS_PER   8
#define EXT_DATA_SIZE   8192
#define HASH_EXTENHINT_SIZE   563
#define INC_DST_OVERFLOW_CHECK
#define NEW_MATCHER_CHK_MATCH
#define NEW_MATCHER_RECURSE
#define SAY_STUBS
#define STATUS_NO_CONTEXT   1
#define STATUS_NO_EXTENSION   2
#define STATUS_NO_LABEL   4
#define STATUS_NO_PRIORITY   3
#define STATUS_SUCCESS   5
#define SWITCH_DATA_LENGTH   256
#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3
#define VAR_NORMAL   1
#define VAR_SOFTTRAN   2
#define WAITEXTEN_DIALTONE   (1 << 1)
#define WAITEXTEN_MOH   (1 << 0)

Functions

void __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
int __ast_custom_function_register_escalating (struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod)
 Register a custom function which requires escalated privileges.
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
static void __ast_internal_context_destroy (struct ast_context *con)
static enum ast_pbx_result __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args)
static void __init_extensionstate_buf (void)
static void __init_switch_data (void)
static void __init_thread_inhibit_escalations_tl (void)
 A thread local indicating whether the current thread can run 'dangerous' dialplan functions.
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static int acf_retrieve_docs (struct ast_custom_function *acf)
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
static struct match_charadd_pattern_node (struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
static int add_priority (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain.
static struct match_charalready_in_tree (struct match_char *current, char *pat, int is_pattern)
int ast_active_calls (void)
 Retrieve the number of active calls.
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Main interface to add extensions to the list for out context.
static int ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int lock_context)
 Same as ast_add_extension2() but controls the context locking.
static int ast_add_extension_nolock (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
static int ast_add_hint (struct ast_exten *e)
 Add hint to hint list, check initial extension state.
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_build_timing (struct ast_timing *i, const char *info_in)
 Construct a timing bitmap, for use in time-based conditionals.
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 Change hint for an extension.
int ast_check_timing (const struct ast_timing *i)
 Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
int ast_check_timing2 (const struct ast_timing *i, const struct timeval tv)
 Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
char * ast_complete_applications (const char *line, const char *word, int state)
 Command completion for the list of installed applications.
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
struct ast_contextast_context_find (const char *name)
 Find a context.
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_lockmacro (const char *context)
 locks the macrolock in the given given context
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ...
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
int ast_context_unlockmacro (const char *context)
 Unlocks the macrolock in the given context.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
struct ast_custom_functionast_custom_function_find (const char *name)
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function.
int ast_destroy_timing (struct ast_timing *i)
 Deallocates memory structures associated with a timing bitmap.
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_extension_close (const char *pattern, const char *data, int needmore)
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
int ast_extension_match (const char *pattern, const char *data)
 Determine if a given extension matches a given pattern (in NXX format).
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Check extension state for an extension by using hint.
static int ast_extension_state2 (struct ast_exten *e)
 Check state of extension by using hints.
const char * ast_extension_state2str (int extension_state)
 Return extension_state as string.
static int ast_extension_state3 (struct ast_str *hint_app)
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
 Add watcher for extension states.
int ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Add watcher for extension states with destructor.
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 ast_extension_state_del: Remove a watcher from the callback list
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function
int ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
 executes a read operation on a function
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function
const char * ast_get_context_name (struct ast_context *con)
const char * ast_get_context_registrar (struct ast_context *c)
const char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
const char * ast_get_extension_cidmatch (struct ast_exten *e)
struct ast_contextast_get_extension_context (struct ast_exten *exten)
const char * ast_get_extension_label (struct ast_exten *exten)
int ast_get_extension_matchcid (struct ast_exten *e)
const char * ast_get_extension_name (struct ast_exten *exten)
int ast_get_extension_priority (struct ast_exten *exten)
const char * ast_get_extension_registrar (struct ast_exten *e)
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel.
const char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
const char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
const char * ast_get_include_name (struct ast_include *inc)
const char * ast_get_include_registrar (struct ast_include *i)
const char * ast_get_switch_data (struct ast_sw *sw)
int ast_get_switch_eval (struct ast_sw *sw)
const char * ast_get_switch_name (struct ast_sw *sw)
const char * ast_get_switch_registrar (struct ast_sw *sw)
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
unsigned int ast_hashtab_hash_contexts (const void *obj)
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
static struct ast_extenast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten)
 Find hint for given extension in context.
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
int ast_pbx_init (void)
int ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
static int ast_pbx_outgoing_cdr_failed (void)
 Function to post an empty cdr after a spool call fails.
int ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
static void * ast_pbx_run_app (void *data)
 run the application and free the descriptor once done
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
int ast_rdlock_contexts (void)
 Read locks the context list.
int ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
 Dynamically register a new dial plan application.
int ast_register_switch (struct ast_switch *sw)
 Register an alternative dialplan switch.
static int ast_remove_hint (struct ast_exten *e)
 Remove hint from extension.
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack).
int ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel.
const char * ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
void ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
void ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
void ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
static const char * ast_str_substring (struct ast_str *value, int offset, int length)
int ast_thread_inhibit_escalations (void)
 Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.
int ast_unlock_context (struct ast_context *con)
int ast_unlock_contexts (void)
 Unlocks contexts.
int ast_unregister_application (const char *app)
 Unregister an application.
void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
int ast_wrlock_contexts (void)
 Write locks the context list.
static void * async_wait (void *data)
static void cli_match_char_tree (struct match_char *node, char *prefix, int fd)
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer.
static int compare_char (const void *a, const void *b)
static char * complete_core_show_hint (const char *line, const char *word, int pos, int state)
 autocomplete for CLI command 'core show hint'
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
static void context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
static void context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar)
static void create_match_char_tree (struct ast_context *con)
static void decrease_call_count (void)
static void destroy_exten (struct ast_exten *e)
static void destroy_hint (void *obj)
static void destroy_pattern_tree (struct match_char *pattern_tree)
static void destroy_state_cb (void *doomed)
static void device_state_cb (const struct ast_event *event, void *unused)
static void exception_store_free (void *data)
static int ext_cmp (const char *left, const char *right)
static int ext_cmp_exten (const char *left, const char *right)
static int ext_cmp_exten_partial (const char *left, const char *right)
static int ext_cmp_exten_strlen (const char *str)
static int ext_cmp_pattern (const char *left, const char *right)
static int ext_cmp_pattern_pos (const char **p, unsigned char *bitwise)
 helper functions to sort extension patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct ast_contextfind_context (const char *context)
 lookup for a context with a given name,
static struct ast_contextfind_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_extenget_canmatch_exten (struct match_char *node)
static const char * get_pattern_node (struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
static unsigned get_range (char *src, int max, const char *const names[], const char *msg)
 helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
static void get_timerange (struct ast_timing *i, char *times)
 store a bitmask of valid times, one bit each 1 minute
static char * handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Send ack once.
static char * handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing chanvar's variables in a parseable way.
static char * handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing global variables in a parseable way.
static char * handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hint: CLI support for listing registered dial plan hint
static char * handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hints: CLI support for listing registered dial plan hints
static char * handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_switches: CLI support for listing registered dial plan switches
static int handle_statechange (void *datap)
static char * handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int hashtab_compare_exten_labels (const void *ah_a, const void *ah_b)
static int hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b)
static int hashtab_compare_extens (const void *ha_a, const void *ah_b)
static unsigned int hashtab_hash_extens (const void *obj)
static unsigned int hashtab_hash_labels (const void *obj)
static unsigned int hashtab_hash_priority (const void *obj)
static int hint_cmp (void *obj, void *arg, int flags)
static int hint_hash (const void *obj, const int flags)
static int hint_id_cmp (void *obj, void *arg, int flags)
static int hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
 Increase call count for channel.
static void insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node)
static int is_read_allowed (struct ast_custom_function *acfptr)
 Determines whether execution of a custom function's read function is allowed.
static int is_write_allowed (struct ast_custom_function *acfptr)
 Determines whether execution of a custom function's write function is allowed.
int load_pbx (void)
static int lookup_name (const char *s, const char *const names[], int max)
 Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
static void manager_dpsendack (struct mansession *s, const struct message *m)
 Send ack once.
static int manager_show_dialplan (struct mansession *s, const struct message *m)
 Manager listing of dial plan.
static int manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
 Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not.
static int matchcid (const char *cidpattern, const char *callerid)
static void new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name.
static int pbx_builtin_answer (struct ast_channel *, const char *)
static int pbx_builtin_background (struct ast_channel *, const char *)
static int pbx_builtin_busy (struct ast_channel *, const char *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, const char *)
static int pbx_builtin_execiftime (struct ast_channel *, const char *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
static int pbx_builtin_goto (struct ast_channel *, const char *)
static int pbx_builtin_gotoif (struct ast_channel *, const char *)
static int pbx_builtin_gotoiftime (struct ast_channel *, const char *)
static int pbx_builtin_hangup (struct ast_channel *, const char *)
static int pbx_builtin_importvar (struct ast_channel *, const char *)
static int pbx_builtin_incomplete (struct ast_channel *, const char *)
static int pbx_builtin_noop (struct ast_channel *, const char *)
static int pbx_builtin_proceeding (struct ast_channel *, const char *)
static int pbx_builtin_progress (struct ast_channel *, const char *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value.
int pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason)
static int pbx_builtin_resetcdr (struct ast_channel *, const char *)
static int pbx_builtin_ringing (struct ast_channel *, const char *)
static int pbx_builtin_saycharacters (struct ast_channel *, const char *)
static int pbx_builtin_saydigits (struct ast_channel *, const char *)
static int pbx_builtin_saynumber (struct ast_channel *, const char *)
static int pbx_builtin_sayphonetic (struct ast_channel *, const char *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
 Create a human-readable string, specifying all variables and their corresponding values.
static int pbx_builtin_setamaflags (struct ast_channel *, const char *)
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
int pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
static int pbx_builtin_wait (struct ast_channel *, const char *)
static int pbx_builtin_waitexten (struct ast_channel *, const char *)
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
 The return value depends on the action:.
struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
struct ast_apppbx_findapp (const char *app)
 Find application handle in linked list.
static struct ast_switchpbx_findswitch (const char *sw)
void pbx_live_dangerously (int new_live_dangerously)
 Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).
static int pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async)
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Support for Asterisk built-in variables in the dialplan.
int pbx_set_autofallthrough (int newval)
int pbx_set_extenpatternmatchnew (int newval)
void pbx_set_overrideswitch (const char *newval)
static void pbx_shutdown (void)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_app_docs (struct ast_app *aa, int fd)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static int raise_exception (struct ast_channel *chan, const char *reason, int priority)
static int read_escalates (const struct ast_custom_function *acf)
 Returns true if given custom function escalates privileges on read.
static void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
static int show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int statecbs_cmp (void *obj, void *arg, int flags)
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static int testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
static int thread_inhibits_escalations (void)
 Indicates whether the current thread inhibits the execution of dangerous functions.
static struct ast_extentrie_find_next_match (struct match_char *node)
static void unload_pbx (void)
static void unreference_cached_app (struct ast_app *app)
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
static void wait_for_hangup (struct ast_channel *chan, const void *data)
static int write_escalates (const struct ast_custom_function *acf)
 Returns true if given custom function escalates privileges on write.

Variables

static int autofallthrough = 1
static struct ast_app_option background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },}
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 Lock for the ast_context list.
static ast_mutex_t context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
static struct ast_contextcontexts
static struct ast_hashtabcontexts_table = NULL
static int countcalls
static const char *const days []
static struct ast_event_subdevice_state_sub
 Subscription for device state change events.
static struct ast_taskprocessordevice_state_tps
static struct ast_custom_function exception_function
static struct ast_datastore_info exception_store_info
static int extenpatternmatchnew = 0
static struct cfextension_states extension_states []
static struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , }
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 }
static struct ao2_containerhints
static struct ast_data_handler hints_data_provider
static int live_dangerously
 Set to true (non-zero) to globally allow all dangerous dialplan functions to run.
static ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static const char *const months []
static char * overrideswitch = NULL
static struct ast_cli_entry pbx_cli []
static struct ast_data_entry pbx_data_providers []
static struct ast_app_option resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },}
static struct ao2_containerstatecbs
static int stateid = 1
static struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , }
static struct ast_custom_function testtime_function
static struct ast_threadstorage thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , }
static int totalcalls
static struct ast_app_option waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },}

Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

Go no deeper than this through includes (not counting loops)

Definition at line 1491 of file pbx.c.

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 799 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 798 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 800 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 797 of file pbx.c.

Referenced by pbx_builtin_background().

#define BITS_PER   8

Referenced by ext_cmp_pattern_pos().

#define EXT_DATA_SIZE   8192
Note:
I M P O R T A N T :

The speed of extension handling will likely be among the most important aspects of this PBX. The switching scheme as it exists right now isn't terribly bad (it's O(N+M), where N is the # of extensions and M is the avg # of priorities, but a constant search time here would be great ;-)

A new algorithm to do searching based on a 'compiled' pattern tree is introduced here, and shows a fairly flat (constant) search time, even for over 10000 patterns.

Also, using a hash table for context/priority name lookup can help prevent the find_extension routines from absorbing exponential cpu cycles as the number of contexts/priorities grow. I've previously tested find_extension with red-black trees, which have O(log2(n)) speed. Right now, I'm using hash tables, which do searches (ideally) in O(1) time. While these techniques do not yield much speed in small dialplans, they are worth the trouble in large dialplans.

Definition at line 786 of file pbx.c.

Referenced by pbx_extension_helper(), and realtime_exec().

#define HASH_EXTENHINT_SIZE   563

Definition at line 986 of file pbx.c.

Referenced by ast_pbx_init().

#define INC_DST_OVERFLOW_CHECK

Referenced by get_pattern_node().

#define NEW_MATCHER_CHK_MATCH

Referenced by new_find_extension().

#define NEW_MATCHER_RECURSE

Referenced by new_find_extension().

#define SAY_STUBS

Definition at line 60 of file pbx.c.

#define STATUS_NO_CONTEXT   1

Definition at line 2953 of file pbx.c.

#define STATUS_NO_EXTENSION   2

Definition at line 2954 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2956 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2955 of file pbx.c.

#define STATUS_SUCCESS   5

Definition at line 2957 of file pbx.c.

#define SWITCH_DATA_LENGTH   256

Definition at line 789 of file pbx.c.

#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3

Definition at line 795 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 793 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 794 of file pbx.c.

#define WAITEXTEN_DIALTONE   (1 << 1)

Definition at line 810 of file pbx.c.

Referenced by pbx_builtin_waitexten().

#define WAITEXTEN_MOH   (1 << 0)

Definition at line 809 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Function Documentation

void __ast_context_destroy ( struct ast_context list,
struct ast_hashtab contexttab,
struct ast_context con,
const char *  registrar 
)

Definition at line 9641 of file pbx.c.

References __ast_internal_context_destroy(), ast_context::alts, ast_context_remove_extension_callerid2(), ast_copy_string(), ast_debug, ast_free, ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_remove_this_object(), ast_hashtab_start_traversal(), AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_MAX_EXTENSION, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ast_context::ignorepats, ast_context::includes, ast_exten::matchcid, ast_context::name, ast_include::next, ast_ignorepat::next, ast_context::next, ast_sw::next, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, ast_context::root, and ast_context::root_table.

Referenced by ast_context_destroy().

09642 {
09643    struct ast_context *tmp, *tmpl=NULL;
09644    struct ast_exten *exten_item, *prio_item;
09645 
09646    for (tmp = list; tmp; ) {
09647       struct ast_context *next = NULL; /* next starting point */
09648          /* The following code used to skip forward to the next
09649             context with matching registrar, but this didn't
09650             make sense; individual priorities registrar'd to
09651             the matching registrar could occur in any context! */
09652       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
09653       if (con) {
09654          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
09655             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
09656             if ( !strcasecmp(tmp->name, con->name) ) {
09657                break;   /* found it */
09658             }
09659          }
09660       }
09661 
09662       if (!tmp)   /* not found, we are done */
09663          break;
09664       ast_wrlock_context(tmp);
09665 
09666       if (registrar) {
09667          /* then search thru and remove any extens that match registrar. */
09668          struct ast_hashtab_iter *exten_iter;
09669          struct ast_hashtab_iter *prio_iter;
09670          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
09671          struct ast_include *i, *pi = NULL, *ni = NULL;
09672          struct ast_sw *sw = NULL;
09673 
09674          /* remove any ignorepats whose registrar matches */
09675          for (ip = tmp->ignorepats; ip; ip = ipn) {
09676             ipn = ip->next;
09677             if (!strcmp(ip->registrar, registrar)) {
09678                if (ipl) {
09679                   ipl->next = ip->next;
09680                   ast_free(ip);
09681                   continue; /* don't change ipl */
09682                } else {
09683                   tmp->ignorepats = ip->next;
09684                   ast_free(ip);
09685                   continue; /* don't change ipl */
09686                }
09687             }
09688             ipl = ip;
09689          }
09690          /* remove any includes whose registrar matches */
09691          for (i = tmp->includes; i; i = ni) {
09692             ni = i->next;
09693             if (strcmp(i->registrar, registrar) == 0) {
09694                /* remove from list */
09695                if (pi) {
09696                   pi->next = i->next;
09697                   /* free include */
09698                   ast_free(i);
09699                   continue; /* don't change pi */
09700                } else {
09701                   tmp->includes = i->next;
09702                   /* free include */
09703                   ast_free(i);
09704                   continue; /* don't change pi */
09705                }
09706             }
09707             pi = i;
09708          }
09709          /* remove any switches whose registrar matches */
09710          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
09711             if (strcmp(sw->registrar,registrar) == 0) {
09712                AST_LIST_REMOVE_CURRENT(list);
09713                ast_free(sw);
09714             }
09715          }
09716          AST_LIST_TRAVERSE_SAFE_END;
09717 
09718          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
09719             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
09720             while ((exten_item=ast_hashtab_next(exten_iter))) {
09721                int end_traversal = 1;
09722                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
09723                while ((prio_item=ast_hashtab_next(prio_iter))) {
09724                   char extension[AST_MAX_EXTENSION];
09725                   char cidmatch[AST_MAX_EXTENSION];
09726                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
09727                      continue;
09728                   }
09729                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
09730                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
09731                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
09732                   if (prio_item->cidmatch) {
09733                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
09734                   }
09735                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
09736                }
09737                /* Explanation:
09738                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
09739                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
09740                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
09741                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
09742                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
09743                 * free the iterator
09744                 */
09745                if (end_traversal) {
09746                   ast_hashtab_end_traversal(prio_iter);
09747                } else {
09748                   ast_free(prio_iter);
09749                }
09750             }
09751             ast_hashtab_end_traversal(exten_iter);
09752          }
09753 
09754          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
09755          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
09756             another registrar. It's not empty if there are any extensions */
09757          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
09758             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09759             ast_hashtab_remove_this_object(contexttab, tmp);
09760 
09761             next = tmp->next;
09762             if (tmpl)
09763                tmpl->next = next;
09764             else
09765                contexts = next;
09766             /* Okay, now we're safe to let it go -- in a sense, we were
09767                ready to let it go as soon as we locked it. */
09768             ast_unlock_context(tmp);
09769             __ast_internal_context_destroy(tmp);
09770          } else {
09771             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
09772                     tmp->refcount, tmp->root);
09773             ast_unlock_context(tmp);
09774             next = tmp->next;
09775             tmpl = tmp;
09776          }
09777       } else if (con) {
09778          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
09779          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09780          ast_hashtab_remove_this_object(contexttab, tmp);
09781 
09782          next = tmp->next;
09783          if (tmpl)
09784             tmpl->next = next;
09785          else
09786             contexts = next;
09787          /* Okay, now we're safe to let it go -- in a sense, we were
09788             ready to let it go as soon as we locked it. */
09789          ast_unlock_context(tmp);
09790          __ast_internal_context_destroy(tmp);
09791       }
09792 
09793       /* if we have a specific match, we are done, otherwise continue */
09794       tmp = con ? NULL : next;
09795    }
09796 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 3903 of file pbx.c.

References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().

Referenced by __ast_custom_function_register_escalating(), and load_pbx().

03904 {
03905    struct ast_custom_function *cur;
03906    char tmps[80];
03907 
03908    if (!acf) {
03909       return -1;
03910    }
03911 
03912    acf->mod = mod;
03913 #ifdef AST_XML_DOCS
03914    acf->docsrc = AST_STATIC_DOC;
03915 #endif
03916 
03917    if (acf_retrieve_docs(acf)) {
03918       return -1;
03919    }
03920 
03921    AST_RWLIST_WRLOCK(&acf_root);
03922 
03923    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03924       if (!strcmp(acf->name, cur->name)) {
03925          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03926          AST_RWLIST_UNLOCK(&acf_root);
03927          return -1;
03928       }
03929    }
03930 
03931    /* Store in alphabetical order */
03932    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03933       if (strcasecmp(acf->name, cur->name) < 0) {
03934          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03935          break;
03936       }
03937    }
03938    AST_RWLIST_TRAVERSE_SAFE_END;
03939 
03940    if (!cur) {
03941       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03942    }
03943 
03944    AST_RWLIST_UNLOCK(&acf_root);
03945 
03946    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03947 
03948    return 0;
03949 }

int __ast_custom_function_register_escalating ( struct ast_custom_function acf,
enum ast_custom_function_escalation  escalation,
struct ast_module mod 
)

Register a custom function which requires escalated privileges.

Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).

Definition at line 3951 of file pbx.c.

References __ast_custom_function_register(), ast_custom_escalating_function::acf, ast_calloc, AST_CFE_BOTH, AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, ast_custom_function_unregister(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_custom_escalating_function::read_escalates, and ast_custom_escalating_function::write_escalates.

03952 {
03953    struct ast_custom_escalating_function *acf_escalation = NULL;
03954    int res;
03955 
03956    res = __ast_custom_function_register(acf, mod);
03957    if (res != 0) {
03958       return -1;
03959    }
03960 
03961    if (escalation == AST_CFE_NONE) {
03962       /* No escalations; no need to do anything else */
03963       return 0;
03964    }
03965 
03966    acf_escalation = ast_calloc(1, sizeof(*acf_escalation));
03967    if (!acf_escalation) {
03968       ast_custom_function_unregister(acf);
03969       return -1;
03970    }
03971 
03972    acf_escalation->acf = acf;
03973    switch (escalation) {
03974    case AST_CFE_NONE:
03975       break;
03976    case AST_CFE_READ:
03977       acf_escalation->read_escalates = 1;
03978       break;
03979    case AST_CFE_WRITE:
03980       acf_escalation->write_escalates = 1;
03981       break;
03982    case AST_CFE_BOTH:
03983       acf_escalation->read_escalates = 1;
03984       acf_escalation->write_escalates = 1;
03985       break;
03986    }
03987 
03988    AST_RWLIST_WRLOCK(&escalation_root);
03989    AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list);
03990    AST_RWLIST_UNLOCK(&escalation_root);
03991 
03992    return 0;
03993 }

static int __ast_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
int  async 
) [static]

Definition at line 11068 of file pbx.c.

References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, ast_party_id::number, S_COR, ast_party_number::str, and ast_party_number::valid.

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

11069 {
11070    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
11071 
11072    if (!chan)
11073       return -2;
11074 
11075    if (context == NULL)
11076       context = chan->context;
11077    if (exten == NULL)
11078       exten = chan->exten;
11079 
11080    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
11081    if (ast_exists_extension(chan, context, exten, priority,
11082       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
11083       return goto_func(chan, context, exten, priority);
11084    else {
11085       return AST_PBX_GOTO_FAILED;
11086    }
11087 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

Definition at line 9593 of file pbx.c.

References ast_context::alts, ast_free, ast_hashtab_destroy(), AST_LIST_REMOVE_HEAD, ast_mutex_destroy, ast_rwlock_destroy, destroy_exten(), destroy_pattern_tree(), el, ast_context::ignorepats, ast_context::includes, ast_context::lock, ast_context::macrolock, ast_exten::next, ast_ignorepat::next, ast_include::next, ast_context::pattern_tree, ast_exten::peer, ast_context::registrar, ast_context::root, and ast_context::root_table.

Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().

09594 {
09595    struct ast_include *tmpi;
09596    struct ast_sw *sw;
09597    struct ast_exten *e, *el, *en;
09598    struct ast_ignorepat *ipi;
09599    struct ast_context *tmp = con;
09600 
09601    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
09602       struct ast_include *tmpil = tmpi;
09603       tmpi = tmpi->next;
09604       ast_free(tmpil);
09605    }
09606    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
09607       struct ast_ignorepat *ipl = ipi;
09608       ipi = ipi->next;
09609       ast_free(ipl);
09610    }
09611    if (tmp->registrar)
09612       ast_free(tmp->registrar);
09613 
09614    /* destroy the hash tabs */
09615    if (tmp->root_table) {
09616       ast_hashtab_destroy(tmp->root_table, 0);
09617    }
09618    /* and destroy the pattern tree */
09619    if (tmp->pattern_tree)
09620       destroy_pattern_tree(tmp->pattern_tree);
09621 
09622    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
09623       ast_free(sw);
09624    for (e = tmp->root; e;) {
09625       for (en = e->peer; en;) {
09626          el = en;
09627          en = en->peer;
09628          destroy_exten(el);
09629       }
09630       el = e;
09631       e = e->next;
09632       destroy_exten(el);
09633    }
09634    tmp->root = NULL;
09635    ast_rwlock_destroy(&tmp->lock);
09636    ast_mutex_destroy(&tmp->macrolock);
09637    ast_free(tmp);
09638 }

static enum ast_pbx_result __ast_pbx_run ( struct ast_channel c,
struct ast_pbx_args args 
) [static]

Note:
We get here on a failure of some kind: non-existing extension or hangup. We have options, here. We can either catch the failure and continue, or we can drop out entirely.
If there is no match at priority 1, it is not a valid extension anymore. Try to continue at "i" (for invalid) or "e" (for exception) or exit if neither exist.

Definition at line 5426 of file pbx.c.

References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_copy_string(), ast_debug, ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_free, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_opt_end_cdr_before_h_exten, AST_PBX_ERROR, AST_PBX_INCOMPLETE, ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verb, autofallthrough, ast_channel::caller, ast_channel::cdr, collect_digits(), ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_pbx_args::no_hangup_chan, ast_party_id::number, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, raise_exception(), ast_pbx::rtimeoutms, S_COR, set_ext_pri(), status, ast_party_number::str, ast_party_number::valid, and ast_channel::whentohangup.

Referenced by ast_pbx_run_args(), and pbx_thread().

05428 {
05429    int found = 0; /* set if we find at least one match */
05430    int res = 0;
05431    int autoloopflag;
05432    int error = 0;    /* set an error conditions */
05433 
05434    /* A little initial setup here */
05435    if (c->pbx) {
05436       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
05437       /* XXX and now what ? */
05438       ast_free(c->pbx);
05439    }
05440    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
05441       return -1;
05442    /* Set reasonable defaults */
05443    c->pbx->rtimeoutms = 10000;
05444    c->pbx->dtimeoutms = 5000;
05445 
05446    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
05447    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
05448 
05449    /* Start by trying whatever the channel is set to */
05450    if (!ast_exists_extension(c, c->context, c->exten, c->priority,
05451       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05452       /* If not successful fall back to 's' */
05453       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);
05454       /* XXX the original code used the existing priority in the call to
05455        * ast_exists_extension(), and reset it to 1 afterwards.
05456        * I believe the correct thing is to set it to 1 immediately.
05457        */
05458       set_ext_pri(c, "s", 1);
05459       if (!ast_exists_extension(c, c->context, c->exten, c->priority,
05460          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05461          /* JK02: And finally back to default if everything else failed */
05462          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);
05463          ast_copy_string(c->context, "default", sizeof(c->context));
05464       }
05465    }
05466    ast_channel_lock(c);
05467    if (c->cdr) {
05468       /* allow CDR variables that have been collected after channel was created to be visible during call */
05469       ast_cdr_update(c);
05470    }
05471    ast_channel_unlock(c);
05472    for (;;) {
05473       char dst_exten[256]; /* buffer to accumulate digits */
05474       int pos = 0;      /* XXX should check bounds */
05475       int digit = 0;
05476       int invalid = 0;
05477       int timeout = 0;
05478 
05479       /* No digits pressed yet */
05480       dst_exten[pos] = '\0';
05481 
05482       /* loop on priorities in this context/exten */
05483       while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05484          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05485          &found, 1))) {
05486          if (!ast_check_hangup(c)) {
05487             ++c->priority;
05488             continue;
05489          }
05490 
05491          /* Check softhangup flags. */
05492          if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05493             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05494             continue;
05495          }
05496          if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05497             if (ast_exists_extension(c, c->context, "T", 1,
05498                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05499                set_ext_pri(c, "T", 1);
05500                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05501                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05502                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05503                continue;
05504             } else if (ast_exists_extension(c, c->context, "e", 1,
05505                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05506                raise_exception(c, "ABSOLUTETIMEOUT", 1);
05507                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05508                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05509                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05510                continue;
05511             }
05512 
05513             /* Call timed out with no special extension to jump to. */
05514             error = 1;
05515             break;
05516          }
05517          ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
05518             c->exten, c->priority);
05519          error = 1;
05520          break;
05521       } /* end while  - from here on we can use 'break' to go out */
05522       if (found && res) {
05523          /* Something bad happened, or a hangup has been requested. */
05524          if (strchr("0123456789ABCDEF*#", res)) {
05525             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
05526             pos = 0;
05527             dst_exten[pos++] = digit = res;
05528             dst_exten[pos] = '\0';
05529          } else if (res == AST_PBX_INCOMPLETE) {
05530             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
05531             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
05532 
05533             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
05534             if (!ast_matchmore_extension(c, c->context, c->exten, 1,
05535                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05536                invalid = 1;
05537             } else {
05538                ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
05539                digit = 1;
05540                pos = strlen(dst_exten);
05541             }
05542          } else {
05543             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05544             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05545 
05546             if ((res == AST_PBX_ERROR)
05547                && ast_exists_extension(c, c->context, "e", 1,
05548                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05549                /* if we are already on the 'e' exten, don't jump to it again */
05550                if (!strcmp(c->exten, "e")) {
05551                   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);
05552                   error = 1;
05553                } else {
05554                   raise_exception(c, "ERROR", 1);
05555                   continue;
05556                }
05557             }
05558 
05559             if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05560                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05561                continue;
05562             }
05563             if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05564                if (ast_exists_extension(c, c->context, "T", 1,
05565                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05566                   set_ext_pri(c, "T", 1);
05567                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05568                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05569                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05570                   continue;
05571                } else if (ast_exists_extension(c, c->context, "e", 1,
05572                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05573                   raise_exception(c, "ABSOLUTETIMEOUT", 1);
05574                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05575                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05576                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05577                   continue;
05578                }
05579                /* Call timed out with no special extension to jump to. */
05580             }
05581             ast_channel_lock(c);
05582             if (c->cdr) {
05583                ast_cdr_update(c);
05584             }
05585             ast_channel_unlock(c);
05586             error = 1;
05587             break;
05588          }
05589       }
05590       if (error)
05591          break;
05592 
05593       /*!\note
05594        * We get here on a failure of some kind:  non-existing extension or
05595        * hangup.  We have options, here.  We can either catch the failure
05596        * and continue, or we can drop out entirely. */
05597 
05598       if (invalid
05599          || (ast_strlen_zero(dst_exten) &&
05600             !ast_exists_extension(c, c->context, c->exten, 1,
05601             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) {
05602          /*!\note
05603           * If there is no match at priority 1, it is not a valid extension anymore.
05604           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
05605           * neither exist.
05606           */
05607          if (ast_exists_extension(c, c->context, "i", 1,
05608             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05609             ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
05610             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
05611             set_ext_pri(c, "i", 1);
05612          } else if (ast_exists_extension(c, c->context, "e", 1,
05613             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05614             raise_exception(c, "INVALID", 1);
05615          } else {
05616             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
05617                c->name, c->exten, c->context);
05618             error = 1; /* we know what to do with it */
05619             break;
05620          }
05621       } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05622          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
05623          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05624       } else { /* keypress received, get more digits for a full extension */
05625          int waittime = 0;
05626          if (digit)
05627             waittime = c->pbx->dtimeoutms;
05628          else if (!autofallthrough)
05629             waittime = c->pbx->rtimeoutms;
05630          if (!waittime) {
05631             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
05632             if (!status)
05633                status = "UNKNOWN";
05634             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
05635             if (!strcasecmp(status, "CONGESTION"))
05636                res = pbx_builtin_congestion(c, "10");
05637             else if (!strcasecmp(status, "CHANUNAVAIL"))
05638                res = pbx_builtin_congestion(c, "10");
05639             else if (!strcasecmp(status, "BUSY"))
05640                res = pbx_builtin_busy(c, "10");
05641             error = 1; /* XXX disable message */
05642             break;   /* exit from the 'for' loop */
05643          }
05644 
05645          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
05646             break;
05647          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
05648             timeout = 1;
05649          if (!timeout
05650             && ast_exists_extension(c, c->context, dst_exten, 1,
05651                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */
05652             set_ext_pri(c, dst_exten, 1);
05653          } else {
05654             /* No such extension */
05655             if (!timeout && !ast_strlen_zero(dst_exten)) {
05656                /* An invalid extension */
05657                if (ast_exists_extension(c, c->context, "i", 1,
05658                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05659                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
05660                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
05661                   set_ext_pri(c, "i", 1);
05662                } else if (ast_exists_extension(c, c->context, "e", 1,
05663                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05664                   raise_exception(c, "INVALID", 1);
05665                } else {
05666                   ast_log(LOG_WARNING,
05667                      "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
05668                      dst_exten, c->context);
05669                   found = 1; /* XXX disable message */
05670                   break;
05671                }
05672             } else {
05673                /* A simple timeout */
05674                if (ast_exists_extension(c, c->context, "t", 1,
05675                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05676                   ast_verb(3, "Timeout on %s\n", c->name);
05677                   set_ext_pri(c, "t", 1);
05678                } else if (ast_exists_extension(c, c->context, "e", 1,
05679                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05680                   raise_exception(c, "RESPONSETIMEOUT", 1);
05681                } else {
05682                   ast_log(LOG_WARNING,
05683                      "Timeout, but no rule 't' or 'e' in context '%s'\n",
05684                      c->context);
05685                   found = 1; /* XXX disable message */
05686                   break;
05687                }
05688             }
05689          }
05690          ast_channel_lock(c);
05691          if (c->cdr) {
05692             ast_verb(2, "CDR updated on %s\n",c->name);
05693             ast_cdr_update(c);
05694          }
05695          ast_channel_unlock(c);
05696       }
05697    }
05698 
05699    if (!found && !error) {
05700       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
05701    }
05702 
05703    if (!args || !args->no_hangup_chan) {
05704       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
05705    }
05706 
05707    if ((!args || !args->no_hangup_chan)
05708       && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN)
05709       && ast_exists_extension(c, c->context, "h", 1,
05710          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05711       set_ext_pri(c, "h", 1);
05712       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
05713          ast_cdr_end(c->cdr);
05714       }
05715       while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05716          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05717          &found, 1)) == 0) {
05718          c->priority++;
05719       }
05720       if (found && res) {
05721          /* Something bad happened, or a hangup has been requested. */
05722          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05723          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05724       }
05725    }
05726    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
05727    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
05728    pbx_destroy(c->pbx);
05729    c->pbx = NULL;
05730 
05731    if (!args || !args->no_hangup_chan) {
05732       ast_hangup(c);
05733    }
05734 
05735    return 0;
05736 }

static void __init_extensionstate_buf ( void   )  [static]

Definition at line 823 of file pbx.c.

00837 : An extension

static void __init_switch_data ( void   )  [static]

Definition at line 822 of file pbx.c.

00837 : An extension

static void __init_thread_inhibit_escalations_tl ( void   )  [static]

A thread local indicating whether the current thread can run 'dangerous' dialplan functions.

Definition at line 828 of file pbx.c.

00837 : An extension

static int _extension_match_core ( const char *  pattern,
const char *  data,
enum ext_match_t  mode 
) [static]

Definition at line 2697 of file pbx.c.

References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, ext_cmp_exten(), ext_cmp_exten_partial(), ext_cmp_exten_strlen(), ext_cmp_pattern(), LOG_NOTICE, and LOG_WARNING.

Referenced by extension_match_core().

02698 {
02699    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
02700 
02701 #ifdef NEED_DEBUG_HERE
02702    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
02703 #endif
02704 
02705    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
02706       int lp = ext_cmp_exten_strlen(pattern);
02707       int ld = ext_cmp_exten_strlen(data);
02708 
02709       if (lp < ld) {    /* pattern too short, cannot match */
02710 #ifdef NEED_DEBUG_HERE
02711          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
02712 #endif
02713          return 0;
02714       }
02715       /* depending on the mode, accept full or partial match or both */
02716       if (mode == E_MATCH) {
02717 #ifdef NEED_DEBUG_HERE
02718          ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data);
02719 #endif
02720          return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */
02721       }
02722       if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */
02723 #ifdef NEED_DEBUG_HERE
02724          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
02725 #endif
02726          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
02727       } else {
02728 #ifdef NEED_DEBUG_HERE
02729          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
02730 #endif
02731          return 0;
02732       }
02733    }
02734    if (mode == E_MATCH && data[0] == '_') {
02735       /*
02736        * XXX It is bad design that we don't know if we should be
02737        * comparing data and pattern as patterns or comparing data if
02738        * it conforms to pattern when the function is called.  First,
02739        * assume they are both patterns.  If they don't match then try
02740        * to see if data conforms to the given pattern.
02741        *
02742        * note: if this test is left out, then _x. will not match _x. !!!
02743        */
02744 #ifdef NEED_DEBUG_HERE
02745       ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data);
02746 #endif
02747       if (!ext_cmp_pattern(pattern + 1, data + 1)) {
02748 #ifdef NEED_DEBUG_HERE
02749          ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
02750 #endif
02751          return 1;
02752       }
02753    }
02754 
02755    ++pattern; /* skip leading _ */
02756    /*
02757     * XXX below we stop at '/' which is a separator for the CID info. However we should
02758     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
02759     */
02760    for (;;) {
02761       const char *end;
02762 
02763       /* Ignore '-' chars as eye candy fluff. */
02764       while (*data == '-') {
02765          ++data;
02766       }
02767       while (*pattern == '-') {
02768          ++pattern;
02769       }
02770       if (!*data || !*pattern || *pattern == '/') {
02771          break;
02772       }
02773 
02774       switch (*pattern) {
02775       case '[':   /* a range */
02776          ++pattern;
02777          end = strchr(pattern, ']'); /* XXX should deal with escapes ? */
02778          if (!end) {
02779             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02780             return 0;   /* unconditional failure */
02781          }
02782          if (pattern == end) {
02783             /* Ignore empty character sets. */
02784             ++pattern;
02785             continue;
02786          }
02787          for (; pattern < end; ++pattern) {
02788             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
02789                if (*data >= pattern[0] && *data <= pattern[2])
02790                   break;   /* match found */
02791                else {
02792                   pattern += 2; /* skip a total of 3 chars */
02793                   continue;
02794                }
02795             } else if (*data == pattern[0])
02796                break;   /* match found */
02797          }
02798          if (pattern >= end) {
02799 #ifdef NEED_DEBUG_HERE
02800             ast_log(LOG_NOTICE,"return (0) when pattern>=end\n");
02801 #endif
02802             return 0;
02803          }
02804          pattern = end; /* skip and continue */
02805          break;
02806       case 'n':
02807       case 'N':
02808          if (*data < '2' || *data > '9') {
02809 #ifdef NEED_DEBUG_HERE
02810             ast_log(LOG_NOTICE,"return (0) N is not matched\n");
02811 #endif
02812             return 0;
02813          }
02814          break;
02815       case 'x':
02816       case 'X':
02817          if (*data < '0' || *data > '9') {
02818 #ifdef NEED_DEBUG_HERE
02819             ast_log(LOG_NOTICE,"return (0) X is not matched\n");
02820 #endif
02821             return 0;
02822          }
02823          break;
02824       case 'z':
02825       case 'Z':
02826          if (*data < '1' || *data > '9') {
02827 #ifdef NEED_DEBUG_HERE
02828             ast_log(LOG_NOTICE,"return (0) Z is not matched\n");
02829 #endif
02830             return 0;
02831          }
02832          break;
02833       case '.':   /* Must match, even with more digits */
02834 #ifdef NEED_DEBUG_HERE
02835          ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
02836 #endif
02837          return 1;
02838       case '!':   /* Early match */
02839 #ifdef NEED_DEBUG_HERE
02840          ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
02841 #endif
02842          return 2;
02843       default:
02844          if (*data != *pattern) {
02845 #ifdef NEED_DEBUG_HERE
02846             ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
02847 #endif
02848             return 0;
02849          }
02850          break;
02851       }
02852       ++data;
02853       ++pattern;
02854    }
02855    if (*data)        /* data longer than pattern, no match */ {
02856 #ifdef NEED_DEBUG_HERE
02857       ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
02858 #endif
02859       return 0;
02860    }
02861 
02862    /*
02863     * match so far, but ran off the end of data.
02864     * Depending on what is next, determine match or not.
02865     */
02866    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
02867 #ifdef NEED_DEBUG_HERE
02868       ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
02869 #endif
02870       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
02871    } else if (*pattern == '!')   {     /* early match */
02872 #ifdef NEED_DEBUG_HERE
02873       ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
02874 #endif
02875       return 2;
02876    } else {                /* partial match */
02877 #ifdef NEED_DEBUG_HERE
02878       ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
02879 #endif
02880       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
02881    }
02882 }

static int acf_exception_read ( struct ast_channel chan,
const char *  name,
char *  data,
char *  buf,
size_t  buflen 
) [static]

Definition at line 3584 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.

03585 {
03586    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03587    struct pbx_exception *exception = NULL;
03588    if (!ds || !ds->data)
03589       return -1;
03590    exception = ds->data;
03591    if (!strcasecmp(data, "REASON"))
03592       ast_copy_string(buf, exception->reason, buflen);
03593    else if (!strcasecmp(data, "CONTEXT"))
03594       ast_copy_string(buf, exception->context, buflen);
03595    else if (!strncasecmp(data, "EXTEN", 5))
03596       ast_copy_string(buf, exception->exten, buflen);
03597    else if (!strcasecmp(data, "PRIORITY"))
03598       snprintf(buf, buflen, "%d", exception->priority);
03599    else
03600       return -1;
03601    return 0;
03602 }

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

Definition at line 3858 of file pbx.c.

References ast_free, ast_module_name(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, and synopsis.

Referenced by __ast_custom_function_register().

03859 {
03860 #ifdef AST_XML_DOCS
03861    char *tmpxml;
03862 
03863    /* Let's try to find it in the Documentation XML */
03864    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
03865       return 0;
03866    }
03867 
03868    if (ast_string_field_init(acf, 128)) {
03869       return -1;
03870    }
03871 
03872    /* load synopsis */
03873    tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
03874    ast_string_field_set(acf, synopsis, tmpxml);
03875    ast_free(tmpxml);
03876 
03877    /* load description */
03878    tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
03879    ast_string_field_set(acf, desc, tmpxml);
03880    ast_free(tmpxml);
03881 
03882    /* load syntax */
03883    tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
03884    ast_string_field_set(acf, syntax, tmpxml);
03885    ast_free(tmpxml);
03886 
03887    /* load arguments */
03888    tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
03889    ast_string_field_set(acf, arguments, tmpxml);
03890    ast_free(tmpxml);
03891 
03892    /* load seealso */
03893    tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
03894    ast_string_field_set(acf, seealso, tmpxml);
03895    ast_free(tmpxml);
03896 
03897    acf->docsrc = AST_XML_DOC;
03898 #endif
03899 
03900    return 0;
03901 }

static struct match_char * add_exten_to_pattern_tree ( struct ast_context con,
struct ast_exten e1,
int  findonly 
) [static, read]

Definition at line 2180 of file pbx.c.

References add_pattern_node(), already_in_tree(), ARRAY_LEN, ast_copy_string(), ast_log(), pattern_node::buf, ast_exten::cidmatch, match_char::deleted, match_char::exten, ast_exten::exten, get_pattern_node(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_exten::matchcid, match_char::next_char, and ast_context::pattern_tree.

Referenced by add_priority(), ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().

02181 {
02182    struct match_char *m1 = NULL;
02183    struct match_char *m2 = NULL;
02184    struct match_char **m0;
02185    const char *pos;
02186    int already;
02187    int pattern = 0;
02188    int idx_cur;
02189    int idx_next;
02190    char extenbuf[512];
02191    struct pattern_node pat_node[2];
02192 
02193    if (e1->matchcid) {
02194       if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
02195          ast_log(LOG_ERROR,
02196             "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
02197             e1->exten, e1->cidmatch);
02198          return NULL;
02199       }
02200       sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe.  We just checked. */
02201    } else {
02202       ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
02203    }
02204 
02205 #ifdef NEED_DEBUG
02206    ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf);
02207 #endif
02208    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
02209    m0 = &con->pattern_tree;
02210    already = 1;
02211 
02212    pos = extenbuf;
02213    if (*pos == '_') {
02214       pattern = 1;
02215       ++pos;
02216    }
02217    idx_cur = 0;
02218    pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
02219    for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
02220       idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
02221       pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
02222 
02223       /* See about adding node to tree. */
02224       m2 = NULL;
02225       if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
02226          && m2->next_char) {
02227          if (!pat_node[idx_next].buf[0]) {
02228             /*
02229              * This is the end of the pattern, but not the end of the tree.
02230              * Mark this node with the exten... a shorter pattern might win
02231              * if the longer one doesn't match.
02232              */
02233             if (findonly) {
02234                return m2;
02235             }
02236             if (m2->exten) {
02237                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02238                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02239             }
02240             m2->exten = e1;
02241             m2->deleted = 0;
02242          }
02243          m1 = m2->next_char; /* m1 points to the node to compare against */
02244          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
02245       } else { /* not already OR not m2 OR nor m2->next_char */
02246          if (m2) {
02247             if (findonly) {
02248                return m2;
02249             }
02250             m1 = m2; /* while m0 stays the same */
02251          } else {
02252             if (findonly) {
02253                return m1;
02254             }
02255             m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
02256             if (!m1) { /* m1 is the node just added */
02257                return NULL;
02258             }
02259             m0 = &m1->next_char;
02260          }
02261          if (!pat_node[idx_next].buf[0]) {
02262             if (m2 && m2->exten) {
02263                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02264                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02265             }
02266             m1->deleted = 0;
02267             m1->exten = e1;
02268          }
02269 
02270          /* The 'already' variable is a mini-optimization designed to make it so that we
02271           * don't have to call already_in_tree when we know it will return false.
02272           */
02273          already = 0;
02274       }
02275    }
02276    return m1;
02277 }

static struct match_char* add_pattern_node ( struct ast_context con,
struct match_char current,
const struct pattern_node pattern,
int  is_pattern,
int  already,
struct match_char **  nextcharptr 
) [static, read]

Definition at line 1982 of file pbx.c.

References ast_calloc, pattern_node::buf, insert_in_next_chars_alt_char_list(), match_char::is_pattern, match_char::next_char, ast_context::pattern_tree, pattern_node::specif, match_char::specificity, and match_char::x.

Referenced by add_exten_to_pattern_tree().

01983 {
01984    struct match_char *m;
01985 
01986    if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
01987       return NULL;
01988    }
01989 
01990    /* strcpy is safe here since we know its size and have allocated
01991     * just enough space for when we allocated m
01992     */
01993    strcpy(m->x, pattern->buf);
01994 
01995    /* the specificity scores are the same as used in the old
01996       pattern matcher. */
01997    m->is_pattern = is_pattern;
01998    if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
01999       m->specificity = 0x0832;
02000    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
02001       m->specificity = 0x0931;
02002    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
02003       m->specificity = 0x0a30;
02004    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
02005       m->specificity = 0x18000;
02006    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
02007       m->specificity = 0x28000;
02008    } else {
02009       m->specificity = pattern->specif;
02010    }
02011 
02012    if (!con->pattern_tree) {
02013       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
02014    } else {
02015       if (already) { /* switch to the new regime (traversing vs appending)*/
02016          insert_in_next_chars_alt_char_list(nextcharptr, m);
02017       } else {
02018          insert_in_next_chars_alt_char_list(&current->next_char, m);
02019       }
02020    }
02021 
02022    return m;
02023 }

static int add_priority ( struct ast_context con,
struct ast_exten tmp,
struct ast_exten el,
struct ast_exten e,
int  replace 
) [static]

add the extension in the priority chain.

Return values:
0 on success.
-1 on failure.

Definition at line 8779 of file pbx.c.

References add_exten_to_pattern_tree(), ast_add_hint(), ast_change_hint(), ast_free, ast_hashtab_insert_safe(), ast_hashtab_remove_object_via_lookup(), ast_log(), ast_exten::data, ast_exten::datad, match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_WARNING, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_context::root, ast_context::root_table, and match_char::x.

Referenced by ast_add_extension2_lockopt().

08781 {
08782    struct ast_exten *ep;
08783    struct ast_exten *eh=e;
08784    int repeated_label = 0; /* Track if this label is a repeat, assume no. */
08785 
08786    for (ep = NULL; e ; ep = e, e = e->peer) {
08787       if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
08788          if (strcmp(e->exten, tmp->exten)) {
08789             ast_log(LOG_WARNING,
08790                "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
08791                tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority);
08792          } else {
08793             ast_log(LOG_WARNING,
08794                "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
08795                tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
08796          }
08797          repeated_label = 1;
08798       }
08799       if (e->priority >= tmp->priority) {
08800          break;
08801       }
08802    }
08803 
08804    if (repeated_label) {   /* Discard the label since it's a repeat. */
08805       tmp->label = NULL;
08806    }
08807 
08808    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
08809       ast_hashtab_insert_safe(eh->peer_table, tmp);
08810 
08811       if (tmp->label) {
08812          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08813       }
08814       ep->peer = tmp;
08815       return 0;   /* success */
08816    }
08817    if (e->priority == tmp->priority) {
08818       /* Can't have something exactly the same.  Is this a
08819          replacement?  If so, replace, otherwise, bonk. */
08820       if (!replace) {
08821          if (strcmp(e->exten, tmp->exten)) {
08822             ast_log(LOG_WARNING,
08823                "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
08824                tmp->exten, tmp->priority, con->name, e->exten);
08825          } else {
08826             ast_log(LOG_WARNING,
08827                "Unable to register extension '%s' priority %d in '%s', already in use\n",
08828                tmp->exten, tmp->priority, con->name);
08829          }
08830          if (tmp->datad) {
08831             tmp->datad(tmp->data);
08832             /* if you free this, null it out */
08833             tmp->data = NULL;
08834          }
08835 
08836          ast_free(tmp);
08837          return -1;
08838       }
08839       /* we are replacing e, so copy the link fields and then update
08840        * whoever pointed to e to point to us
08841        */
08842       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
08843       tmp->peer = e->peer; /* always meaningful */
08844       if (ep)  {     /* We're in the peer list, just insert ourselves */
08845          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
08846 
08847          if (e->label) {
08848             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
08849          }
08850 
08851          ast_hashtab_insert_safe(eh->peer_table,tmp);
08852          if (tmp->label) {
08853             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
08854          }
08855 
08856          ep->peer = tmp;
08857       } else if (el) {     /* We're the first extension. Take over e's functions */
08858          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08859          tmp->peer_table = e->peer_table;
08860          tmp->peer_label_table = e->peer_label_table;
08861          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
08862          ast_hashtab_insert_safe(tmp->peer_table,tmp);
08863          if (e->label) {
08864             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08865          }
08866          if (tmp->label) {
08867             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08868          }
08869 
08870          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08871          ast_hashtab_insert_safe(con->root_table, tmp);
08872          el->next = tmp;
08873          /* The pattern trie points to this exten; replace the pointer,
08874             and all will be well */
08875          if (x) { /* if the trie isn't formed yet, don't sweat this */
08876             if (x->exten) { /* this test for safety purposes */
08877                x->exten = tmp; /* replace what would become a bad pointer */
08878             } else {
08879                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08880             }
08881          }
08882       } else {       /* We're the very first extension.  */
08883          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08884          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08885          ast_hashtab_insert_safe(con->root_table, tmp);
08886          tmp->peer_table = e->peer_table;
08887          tmp->peer_label_table = e->peer_label_table;
08888          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
08889          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08890          if (e->label) {
08891             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08892          }
08893          if (tmp->label) {
08894             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08895          }
08896 
08897          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08898          ast_hashtab_insert_safe(con->root_table, tmp);
08899          con->root = tmp;
08900          /* The pattern trie points to this exten; replace the pointer,
08901             and all will be well */
08902          if (x) { /* if the trie isn't formed yet; no problem */
08903             if (x->exten) { /* this test for safety purposes */
08904                x->exten = tmp; /* replace what would become a bad pointer */
08905             } else {
08906                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08907             }
08908          }
08909       }
08910       if (tmp->priority == PRIORITY_HINT)
08911          ast_change_hint(e,tmp);
08912       /* Destroy the old one */
08913       if (e->datad)
08914          e->datad(e->data);
08915       ast_free(e);
08916    } else { /* Slip ourselves in just before e */
08917       tmp->peer = e;
08918       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
08919       if (ep) {         /* Easy enough, we're just in the peer list */
08920          if (tmp->label) {
08921             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08922          }
08923          ast_hashtab_insert_safe(eh->peer_table, tmp);
08924          ep->peer = tmp;
08925       } else {       /* we are the first in some peer list, so link in the ext list */
08926          tmp->peer_table = e->peer_table;
08927          tmp->peer_label_table = e->peer_label_table;
08928          e->peer_table = 0;
08929          e->peer_label_table = 0;
08930          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08931          if (tmp->label) {
08932             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08933          }
08934          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08935          ast_hashtab_insert_safe(con->root_table, tmp);
08936          if (el)
08937             el->next = tmp;   /* in the middle... */
08938          else
08939             con->root = tmp; /* ... or at the head */
08940          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
08941       }
08942       /* And immediately return success. */
08943       if (tmp->priority == PRIORITY_HINT) {
08944          ast_add_hint(tmp);
08945       }
08946    }
08947    return 0;
08948 }

static struct match_char * already_in_tree ( struct match_char current,
char *  pat,
int  is_pattern 
) [static, read]

Definition at line 1920 of file pbx.c.

References match_char::alt_char, match_char::is_pattern, and match_char::x.

Referenced by add_exten_to_pattern_tree().

01921 {
01922    struct match_char *t;
01923 
01924    if (!current) {
01925       return 0;
01926    }
01927 
01928    for (t = current; t; t = t->alt_char) {
01929       if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
01930          return t;
01931       }
01932    }
01933 
01934    return 0;
01935 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5884 of file pbx.c.

References countcalls.

Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().

05885 {
05886    return countcalls;
05887 }

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.

Parameters:
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
Return values:
0 success
-1 failure

Definition at line 8614 of file pbx.c.

References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().

Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().

08617 {
08618    int ret = -1;
08619    struct ast_context *c;
08620 
08621    c = find_context_locked(context);
08622    if (c) {
08623       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08624          application, data, datad, registrar);
08625       ast_unlock_contexts();
08626    }
08627 
08628    return ret;
08629 }

int ast_add_extension2 ( struct ast_context con,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar 
)

Main interface to add extensions to the list for out context.

Add an extension to an extension context, this time with an ast_context *.

We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.

The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.

EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set

Definition at line 8975 of file pbx.c.

References ast_add_extension2_lockopt().

Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().

08979 {
08980    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
08981       application, data, datad, registrar, 1);
08982 }

static int ast_add_extension2_lockopt ( struct ast_context con,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar,
int  lock_context 
) [static]

Same as ast_add_extension2() but controls the context locking.

Does all the work of ast_add_extension2, but adds an arg to determine if context locking should be done.

Definition at line 8991 of file pbx.c.

References add_exten_to_pattern_tree(), add_priority(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, AST_EXT_MATCHCID_OFF, AST_EXT_MATCHCID_ON, ast_hashtab_create(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_channel::context, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_channel::exten, hashtab_compare_exten_labels(), hashtab_compare_exten_numbers(), hashtab_compare_extens(), hashtab_hash_extens(), hashtab_hash_labels(), hashtab_hash_priority(), ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::next, option_debug, ast_exten::parent, ast_context::pattern_tree, pbx_substitute_variables_helper(), ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_context::root_table, ast_exten::stuff, and VAR_BUF_SIZE.

Referenced by ast_add_extension2(), and ast_add_extension_nolock().

08995 {
08996    /*
08997     * Sort extensions (or patterns) according to the rules indicated above.
08998     * These are implemented by the function ext_cmp()).
08999     * All priorities for the same ext/pattern/cid are kept in a list,
09000     * using the 'peer' field  as a link field..
09001     */
09002    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
09003    int res;
09004    int length;
09005    char *p;
09006    char expand_buf[VAR_BUF_SIZE];
09007    struct ast_exten dummy_exten = {0};
09008    char dummy_name[1024];
09009 
09010    if (ast_strlen_zero(extension)) {
09011       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",
09012             con->name);
09013       return -1;
09014    }
09015 
09016    /* If we are adding a hint evalulate in variables and global variables */
09017    if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
09018       struct ast_channel *c = ast_dummy_channel_alloc();
09019 
09020       if (c) {
09021          ast_copy_string(c->exten, extension, sizeof(c->exten));
09022          ast_copy_string(c->context, con->name, sizeof(c->context));
09023       }
09024       pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
09025       application = expand_buf;
09026       if (c) {
09027          ast_channel_unref(c);
09028       }
09029    }
09030 
09031    length = sizeof(struct ast_exten);
09032    length += strlen(extension) + 1;
09033    length += strlen(application) + 1;
09034    if (label)
09035       length += strlen(label) + 1;
09036    if (callerid)
09037       length += strlen(callerid) + 1;
09038    else
09039       length ++;  /* just the '\0' */
09040 
09041    /* Be optimistic:  Build the extension structure first */
09042    if (!(tmp = ast_calloc(1, length)))
09043       return -1;
09044 
09045    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
09046       label = 0;
09047 
09048    /* use p as dst in assignments, as the fields are const char * */
09049    p = tmp->stuff;
09050    if (label) {
09051       tmp->label = p;
09052       strcpy(p, label);
09053       p += strlen(label) + 1;
09054    }
09055    tmp->exten = p;
09056    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
09057    tmp->priority = priority;
09058    tmp->cidmatch = p;   /* but use p for assignments below */
09059 
09060    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
09061    if (callerid) {
09062       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
09063       tmp->matchcid = AST_EXT_MATCHCID_ON;
09064    } else {
09065       *p++ = '\0';
09066       tmp->matchcid = AST_EXT_MATCHCID_OFF;
09067    }
09068    tmp->app = p;
09069    strcpy(p, application);
09070    tmp->parent = con;
09071    tmp->data = data;
09072    tmp->datad = datad;
09073    tmp->registrar = registrar;
09074 
09075    if (lock_context) {
09076       ast_wrlock_context(con);
09077    }
09078 
09079    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
09080                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
09081       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
09082       dummy_exten.exten = dummy_name;
09083       dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
09084       dummy_exten.cidmatch = 0;
09085       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
09086       if (!tmp2) {
09087          /* hmmm, not in the trie; */
09088          add_exten_to_pattern_tree(con, tmp, 0);
09089          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
09090       }
09091    }
09092    res = 0; /* some compilers will think it is uninitialized otherwise */
09093    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
09094       res = ext_cmp(e->exten, tmp->exten);
09095       if (res == 0) { /* extension match, now look at cidmatch */
09096          if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF)
09097             res = 0;
09098          else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
09099             res = 1;
09100          else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
09101             res = -1;
09102          else
09103             res = ext_cmp(e->cidmatch, tmp->cidmatch);
09104       }
09105       if (res >= 0)
09106          break;
09107    }
09108    if (e && res == 0) { /* exact match, insert in the priority chain */
09109       res = add_priority(con, tmp, el, e, replace);
09110       if (lock_context) {
09111          ast_unlock_context(con);
09112       }
09113       if (res < 0) {
09114          errno = EEXIST;   /* XXX do we care ? */
09115          return 0; /* XXX should we return -1 maybe ? */
09116       }
09117    } else {
09118       /*
09119        * not an exact match, this is the first entry with this pattern,
09120        * so insert in the main list right before 'e' (if any)
09121        */
09122       tmp->next = e;
09123       if (el) {  /* there is another exten already in this context */
09124          el->next = tmp;
09125          tmp->peer_table = ast_hashtab_create(13,
09126                      hashtab_compare_exten_numbers,
09127                      ast_hashtab_resize_java,
09128                      ast_hashtab_newsize_java,
09129                      hashtab_hash_priority,
09130                      0);
09131          tmp->peer_label_table = ast_hashtab_create(7,
09132                         hashtab_compare_exten_labels,
09133                         ast_hashtab_resize_java,
09134                         ast_hashtab_newsize_java,
09135                         hashtab_hash_labels,
09136                         0);
09137          if (label) {
09138             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
09139          }
09140          ast_hashtab_insert_safe(tmp->peer_table, tmp);
09141       } else {  /* this is the first exten in this context */
09142          if (!con->root_table)
09143             con->root_table = ast_hashtab_create(27,
09144                                        hashtab_compare_extens,
09145                                        ast_hashtab_resize_java,
09146                                        ast_hashtab_newsize_java,
09147                                        hashtab_hash_extens,
09148                                        0);
09149          con->root = tmp;
09150          con->root->peer_table = ast_hashtab_create(13,
09151                         hashtab_compare_exten_numbers,
09152                         ast_hashtab_resize_java,
09153                         ast_hashtab_newsize_java,
09154                         hashtab_hash_priority,
09155                         0);
09156          con->root->peer_label_table = ast_hashtab_create(7,
09157                            hashtab_compare_exten_labels,
09158                            ast_hashtab_resize_java,
09159                            ast_hashtab_newsize_java,
09160                            hashtab_hash_labels,
09161                            0);
09162          if (label) {
09163             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
09164          }
09165          ast_hashtab_insert_safe(con->root->peer_table, tmp);
09166 
09167       }
09168       ast_hashtab_insert_safe(con->root_table, tmp);
09169       if (lock_context) {
09170          ast_unlock_context(con);
09171       }
09172       if (tmp->priority == PRIORITY_HINT) {
09173          ast_add_hint(tmp);
09174       }
09175    }
09176    if (option_debug) {
09177       if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
09178          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
09179                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
09180       } else {
09181          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
09182                  tmp->exten, tmp->priority, con->name, con);
09183       }
09184    }
09185 
09186    if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
09187       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
09188              tmp->exten, tmp->priority, tmp->cidmatch, con->name);
09189    } else {
09190       ast_verb(3, "Added extension '%s' priority %d to %s\n",
09191              tmp->exten, tmp->priority, con->name);
09192    }
09193 
09194    return 0;
09195 }

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 8594 of file pbx.c.

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

08597 {
08598    int ret = -1;
08599    struct ast_context *c;
08600 
08601    c = find_context(context);
08602    if (c) {
08603       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
08604          application, data, datad, registrar, 1);
08605    }
08606 
08607    return ret;
08608 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 5227 of file pbx.c.

References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), ast_hint::callbacks, destroy_hint(), ast_hint::exten, hint_id_cmp(), hints, and ast_hint::laststate.

Referenced by add_priority(), and ast_add_extension2_lockopt().

05228 {
05229    struct ast_hint *hint_new;
05230    struct ast_hint *hint_found;
05231 
05232    if (!e) {
05233       return -1;
05234    }
05235 
05236    /*
05237     * We must create the hint we wish to add before determining if
05238     * it is already in the hints container to avoid possible
05239     * deadlock when getting the current extension state.
05240     */
05241    hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
05242    if (!hint_new) {
05243       return -1;
05244    }
05245 
05246    /* Initialize new hint. */
05247    hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
05248    if (!hint_new->callbacks) {
05249       ao2_ref(hint_new, -1);
05250       return -1;
05251    }
05252    hint_new->exten = e;
05253    hint_new->laststate = ast_extension_state2(e);
05254 
05255    /* Prevent multiple add hints from adding the same hint at the same time. */
05256    ao2_lock(hints);
05257 
05258    /* Search if hint exists, do nothing */
05259    hint_found = ao2_find(hints, e, 0);
05260    if (hint_found) {
05261       ao2_ref(hint_found, -1);
05262       ao2_unlock(hints);
05263       ao2_ref(hint_new, -1);
05264       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
05265          ast_get_extension_name(e), ast_get_extension_app(e));
05266       return -1;
05267    }
05268 
05269    /* Add new hint to the hints container */
05270    ast_debug(2, "HINTS: Adding hint %s: %s\n",
05271       ast_get_extension_name(e), ast_get_extension_app(e));
05272    ao2_link(hints, hint_new);
05273 
05274    ao2_unlock(hints);
05275    ao2_ref(hint_new, -1);
05276 
05277    return 0;
05278 }

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.

See also:
ast_async_parseable_goto, ast_async_goto_if_exists
Note:
Do _NOT_ hold any channel locks when calling this function.

Definition at line 8654 of file pbx.c.

References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.

Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmf(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().

08655 {
08656    int res = 0;
08657    struct ast_channel *tmpchan;
08658    struct {
08659       char *accountcode;
08660       char *exten;
08661       char *context;
08662       char *linkedid;
08663       char *name;
08664       struct ast_cdr *cdr;
08665       int amaflags;
08666       int state;
08667       format_t readformat;
08668       format_t writeformat;
08669    } tmpvars = { 0, };
08670 
08671    ast_channel_lock(chan);
08672    if (chan->pbx) { /* This channel is currently in the PBX */
08673       ast_explicit_goto(chan, context, exten, priority + 1);
08674       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08675       ast_channel_unlock(chan);
08676       return res;
08677    }
08678 
08679    /* In order to do it when the channel doesn't really exist within
08680     * the PBX, we have to make a new channel, masquerade, and start the PBX
08681     * at the new location */
08682    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08683    tmpvars.exten = ast_strdupa(chan->exten);
08684    tmpvars.context = ast_strdupa(chan->context);
08685    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08686    tmpvars.name = ast_strdupa(chan->name);
08687    tmpvars.amaflags = chan->amaflags;
08688    tmpvars.state = chan->_state;
08689    tmpvars.writeformat = chan->writeformat;
08690    tmpvars.readformat = chan->readformat;
08691    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08692 
08693    ast_channel_unlock(chan);
08694 
08695    /* Do not hold any channel locks while calling channel_alloc() since the function
08696     * locks the channel container when linking the new channel in. */
08697    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08698       ast_cdr_discard(tmpvars.cdr);
08699       return -1;
08700    }
08701 
08702    /* copy the cdr info over */
08703    if (tmpvars.cdr) {
08704       ast_cdr_discard(tmpchan->cdr);
08705       tmpchan->cdr = tmpvars.cdr;
08706       tmpvars.cdr = NULL;
08707    }
08708 
08709    /* Make formats okay */
08710    tmpchan->readformat = tmpvars.readformat;
08711    tmpchan->writeformat = tmpvars.writeformat;
08712 
08713    /* Setup proper location. Never hold another channel lock while calling this function. */
08714    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08715 
08716    /* Masquerade into tmp channel */
08717    if (ast_channel_masquerade(tmpchan, chan)) {
08718       /* Failed to set up the masquerade.  It's probably chan_local
08719        * in the middle of optimizing itself out.  Sad. :( */
08720       ast_hangup(tmpchan);
08721       tmpchan = NULL;
08722       res = -1;
08723    } else {
08724       ast_do_masquerade(tmpchan);
08725       /* Start the PBX going on our stolen channel */
08726       if (ast_pbx_start(tmpchan)) {
08727          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08728          ast_hangup(tmpchan);
08729          res = -1;
08730       }
08731    }
08732 
08733    return res;
08734 }

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 8736 of file pbx.c.

References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.

08737 {
08738    struct ast_channel *chan;
08739    int res = -1;
08740 
08741    if ((chan = ast_channel_get_by_name(channame))) {
08742       res = ast_async_goto(chan, context, exten, priority);
08743       chan = ast_channel_unref(chan);
08744    }
08745 
08746    return res;
08747 }

int ast_async_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
Note:
This function will handle locking the channel as needed.

Definition at line 11094 of file pbx.c.

References __ast_goto_if_exists().

11095 {
11096    return __ast_goto_if_exists(chan, context, exten, priority, 1);
11097 }

int ast_async_parseable_goto ( struct ast_channel chan,
const char *  goto_string 
)
Note:
This function will handle locking the channel as needed.

Definition at line 11159 of file pbx.c.

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

11160 {
11161    return pbx_parseable_goto(chan, goto_string, 1);
11162 }

int ast_build_timing ( struct ast_timing i,
const char *  info 
)

Construct a timing bitmap, for use in time-based conditionals.

Parameters:
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.
Return values:
Returns 1 on success or 0 on failure.

Definition at line 8237 of file pbx.c.

References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and ast_timing::timezone.

Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().

08238 {
08239    char *info;
08240    int j, num_fields, last_sep = -1;
08241 
08242    /* Check for empty just in case */
08243    if (ast_strlen_zero(info_in)) {
08244       return 0;
08245    }
08246 
08247    /* make a copy just in case we were passed a static string */
08248    info = ast_strdupa(info_in);
08249 
08250    /* count the number of fields in the timespec */
08251    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
08252       if (info[j] == ',') {
08253          last_sep = j;
08254          num_fields++;
08255       }
08256    }
08257 
08258    /* save the timezone, if it is specified */
08259    if (num_fields == 5) {
08260       i->timezone = ast_strdup(info + last_sep + 1);
08261    } else {
08262       i->timezone = NULL;
08263    }
08264 
08265    /* Assume everything except time */
08266    i->monthmask = 0xfff;   /* 12 bits */
08267    i->daymask = 0x7fffffffU; /* 31 bits */
08268    i->dowmask = 0x7f; /* 7 bits */
08269    /* on each call, use strsep() to move info to the next argument */
08270    get_timerange(i, strsep(&info, "|,"));
08271    if (info)
08272       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
08273    if (info)
08274       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
08275    if (info)
08276       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
08277    return 1;
08278 }

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.

Parameters:
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
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Returns:
If "exten" *could be* a valid extension in this context with or without some more digits, return non-zero. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

Definition at line 5368 of file pbx.c.

References E_CANMATCH, and pbx_extension_helper().

Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().

05369 {
05370    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05371 }

static int ast_change_hint ( struct ast_exten oe,
struct ast_exten ne 
) [static]

Change hint for an extension.

Definition at line 5281 of file pbx.c.

References ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_hint::exten, hints, and OBJ_UNLINK.

Referenced by add_priority().

05282 {
05283    struct ast_hint *hint;
05284 
05285    if (!oe || !ne) {
05286       return -1;
05287    }
05288 
05289    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
05290 
05291    /*
05292     * Unlink the hint from the hints container as the extension
05293     * name (which is the hash value) could change.
05294     */
05295    hint = ao2_find(hints, oe, OBJ_UNLINK);
05296    if (!hint) {
05297       ao2_unlock(hints);
05298       return -1;
05299    }
05300 
05301    /* Update the hint and put it back in the hints container. */
05302    ao2_lock(hint);
05303    hint->exten = ne;
05304    ao2_unlock(hint);
05305    ao2_link(hints, hint);
05306 
05307    ao2_unlock(hints);
05308    ao2_ref(hint, -1);
05309 
05310    return 0;
05311 }

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.

Parameters:
i Pointer to an ast_timing structure.
Return values:
Returns 1, if the time matches or 0, if the current time falls outside of the specified range.

Definition at line 8280 of file pbx.c.

References ast_check_timing2(), and ast_tvnow().

Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().

08281 {
08282    return ast_check_timing2(i, ast_tvnow());
08283 }

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.

Parameters:
i Pointer to an ast_timing structure.
tv Specified time
Return values:
Returns 1, if the time matches or 0, if the time falls outside of the specified range.

Definition at line 8285 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().

08286 {
08287    struct ast_tm tm;
08288 
08289    ast_localtime(&tv, &tm, i->timezone);
08290 
08291    /* If it's not the right month, return */
08292    if (!(i->monthmask & (1 << tm.tm_mon)))
08293       return 0;
08294 
08295    /* If it's not that time of the month.... */
08296    /* Warning, tm_mday has range 1..31! */
08297    if (!(i->daymask & (1 << (tm.tm_mday-1))))
08298       return 0;
08299 
08300    /* If it's not the right day of the week */
08301    if (!(i->dowmask & (1 << tm.tm_wday)))
08302       return 0;
08303 
08304    /* Sanity check the hour just to be safe */
08305    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
08306       ast_log(LOG_WARNING, "Insane time...\n");
08307       return 0;
08308    }
08309 
08310    /* Now the tough part, we calculate if it fits
08311       in the right time based on min/hour */
08312    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))))
08313       return 0;
08314 
08315    /* If we got this far, then we're good */
08316    return 1;
08317 }

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 11164 of file pbx.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::name.

Referenced by handle_orig(), and handle_show_application().

11165 {
11166    struct ast_app *app = NULL;
11167    int which = 0;
11168    char *ret = NULL;
11169    size_t wordlen = strlen(word);
11170 
11171    AST_RWLIST_RDLOCK(&apps);
11172    AST_RWLIST_TRAVERSE(&apps, app, list) {
11173       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
11174          ret = ast_strdup(app->name);
11175          break;
11176       }
11177    }
11178    AST_RWLIST_UNLOCK(&apps);
11179 
11180    return ret;
11181 }

int ast_context_add_ignorepat ( const char *  context,
const char *  ignorepat,
const char *  registrar 
)

Add an ignorepat.

Parameters:
context which context to add the ignorpattern to
ignorepat ignorepattern to set up for the extension
registrar registrar of the ignore pattern

Adds an ignore pattern to a particular context.

Return values:
0 on success
-1 on failure

Definition at line 8521 of file pbx.c.

References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_cli_dialplan_add_ignorepat().

08522 {
08523    int ret = -1;
08524    struct ast_context *c;
08525 
08526    c = find_context_locked(context);
08527    if (c) {
08528       ret = ast_context_add_ignorepat2(c, value, registrar);
08529       ast_unlock_contexts();
08530    }
08531    return ret;
08532 }

int ast_context_add_ignorepat2 ( struct ast_context con,
const char *  value,
const char *  registrar 
)

Definition at line 8534 of file pbx.c.

References ast_calloc, ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.

Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().

08535 {
08536    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08537    int length;
08538    char *pattern;
08539    length = sizeof(struct ast_ignorepat);
08540    length += strlen(value) + 1;
08541    if (!(ignorepat = ast_calloc(1, length)))
08542       return -1;
08543    /* The cast to char * is because we need to write the initial value.
08544     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08545     * sees the cast as dereferencing a type-punned pointer and warns about
08546     * it.  This is the workaround (we're telling gcc, yes, that's really
08547     * what we wanted to do).
08548     */
08549    pattern = (char *) ignorepat->pattern;
08550    strcpy(pattern, value);
08551    ignorepat->next = NULL;
08552    ignorepat->registrar = registrar;
08553    ast_wrlock_context(con);
08554    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08555       ignorepatl = ignorepatc;
08556       if (!strcasecmp(ignorepatc->pattern, value)) {
08557          /* Already there */
08558          ast_unlock_context(con);
08559          ast_free(ignorepat);
08560          errno = EEXIST;
08561          return -1;
08562       }
08563    }
08564    if (ignorepatl)
08565       ignorepatl->next = ignorepat;
08566    else
08567       con->ignorepats = ignorepat;
08568    ast_unlock_context(con);
08569    return 0;
08570 
08571 }

int ast_context_add_include ( const char *  context,
const char *  include,
const char *  registrar 
)

Add a context include.

Parameters:
context context to add include to
include new include to add
registrar who's registering it

Adds an include taking a char * string as the context parameter

Return values:
0 on success
-1 on error

Definition at line 8065 of file pbx.c.

References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_cli_dialplan_add_include().

08066 {
08067    int ret = -1;
08068    struct ast_context *c;
08069 
08070    c = find_context_locked(context);
08071    if (c) {
08072       ret = ast_context_add_include2(c, include, registrar);
08073       ast_unlock_contexts();
08074    }
08075    return ret;
08076 }

int ast_context_add_include2 ( struct ast_context con,
const char *  include,
const char *  registrar 
)

Add a context include.

Parameters:
con context to add the include to
include include to add
registrar who registered the context

Adds an include taking a struct ast_context as the first parameter

Return values:
0 on success
-1 on failure

Definition at line 8334 of file pbx.c.

References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.

Referenced by ast_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().

08336 {
08337    struct ast_include *new_include;
08338    char *c;
08339    struct ast_include *i, *il = NULL; /* include, include_last */
08340    int length;
08341    char *p;
08342 
08343    length = sizeof(struct ast_include);
08344    length += 2 * (strlen(value) + 1);
08345 
08346    /* allocate new include structure ... */
08347    if (!(new_include = ast_calloc(1, length)))
08348       return -1;
08349    /* Fill in this structure. Use 'p' for assignments, as the fields
08350     * in the structure are 'const char *'
08351     */
08352    p = new_include->stuff;
08353    new_include->name = p;
08354    strcpy(p, value);
08355    p += strlen(value) + 1;
08356    new_include->rname = p;
08357    strcpy(p, value);
08358    /* Strip off timing info, and process if it is there */
08359    if ( (c = strchr(p, ',')) ) {
08360       *c++ = '\0';
08361       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08362    }
08363    new_include->next      = NULL;
08364    new_include->registrar = registrar;
08365 
08366    ast_wrlock_context(con);
08367 
08368    /* ... go to last include and check if context is already included too... */
08369    for (i = con->includes; i; i = i->next) {
08370       if (!strcasecmp(i->name, new_include->name)) {
08371          ast_destroy_timing(&(new_include->timing));
08372          ast_free(new_include);
08373          ast_unlock_context(con);
08374          errno = EEXIST;
08375          return -1;
08376       }
08377       il = i;
08378    }
08379 
08380    /* ... include new context into context list, unlock, return */
08381    if (il)
08382       il->next = new_include;
08383    else
08384       con->includes = new_include;
08385    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08386 
08387    ast_unlock_context(con);
08388 
08389    return 0;
08390 }

int ast_context_add_switch ( const char *  context,
const char *  sw,
const char *  data,
int  eval,
const char *  registrar 
)

Add a switch.

Parameters:
context context to which to add the switch
sw switch to add
data data to pass to switch
eval whether to evaluate variables when running switch
registrar whoever registered the switch

This function registers a switch with the asterisk switch architecture

Return values:
0 on success
-1 on failure

Definition at line 8397 of file pbx.c.

References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().

08398 {
08399    int ret = -1;
08400    struct ast_context *c;
08401 
08402    c = find_context_locked(context);
08403    if (c) { /* found, add switch to this context */
08404       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08405       ast_unlock_contexts();
08406    }
08407    return ret;
08408 }

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).

Note:
See ast_context_add_switch() for argument information, with the exception of the first argument. In this case, it's a pointer to an ast_context structure as opposed to the name.

Definition at line 8417 of file pbx.c.

References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.

Referenced by ast_compile_ael2(), ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().

08419 {
08420    struct ast_sw *new_sw;
08421    struct ast_sw *i;
08422    int length;
08423    char *p;
08424 
08425    length = sizeof(struct ast_sw);
08426    length += strlen(value) + 1;
08427    if (data)
08428       length += strlen(data);
08429    length++;
08430 
08431    /* allocate new sw structure ... */
08432    if (!(new_sw = ast_calloc(1, length)))
08433       return -1;
08434    /* ... fill in this structure ... */
08435    p = new_sw->stuff;
08436    new_sw->name = p;
08437    strcpy(new_sw->name, value);
08438    p += strlen(value) + 1;
08439    new_sw->data = p;
08440    if (data) {
08441       strcpy(new_sw->data, data);
08442       p += strlen(data) + 1;
08443    } else {
08444       strcpy(new_sw->data, "");
08445       p++;
08446    }
08447    new_sw->eval     = eval;
08448    new_sw->registrar = registrar;
08449 
08450    /* ... try to lock this context ... */
08451    ast_wrlock_context(con);
08452 
08453    /* ... go to last sw and check if context is already swd too... */
08454    AST_LIST_TRAVERSE(&con->alts, i, list) {
08455       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08456          ast_free(new_sw);
08457          ast_unlock_context(con);
08458          errno = EEXIST;
08459          return -1;
08460       }
08461    }
08462 
08463    /* ... sw new context into context list, unlock, return */
08464    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08465 
08466    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08467 
08468    ast_unlock_context(con);
08469 
08470    return 0;
08471 }

void ast_context_destroy ( struct ast_context con,
const char *  registrar 
)

Destroy a context (matches the specified context (or ANY context if NULL).

Parameters:
con context to destroy
registrar who registered it

You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.

Returns:
nothing

Definition at line 9798 of file pbx.c.

References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.

Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), features_shutdown(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().

struct ast_context* ast_context_find ( const char *  name  )  [read]

Find a context.

Parameters:
name name of the context to find

Will search for the context with the given name.

Returns:
the ast_context on success, NULL on failure.

Definition at line 2929 of file pbx.c.

References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.

Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().

02930 {
02931    struct ast_context *tmp;
02932    struct fake_context item;
02933 
02934    if (!name) {
02935       return NULL;
02936    }
02937    ast_rdlock_contexts();
02938    if (contexts_table) {
02939       ast_copy_string(item.name, name, sizeof(item.name));
02940       tmp = ast_hashtab_lookup(contexts_table, &item);
02941    } else {
02942       tmp = NULL;
02943       while ((tmp = ast_walk_contexts(tmp))) {
02944          if (!strcasecmp(name, tmp->name)) {
02945             break;
02946          }
02947       }
02948    }
02949    ast_unlock_contexts();
02950    return tmp;
02951 }

struct ast_context* ast_context_find_or_create ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  name,
const char *  registrar 
) [read]

Register a new context or find an existing one.

Parameters:
extcontexts pointer to the ast_context structure pointer
exttable pointer to the hashtable that contains all the elements in extcontexts
name name of the new context
registrar registrar of the context

This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.

This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns:
NULL on failure, and an ast_context structure on success

Definition at line 7664 of file pbx.c.

References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.

Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().

07665 {
07666    struct ast_context *tmp, **local_contexts;
07667    struct fake_context search;
07668    int length = sizeof(struct ast_context) + strlen(name) + 1;
07669 
07670    if (!contexts_table) {
07671       /* Protect creation of contexts_table from reentrancy. */
07672       ast_wrlock_contexts();
07673       if (!contexts_table) {
07674          contexts_table = ast_hashtab_create(17,
07675             ast_hashtab_compare_contexts,
07676             ast_hashtab_resize_java,
07677             ast_hashtab_newsize_java,
07678             ast_hashtab_hash_contexts,
07679             0);
07680       }
07681       ast_unlock_contexts();
07682    }
07683 
07684    ast_copy_string(search.name, name, sizeof(search.name));
07685    if (!extcontexts) {
07686       ast_rdlock_contexts();
07687       local_contexts = &contexts;
07688       tmp = ast_hashtab_lookup(contexts_table, &search);
07689       ast_unlock_contexts();
07690       if (tmp) {
07691          tmp->refcount++;
07692          return tmp;
07693       }
07694    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07695       local_contexts = extcontexts;
07696       tmp = ast_hashtab_lookup(exttable, &search);
07697       if (tmp) {
07698          tmp->refcount++;
07699          return tmp;
07700       }
07701    }
07702 
07703    if ((tmp = ast_calloc(1, length))) {
07704       ast_rwlock_init(&tmp->lock);
07705       ast_mutex_init(&tmp->macrolock);
07706       strcpy(tmp->name, name);
07707       tmp->root = NULL;
07708       tmp->root_table = NULL;
07709       tmp->registrar = ast_strdup(registrar);
07710       tmp->includes = NULL;
07711       tmp->ignorepats = NULL;
07712       tmp->refcount = 1;
07713    } else {
07714       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07715       return NULL;
07716    }
07717 
07718    if (!extcontexts) {
07719       ast_wrlock_contexts();
07720       tmp->next = *local_contexts;
07721       *local_contexts = tmp;
07722       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07723       ast_unlock_contexts();
07724       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07725       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07726    } else {
07727       tmp->next = *local_contexts;
07728       if (exttable)
07729          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07730 
07731       *local_contexts = tmp;
07732       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07733       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07734    }
07735    return tmp;
07736 }

int ast_context_lockmacro ( const char *  context  ) 

locks the macrolock in the given given context

Note:
This function locks contexts list by &conlist, searches for the right context structure, and locks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.

Definition at line 6259 of file pbx.c.

References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.

Referenced by _macro_exec().

06260 {
06261    struct ast_context *c;
06262    int ret = -1;
06263 
06264    c = find_context_locked(context);
06265    if (c) {
06266       ast_unlock_contexts();
06267 
06268       /* if we found context, lock macrolock */
06269       ret = ast_mutex_lock(&c->macrolock);
06270    }
06271 
06272    return ret;
06273 }

int ast_context_remove_extension ( const char *  context,
const char *  extension,
int  priority,
const char *  registrar 
)

Simply remove extension from context.

Note:
This function will lock conlock.

Definition at line 6067 of file pbx.c.

References ast_context_remove_extension_callerid(), and AST_EXT_MATCHCID_ANY.

Referenced by register_peer_exten(), remove_exten_if_exist(), sla_station_destructor(), sla_trunk_destructor(), unregister_exten(), and UnregisterExtension().

06068 {
06069    return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
06070 }

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.

Note:
When do you want to call this function, make sure that &conlock is locked, because some process can handle with your *con context before you lock it.

Definition at line 6097 of file pbx.c.

References ast_context_remove_extension_callerid2(), and AST_EXT_MATCHCID_ANY.

Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().

06098 {
06099    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
06100 }

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 6072 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().

06073 {
06074    int ret = -1; /* default error return */
06075    struct ast_context *c;
06076 
06077    c = find_context_locked(context);
06078    if (c) { /* ... remove extension ... */
06079       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
06080          matchcallerid, registrar, 0);
06081       ast_unlock_contexts();
06082    }
06083 
06084    return ret;
06085 }

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 6102 of file pbx.c.

References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.

Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().

06103 {
06104    struct ast_exten *exten, *prev_exten = NULL;
06105    struct ast_exten *peer;
06106    struct ast_exten ex, *exten2, *exten3;
06107    char dummy_name[1024];
06108    struct ast_exten *previous_peer = NULL;
06109    struct ast_exten *next_peer = NULL;
06110    int found = 0;
06111 
06112    if (!already_locked)
06113       ast_wrlock_context(con);
06114 
06115 #ifdef NEED_DEBUG
06116    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
06117 #endif
06118 #ifdef CONTEXT_DEBUG
06119    check_contexts(__FILE__, __LINE__);
06120 #endif
06121    /* find this particular extension */
06122    ex.exten = dummy_name;
06123    ex.matchcid = matchcallerid;
06124    ex.cidmatch = callerid;
06125    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
06126    exten = ast_hashtab_lookup(con->root_table, &ex);
06127    if (exten) {
06128       if (priority == 0) {
06129          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
06130          if (!exten2)
06131             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);
06132          if (con->pattern_tree) {
06133             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
06134 
06135             if (x->exten) { /* this test for safety purposes */
06136                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
06137                x->exten = 0; /* get rid of what will become a bad pointer */
06138             } else {
06139                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
06140             }
06141          }
06142       } else {
06143          ex.priority = priority;
06144          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
06145          if (exten2) {
06146             if (exten2->label) { /* if this exten has a label, remove that, too */
06147                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
06148                if (!exten3)
06149                   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);
06150             }
06151 
06152             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
06153             if (!exten3)
06154                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);
06155             if (exten2 == exten && exten2->peer) {
06156                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
06157                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
06158             }
06159             if (ast_hashtab_size(exten->peer_table) == 0) {
06160                /* well, if the last priority of an exten is to be removed,
06161                   then, the extension is removed, too! */
06162                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
06163                if (!exten3)
06164                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
06165                if (con->pattern_tree) {
06166                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
06167                   if (x->exten) { /* this test for safety purposes */
06168                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
06169                      x->exten = 0; /* get rid of what will become a bad pointer */
06170                   }
06171                }
06172             }
06173          } else {
06174             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
06175                   priority, exten->exten, con->name);
06176          }
06177       }
06178    } else {
06179       /* hmmm? this exten is not in this pattern tree? */
06180       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
06181             extension, con->name);
06182    }
06183 #ifdef NEED_DEBUG
06184    if (con->pattern_tree) {
06185       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
06186       log_match_char_tree(con->pattern_tree, " ");
06187    }
06188 #endif
06189 
06190    /* scan the extension list to find first matching extension-registrar */
06191    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
06192       if (!strcmp(exten->exten, extension) &&
06193          (!registrar || !strcmp(exten->registrar, registrar)) &&
06194          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
06195          break;
06196    }
06197    if (!exten) {
06198       /* we can't find right extension */
06199       if (!already_locked)
06200          ast_unlock_context(con);
06201       return -1;
06202    }
06203 
06204    /* scan the priority list to remove extension with exten->priority == priority */
06205    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
06206        peer && !strcmp(peer->exten, extension) &&
06207          (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ;
06208          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
06209 
06210       if ((priority == 0 || peer->priority == priority) &&
06211             (!registrar || !strcmp(peer->registrar, registrar) )) {
06212          found = 1;
06213 
06214          /* we are first priority extension? */
06215          if (!previous_peer) {
06216             /*
06217              * We are first in the priority chain, so must update the extension chain.
06218              * The next node is either the next priority or the next extension
06219              */
06220             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
06221             if (peer->peer) {
06222                /* move the peer_table and peer_label_table down to the next peer, if
06223                   it is there */
06224                peer->peer->peer_table = peer->peer_table;
06225                peer->peer->peer_label_table = peer->peer_label_table;
06226                peer->peer_table = NULL;
06227                peer->peer_label_table = NULL;
06228             }
06229             if (!prev_exten) {   /* change the root... */
06230                con->root = next_node;
06231             } else {
06232                prev_exten->next = next_node; /* unlink */
06233             }
06234             if (peer->peer)   { /* update the new head of the pri list */
06235                peer->peer->next = peer->next;
06236             }
06237          } else { /* easy, we are not first priority in extension */
06238             previous_peer->peer = peer->peer;
06239          }
06240 
06241 
06242          /* now, free whole priority extension */
06243          destroy_exten(peer);
06244       } else {
06245          previous_peer = peer;
06246       }
06247    }
06248    if (!already_locked)
06249       ast_unlock_context(con);
06250    return found ? 0 : -1;
06251 }

int ast_context_remove_ignorepat ( const char *  context,
const char *  ignorepat,
const char *  registrar 
)

Definition at line 8477 of file pbx.c.

References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_cli_dialplan_remove_ignorepat().

08478 {
08479    int ret = -1;
08480    struct ast_context *c;
08481 
08482    c = find_context_locked(context);
08483    if (c) {
08484       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08485       ast_unlock_contexts();
08486    }
08487    return ret;
08488 }

int ast_context_remove_ignorepat2 ( struct ast_context con,
const char *  ignorepat,
const char *  registrar 
)

Definition at line 8490 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().

08491 {
08492    struct ast_ignorepat *ip, *ipl = NULL;
08493 
08494    ast_wrlock_context(con);
08495 
08496    for (ip = con->ignorepats; ip; ip = ip->next) {
08497       if (!strcmp(ip->pattern, ignorepat) &&
08498          (!registrar || (registrar == ip->registrar))) {
08499          if (ipl) {
08500             ipl->next = ip->next;
08501             ast_free(ip);
08502          } else {
08503             con->ignorepats = ip->next;
08504             ast_free(ip);
08505          }
08506          ast_unlock_context(con);
08507          return 0;
08508       }
08509       ipl = ip;
08510    }
08511 
08512    ast_unlock_context(con);
08513    errno = EINVAL;
08514    return -1;
08515 }

int ast_context_remove_include ( const char *  context,
const char *  include,
const char *  registrar 
)

Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ...

Remove a context include.

Definition at line 5960 of file pbx.c.

References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().

Referenced by handle_cli_dialplan_remove_include().

05961 {
05962    int ret = -1;
05963    struct ast_context *c;
05964 
05965    c = find_context_locked(context);
05966    if (c) {
05967       /* found, remove include from this context ... */
05968       ret = ast_context_remove_include2(c, include, registrar);
05969       ast_unlock_contexts();
05970    }
05971    return ret;
05972 }

int ast_context_remove_include2 ( struct ast_context con,
const char *  include,
const char *  registrar 
)

Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.

Removes an include by an ast_context structure.

Return values:
0 on success.
-1 on failure.

Definition at line 5983 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().

05984 {
05985    struct ast_include *i, *pi = NULL;
05986    int ret = -1;
05987 
05988    ast_wrlock_context(con);
05989 
05990    /* find our include */
05991    for (i = con->includes; i; pi = i, i = i->next) {
05992       if (!strcmp(i->name, include) &&
05993             (!registrar || !strcmp(i->registrar, registrar))) {
05994          /* remove from list */
05995          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05996          if (pi)
05997             pi->next = i->next;
05998          else
05999             con->includes = i->next;
06000          /* free include and return */
06001          ast_destroy_timing(&(i->timing));
06002          ast_free(i);
06003          ret = 0;
06004          break;
06005       }
06006    }
06007 
06008    ast_unlock_context(con);
06009 
06010    return ret;
06011 }

int ast_context_remove_switch ( const char *  context,
const char *  sw,
const char *  data,
const char *  registrar 
)

Remove a switch.

Note:
This function locks contexts list by &conlist, search for the rigt context structure, leave context list locked and call ast_context_remove_switch2 which removes switch, unlock contexts list and return ...

Definition at line 6018 of file pbx.c.

References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().

06019 {
06020    int ret = -1; /* default error return */
06021    struct ast_context *c;
06022 
06023    c = find_context_locked(context);
06024    if (c) {
06025       /* remove switch from this context ... */
06026       ret = ast_context_remove_switch2(c, sw, data, registrar);
06027       ast_unlock_contexts();
06028    }
06029    return ret;
06030 }

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.

Note:
When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.

Definition at line 6040 of file pbx.c.

References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.

Referenced by ast_context_remove_switch().

06041 {
06042    struct ast_sw *i;
06043    int ret = -1;
06044 
06045    ast_wrlock_context(con);
06046 
06047    /* walk switches */
06048    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
06049       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
06050          (!registrar || !strcmp(i->registrar, registrar))) {
06051          /* found, remove from list */
06052          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
06053          AST_LIST_REMOVE_CURRENT(list);
06054          ast_free(i); /* free switch and return */
06055          ret = 0;
06056          break;
06057       }
06058    }
06059    AST_LIST_TRAVERSE_SAFE_END;
06060 
06061    ast_unlock_context(con);
06062 
06063    return ret;
06064 }

int ast_context_unlockmacro ( const char *  context  ) 

Unlocks the macrolock in the given context.

Note:
This function locks contexts list by &conlist, searches for the right context structure, and unlocks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.

Definition at line 6280 of file pbx.c.

References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.

Referenced by _macro_exec().

06281 {
06282    struct ast_context *c;
06283    int ret = -1;
06284 
06285    c = find_context_locked(context);
06286    if (c) {
06287       ast_unlock_contexts();
06288 
06289       /* if we found context, unlock macrolock */
06290       ret = ast_mutex_unlock(&c->macrolock);
06291    }
06292 
06293    return ret;
06294 }

int ast_context_verify_includes ( struct ast_context con  ) 

Verifies includes in an ast_contect structure.

Parameters:
con context in which to verify the includes
Return values:
0 if no problems found
-1 if there were any missing context

Definition at line 11049 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().

11050 {
11051    struct ast_include *inc = NULL;
11052    int res = 0;
11053 
11054    while ( (inc = ast_walk_context_includes(con, inc)) ) {
11055       if (ast_context_find(inc->rname))
11056          continue;
11057 
11058       res = -1;
11059       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
11060          ast_get_context_name(con), inc->rname);
11061       break;
11062    }
11063 
11064    return res;
11065 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  )  [read]
int ast_custom_function_unregister ( struct ast_custom_function acf  ) 

Unregister a custom function.

Definition at line 3772 of file pbx.c.

References ast_custom_escalating_function::acf, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.

Referenced by __ast_custom_function_register_escalating(), _unload_module(), load_module(), reload(), unload_module(), and unload_pbx().

03773 {
03774    struct ast_custom_function *cur;
03775    struct ast_custom_escalating_function *cur_escalation;
03776 
03777    if (!acf) {
03778       return -1;
03779    }
03780 
03781    AST_RWLIST_WRLOCK(&acf_root);
03782    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03783 #ifdef AST_XML_DOCS
03784       if (cur->docsrc == AST_XML_DOC) {
03785          ast_string_field_free_memory(acf);
03786       }
03787 #endif
03788       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03789    }
03790    AST_RWLIST_UNLOCK(&acf_root);
03791 
03792    /* Remove from the escalation list */
03793    AST_RWLIST_WRLOCK(&escalation_root);
03794    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) {
03795       if (cur_escalation->acf == acf) {
03796          AST_RWLIST_REMOVE_CURRENT(list);
03797          break;
03798       }
03799    }
03800    AST_RWLIST_TRAVERSE_SAFE_END;
03801    AST_RWLIST_UNLOCK(&escalation_root);
03802 
03803    return cur ? 0 : -1;
03804 }

int ast_destroy_timing ( struct ast_timing i  ) 

Deallocates memory structures associated with a timing bitmap.

Parameters:
i Pointer to an ast_timing structure.
Return values:
0 success
non-zero failure (number suitable to pass to
See also:
strerror)

Definition at line 8319 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().

08320 {
08321    if (i->timezone) {
08322       ast_free(i->timezone);
08323       i->timezone = NULL;
08324    }
08325    return 0;
08326 }

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate  ) 

Map devstate to an extension state.

Parameters:
[in] devstate device state
Returns:
the extension state mapping.

Definition at line 4801 of file pbx.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.

Referenced by ast_extension_state3().

04802 {
04803    switch (devstate) {
04804    case AST_DEVICE_ONHOLD:
04805       return AST_EXTENSION_ONHOLD;
04806    case AST_DEVICE_BUSY:
04807       return AST_EXTENSION_BUSY;
04808    case AST_DEVICE_UNKNOWN:
04809       return AST_EXTENSION_NOT_INUSE;
04810    case AST_DEVICE_UNAVAILABLE:
04811    case AST_DEVICE_INVALID:
04812       return AST_EXTENSION_UNAVAILABLE;
04813    case AST_DEVICE_RINGINUSE:
04814       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04815    case AST_DEVICE_RINGING:
04816       return AST_EXTENSION_RINGING;
04817    case AST_DEVICE_INUSE:
04818       return AST_EXTENSION_INUSE;
04819    case AST_DEVICE_NOT_INUSE:
04820       return AST_EXTENSION_NOT_INUSE;
04821    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04822       break;
04823    }
04824 
04825    return AST_EXTENSION_NOT_INUSE;
04826 }

int ast_exists_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid 
)

Determine whether an extension exists.

Parameters:
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
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Returns:
If an extension within the given context(or callerid) with the given priority is found a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 5353 of file pbx.c.

References E_MATCH, and pbx_extension_helper().

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().

05354 {
05355    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05356 }

int ast_explicit_goto ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
Note:
This function will handle locking the channel as needed.

Definition at line 8631 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.

Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().

08632 {
08633    if (!chan)
08634       return -1;
08635 
08636    ast_channel_lock(chan);
08637 
08638    if (!ast_strlen_zero(context))
08639       ast_copy_string(chan->context, context, sizeof(chan->context));
08640    if (!ast_strlen_zero(exten))
08641       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08642    if (priority > -1) {
08643       chan->priority = priority;
08644       /* see flag description in channel.h for explanation */
08645       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08646          chan->priority--;
08647    }
08648 
08649    ast_channel_unlock(chan);
08650 
08651    return 0;
08652 }

int ast_extension_close ( const char *  pattern,
const char *  data,
int  needmore 
)

Definition at line 2906 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().

02907 {
02908    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02909       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02910    return extension_match_core(pattern, data, needmore);
02911 }

int ast_extension_cmp ( const char *  a,
const char *  b 
)

Determine if one extension should match before another.

Parameters:
a extension to compare with b
b extension to compare with a

Checks whether or extension a should match before extension b

Return values:
0 if the two extensions have equal matching priority
1 on a > b
-1 on a < b

Definition at line 2671 of file pbx.c.

References ext_cmp().

Referenced by lua_extension_cmp().

02672 {
02673    int cmp;
02674 
02675    cmp = ext_cmp(a, b);
02676    if (cmp < 0) {
02677       return -1;
02678    }
02679    if (cmp > 0) {
02680       return 1;
02681    }
02682    return 0;
02683 }

int ast_extension_match ( const char *  pattern,
const char *  extension 
)

Determine if a given extension matches a given pattern (in NXX format).

Parameters:
pattern pattern to match
extension extension to check against the pattern.

Checks whether or not the given extension matches the given pattern.

Return values:
1 on match
0 on failure

Definition at line 2901 of file pbx.c.

References E_MATCH, and extension_match_core().

Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().

02902 {
02903    return extension_match_core(pattern, data, E_MATCH);
02904 }

int ast_extension_state ( struct ast_channel c,
const char *  context,
const char *  exten 
)

Check extension state for an extension by using hint.

Uses hint and devicestate callback to get the state of an extension.

Definition at line 4871 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().

04872 {
04873    struct ast_exten *e;
04874 
04875    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04876       return -1;                   /* No hint, return -1 */
04877    }
04878 
04879    if (e->exten[0] == '_') {
04880       /* Create this hint on-the-fly */
04881       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04882          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04883          e->registrar);
04884       if (!(e = ast_hint_extension(c, context, exten))) {
04885          /* Improbable, but not impossible */
04886          return -1;
04887       }
04888    }
04889 
04890    return ast_extension_state2(e);  /* Check all devices in the hint */
04891 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

Definition at line 4846 of file pbx.c.

References ast_extension_state3(), ast_get_extension_app(), ast_str_set(), ast_str_thread_get(), and extensionstate_buf.

Referenced by ast_add_hint(), and ast_extension_state().

04847 {
04848    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
04849 
04850    if (!e || !hint_app) {
04851       return -1;
04852    }
04853 
04854    ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
04855    return ast_extension_state3(hint_app);
04856 }

const char* ast_extension_state2str ( int  extension_state  ) 

Return extension_state as string.

Return string representation of the state of an extension.

Definition at line 4859 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().

04860 {
04861    int i;
04862 
04863    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04864       if (extension_states[i].extension_state == extension_state)
04865          return extension_states[i].text;
04866    }
04867    return "Unknown";
04868 }

static int ast_extension_state3 ( struct ast_str hint_app  )  [static]

Definition at line 4828 of file pbx.c.

References ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), and ast_str_buffer().

Referenced by ast_extension_state2(), and handle_statechange().

04829 {
04830    char *cur;
04831    char *rest;
04832    struct ast_devstate_aggregate agg;
04833 
04834    /* One or more devices separated with a & character */
04835    rest = ast_str_buffer(hint_app);
04836 
04837    ast_devstate_aggregate_init(&agg);
04838    while ((cur = strsep(&rest, "&"))) {
04839       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
04840    }
04841 
04842    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
04843 }

int ast_extension_state_add ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
void *  data 
)

Add watcher for extension states.

Registers a state change callback.

Definition at line 5092 of file pbx.c.

References ast_extension_state_add_destroy().

Referenced by __init_manager(), load_module(), and skinny_register().

05094 {
05095    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
05096 }

int ast_extension_state_add_destroy ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
ast_state_cb_destroy_type  destroy_cb,
void *  data 
)

Add watcher for extension states with destructor.

Registers a state change callback with destructor.

Definition at line 5005 of file pbx.c.

References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, hints, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.

Referenced by ast_extension_state_add(), and handle_request_subscribe().

05007 {
05008    struct ast_hint *hint;
05009    struct ast_state_cb *state_cb;
05010    struct ast_exten *e;
05011    int id;
05012 
05013    /* If there's no context and extension:  add callback to statecbs list */
05014    if (!context && !exten) {
05015       /* Prevent multiple adds from adding the same change_cb at the same time. */
05016       ao2_lock(statecbs);
05017 
05018       /* Remove any existing change_cb. */
05019       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
05020 
05021       /* Now insert the change_cb */
05022       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05023          ao2_unlock(statecbs);
05024          return -1;
05025       }
05026       state_cb->id = 0;
05027       state_cb->change_cb = change_cb;
05028       state_cb->destroy_cb = destroy_cb;
05029       state_cb->data = data;
05030       ao2_link(statecbs, state_cb);
05031 
05032       ao2_ref(state_cb, -1);
05033       ao2_unlock(statecbs);
05034       return 0;
05035    }
05036 
05037    if (!context || !exten)
05038       return -1;
05039 
05040    /* This callback type is for only one hint, so get the hint */
05041    e = ast_hint_extension(NULL, context, exten);
05042    if (!e) {
05043       return -1;
05044    }
05045 
05046    /* If this is a pattern, dynamically create a new extension for this
05047     * particular match.  Note that this will only happen once for each
05048     * individual extension, because the pattern will no longer match first.
05049     */
05050    if (e->exten[0] == '_') {
05051       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05052          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05053          e->registrar);
05054       e = ast_hint_extension(NULL, context, exten);
05055       if (!e || e->exten[0] == '_') {
05056          return -1;
05057       }
05058    }
05059 
05060    /* Find the hint in the hints container */
05061    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05062    hint = ao2_find(hints, e, 0);
05063    if (!hint) {
05064       ao2_unlock(hints);
05065       return -1;
05066    }
05067 
05068    /* Now insert the callback in the callback list  */
05069    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05070       ao2_ref(hint, -1);
05071       ao2_unlock(hints);
05072       return -1;
05073    }
05074    do {
05075       id = stateid++;      /* Unique ID for this callback */
05076       /* Do not allow id to ever be -1 or 0. */
05077    } while (id == -1 || id == 0);
05078    state_cb->id = id;
05079    state_cb->change_cb = change_cb; /* Pointer to callback routine */
05080    state_cb->destroy_cb = destroy_cb;
05081    state_cb->data = data;     /* Data for the callback */
05082    ao2_link(hint->callbacks, state_cb);
05083 
05084    ao2_ref(state_cb, -1);
05085    ao2_ref(hint, -1);
05086    ao2_unlock(hints);
05087 
05088    return id;
05089 }

int ast_extension_state_del ( int  id,
ast_state_cb_type  change_cb 
)

ast_extension_state_del: Remove a watcher from the callback list

Deletes a registered state change callback by ID.

Definition at line 5114 of file pbx.c.

References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::callbacks, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.

Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().

05115 {
05116    struct ast_state_cb *p_cur;
05117    int ret = -1;
05118 
05119    if (!id) {  /* id == 0 is a callback without extension */
05120       if (!change_cb) {
05121          return ret;
05122       }
05123       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
05124       if (p_cur) {
05125          ret = 0;
05126          ao2_ref(p_cur, -1);
05127       }
05128    } else { /* callback with extension, find the callback based on ID */
05129       struct ast_hint *hint;
05130 
05131       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05132       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
05133       if (hint) {
05134          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
05135          if (p_cur) {
05136             ret = 0;
05137             ao2_ref(p_cur, -1);
05138          }
05139          ao2_ref(hint, -1);
05140       }
05141       ao2_unlock(hints);
05142    }
05143 
05144    return ret;
05145 }

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.

Parameters:
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
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Return values:
the priority which matches the given label in the extension
-1 if not found.

Definition at line 5358 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().

05359 {
05360    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05361 }

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.

Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
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 5363 of file pbx.c.

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

05364 {
05365    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05366 }

int ast_func_read ( struct ast_channel chan,
const char *  function,
char *  workspace,
size_t  len 
)

executes a read operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
workspace A pointer to safe memory to use for a return value
len the number of bytes in workspace

This application executes a function in read mode on a given channel.

Return values:
0 success
non-zero failure

Definition at line 4134 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.

Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().

04135 {
04136    char *copy = ast_strdupa(function);
04137    char *args = func_args(copy);
04138    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04139    int res;
04140    struct ast_module_user *u = NULL;
04141 
04142    if (acfptr == NULL) {
04143       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04144    } else if (!acfptr->read && !acfptr->read2) {
04145       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04146    } else if (!is_read_allowed(acfptr)) {
04147       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04148    } else if (acfptr->read) {
04149       if (acfptr->mod) {
04150          u = __ast_module_user_add(acfptr->mod, chan);
04151       }
04152       res = acfptr->read(chan, copy, args, workspace, len);
04153       if (acfptr->mod && u) {
04154          __ast_module_user_remove(acfptr->mod, u);
04155       }
04156       return res;
04157    } else {
04158       struct ast_str *str = ast_str_create(16);
04159       if (acfptr->mod) {
04160          u = __ast_module_user_add(acfptr->mod, chan);
04161       }
04162       res = acfptr->read2(chan, copy, args, &str, 0);
04163       if (acfptr->mod && u) {
04164          __ast_module_user_remove(acfptr->mod, u);
04165       }
04166       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
04167       ast_free(str);
04168       return res;
04169    }
04170    return -1;
04171 }

int ast_func_read2 ( struct ast_channel chan,
const char *  function,
struct ast_str **  str,
ssize_t  maxlen 
)

executes a read operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
str A dynamic string buffer into which to place the result.
maxlen <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit

This application executes a function in read mode on a given channel.

Return values:
0 success
non-zero failure

Definition at line 4173 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.

Referenced by append_channel_vars(), and ast_str_substitute_variables_full().

04174 {
04175    char *copy = ast_strdupa(function);
04176    char *args = func_args(copy);
04177    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04178    int res;
04179    struct ast_module_user *u = NULL;
04180 
04181    if (acfptr == NULL) {
04182       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04183    } else if (!acfptr->read && !acfptr->read2) {
04184       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04185    } else if (!is_read_allowed(acfptr)) {
04186       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04187    } else {
04188       if (acfptr->mod) {
04189          u = __ast_module_user_add(acfptr->mod, chan);
04190       }
04191       ast_str_reset(*str);
04192       if (acfptr->read2) {
04193          /* ast_str enabled */
04194          res = acfptr->read2(chan, copy, args, str, maxlen);
04195       } else {
04196          /* Legacy function pointer, allocate buffer for result */
04197          int maxsize = ast_str_size(*str);
04198          if (maxlen > -1) {
04199             if (maxlen == 0) {
04200                if (acfptr->read_max) {
04201                   maxsize = acfptr->read_max;
04202                } else {
04203                   maxsize = VAR_BUF_SIZE;
04204                }
04205             } else {
04206                maxsize = maxlen;
04207             }
04208             ast_str_make_space(str, maxsize);
04209          }
04210          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
04211       }
04212       if (acfptr->mod && u) {
04213          __ast_module_user_remove(acfptr->mod, u);
04214       }
04215       return res;
04216    }
04217    return -1;
04218 }

int ast_func_write ( struct ast_channel chan,
const char *  function,
const char *  value 
)

executes a write operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
value A value parameter to pass for writing

This application executes a function in write mode on a given channel.

Return values:
0 success
non-zero failure

Definition at line 4220 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), is_write_allowed(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.

Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

04221 {
04222    char *copy = ast_strdupa(function);
04223    char *args = func_args(copy);
04224    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04225 
04226    if (acfptr == NULL) {
04227       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04228    } else if (!acfptr->write) {
04229       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
04230    } else if (!is_write_allowed(acfptr)) {
04231       ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
04232    } else {
04233       int res;
04234       struct ast_module_user *u = NULL;
04235       if (acfptr->mod)
04236          u = __ast_module_user_add(acfptr->mod, chan);
04237       res = acfptr->write(chan, copy, args, value);
04238       if (acfptr->mod && u)
04239          __ast_module_user_remove(acfptr->mod, u);
04240       return res;
04241    }
04242 
04243    return -1;
04244 }

const char* ast_get_context_name ( struct ast_context con  ) 
const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 10939 of file pbx.c.

References ast_context::registrar.

Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().

10940 {
10941    return c ? c->registrar : NULL;
10942 }

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  ) 

Definition at line 10964 of file pbx.c.

References ast_exten::cidmatch.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().

10965 {
10966    return e ? e->cidmatch : NULL;
10967 }

struct ast_context* ast_get_extension_context ( struct ast_exten exten  )  [read]

Definition at line 10906 of file pbx.c.

References ast_exten::parent.

Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().

10907 {
10908    return exten ? exten->parent : NULL;
10909 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 10916 of file pbx.c.

References ast_exten::label.

Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().

10917 {
10918    return exten ? exten->label : NULL;
10919 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10959 of file pbx.c.

References ast_exten::matchcid.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().

10960 {
10961    return e ? e->matchcid : 0;
10962 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 
int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 10931 of file pbx.c.

References ast_exten::priority.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().

10932 {
10933    return exten ? exten->priority : -1;
10934 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10944 of file pbx.c.

References ast_exten::registrar.

Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().

10945 {
10946    return e ? e->registrar : NULL;
10947 }

int ast_get_hint ( char *  hint,
int  hintsize,
char *  name,
int  namesize,
struct ast_channel c,
const char *  context,
const char *  exten 
)

Get hint for channel.

If an extension hint exists, return non-zero.

Definition at line 5315 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().

05316 {
05317    struct ast_exten *e = ast_hint_extension(c, context, exten);
05318 
05319    if (e) {
05320       if (hint)
05321          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05322       if (name) {
05323          const char *tmp = ast_get_extension_app_data(e);
05324          if (tmp)
05325             ast_copy_string(name, tmp, namesize);
05326       }
05327       return -1;
05328    }
05329    return 0;
05330 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 
const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 10954 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().

10955 {
10956    return ip ? ip->registrar : NULL;
10957 }

const char* ast_get_include_name ( struct ast_include inc  ) 
const char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 10949 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().

10950 {
10951    return i ? i->registrar : NULL;
10952 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 10984 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().

10985 {
10986    return sw ? sw->data : NULL;
10987 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10989 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10990 {
10991    return sw->eval;
10992 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 10979 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().

10980 {
10981    return sw ? sw->name : NULL;
10982 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 10994 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().

10995 {
10996    return sw ? sw->registrar : NULL;
10997 }

int ast_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
Note:
This function will handle locking the channel as needed.

Definition at line 11089 of file pbx.c.

References __ast_goto_if_exists().

Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().

11090 {
11091    return __ast_goto_if_exists(chan, context, exten, priority, 0);
11092 }

int ast_hashtab_compare_contexts ( const void *  ah_a,
const void *  ah_b 
)

hashtable functions for contexts

Definition at line 1092 of file pbx.c.

References ast_context::name.

Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().

01093 {
01094    const struct ast_context *ac = ah_a;
01095    const struct ast_context *bc = ah_b;
01096    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01097       return 1;
01098    /* assume context names are registered in a string table! */
01099    return strcmp(ac->name, bc->name);
01100 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

Definition at line 1144 of file pbx.c.

References ast_hashtab_hash_string(), and ast_context::name.

Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().

01145 {
01146    const struct ast_context *ac = obj;
01147    return ast_hashtab_hash_string(ac->name);
01148 }

static struct ast_exten* ast_hint_extension ( struct ast_channel c,
const char *  context,
const char *  exten 
) [static, read]

Definition at line 4792 of file pbx.c.

References ast_hint_extension_nolock(), ast_rdlock_contexts(), and ast_unlock_contexts().

Referenced by ast_extension_state(), ast_extension_state_add_destroy(), ast_get_hint(), and ast_str_get_hint().

04793 {
04794    struct ast_exten *e;
04795    ast_rdlock_contexts();
04796    e = ast_hint_extension_nolock(c, context, exten);
04797    ast_unlock_contexts();
04798    return e;
04799 }

static struct ast_exten* ast_hint_extension_nolock ( struct ast_channel c,
const char *  context,
const char *  exten 
) [static, read]

Find hint for given extension in context.

Definition at line 4786 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().

04787 {
04788    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04789    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04790 }

int ast_ignore_pattern ( const char *  context,
const char *  pattern 
)

Checks to see if a number should be ignored.

Parameters:
context context to search within
pattern to check whether it should be ignored or not

Check if a number should be ignored with respect to dialtone cancellation.

Return values:
0 if the pattern should not be ignored
non-zero if the pattern should be ignored

Definition at line 8573 of file pbx.c.

References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.

Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), and skinny_ss().

08574 {
08575    struct ast_context *con = ast_context_find(context);
08576 
08577    if (con) {
08578       struct ast_ignorepat *pat;
08579 
08580       for (pat = con->ignorepats; pat; pat = pat->next) {
08581          if (ast_extension_match(pat->pattern, pattern))
08582             return 1;
08583       }
08584    }
08585 
08586    return 0;
08587 }

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).

Parameters:
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
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Returns:
If "exten" *could match* a valid extension in this context with some more digits, return non-zero. Does NOT return non-zero if this is an exact-match only. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

Definition at line 5373 of file pbx.c.

References E_MATCHMORE, and pbx_extension_helper().

Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().

05374 {
05375    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05376 }

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.

Parameters:
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 7870 of file pbx.c.

References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

07871 {
07872    double ft;
07873    struct ast_context *tmp;
07874    struct ast_context *oldcontextslist;
07875    struct ast_hashtab *oldtable;
07876    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07877    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07878    struct store_hint *saved_hint;
07879    struct ast_hint *hint;
07880    struct ast_exten *exten;
07881    int length;
07882    struct ast_state_cb *thiscb;
07883    struct ast_hashtab_iter *iter;
07884    struct ao2_iterator i;
07885    struct timeval begintime;
07886    struct timeval writelocktime;
07887    struct timeval endlocktime;
07888    struct timeval enddeltime;
07889 
07890    /*
07891     * It is very important that this function hold the hints
07892     * container lock _and_ the conlock during its operation; not
07893     * only do we need to ensure that the list of contexts and
07894     * extensions does not change, but also that no hint callbacks
07895     * (watchers) are added or removed during the merge/delete
07896     * process
07897     *
07898     * In addition, the locks _must_ be taken in this order, because
07899     * there are already other code paths that use this order
07900     */
07901 
07902    begintime = ast_tvnow();
07903    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07904    ast_wrlock_contexts();
07905    iter = ast_hashtab_start_traversal(contexts_table);
07906    while ((tmp = ast_hashtab_next(iter))) {
07907       context_merge(extcontexts, exttable, tmp, registrar);
07908    }
07909    ast_hashtab_end_traversal(iter);
07910 
07911    ao2_lock(hints);
07912    writelocktime = ast_tvnow();
07913 
07914    /* preserve all watchers for hints */
07915    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07916    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07917       if (ao2_container_count(hint->callbacks)) {
07918          ao2_lock(hint);
07919          if (!hint->exten) {
07920             /* The extension has already been destroyed. (Should never happen here) */
07921             ao2_unlock(hint);
07922             continue;
07923          }
07924 
07925          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07926             + sizeof(*saved_hint);
07927          if (!(saved_hint = ast_calloc(1, length))) {
07928             ao2_unlock(hint);
07929             continue;
07930          }
07931 
07932          /* This removes all the callbacks from the hint into saved_hint. */
07933          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07934             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07935             /*
07936              * We intentionally do not unref thiscb to account for the
07937              * non-ao2 reference in saved_hint->callbacks
07938              */
07939          }
07940 
07941          saved_hint->laststate = hint->laststate;
07942          saved_hint->context = saved_hint->data;
07943          strcpy(saved_hint->data, hint->exten->parent->name);
07944          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07945          strcpy(saved_hint->exten, hint->exten->exten);
07946          ao2_unlock(hint);
07947          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07948       }
07949    }
07950    ao2_iterator_destroy(&i);
07951 
07952    /* save the old table and list */
07953    oldtable = contexts_table;
07954    oldcontextslist = contexts;
07955 
07956    /* move in the new table and list */
07957    contexts_table = exttable;
07958    contexts = *extcontexts;
07959 
07960    /*
07961     * Restore the watchers for hints that can be found; notify
07962     * those that cannot be restored.
07963     */
07964    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07965       struct pbx_find_info q = { .stacklen = 0 };
07966 
07967       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07968          PRIORITY_HINT, NULL, "", E_MATCH);
07969       /*
07970        * If this is a pattern, dynamically create a new extension for this
07971        * particular match.  Note that this will only happen once for each
07972        * individual extension, because the pattern will no longer match first.
07973        */
07974       if (exten && exten->exten[0] == '_') {
07975          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
07976             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
07977             exten->registrar);
07978          /* rwlocks are not recursive locks */
07979          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
07980             saved_hint->exten);
07981       }
07982 
07983       /* Find the hint in the hints container */
07984       hint = exten ? ao2_find(hints, exten, 0) : NULL;
07985       if (!hint) {
07986          /*
07987           * Notify watchers of this removed hint later when we aren't
07988           * encumberd by so many locks.
07989           */
07990          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
07991       } else {
07992          ao2_lock(hint);
07993          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07994             ao2_link(hint->callbacks, thiscb);
07995             /* Ref that we added when putting into saved_hint->callbacks */
07996             ao2_ref(thiscb, -1);
07997          }
07998          hint->laststate = saved_hint->laststate;
07999          ao2_unlock(hint);
08000          ao2_ref(hint, -1);
08001          ast_free(saved_hint);
08002       }
08003    }
08004 
08005    ao2_unlock(hints);
08006    ast_unlock_contexts();
08007 
08008    /*
08009     * Notify watchers of all removed hints with the same lock
08010     * environment as handle_statechange().
08011     */
08012    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
08013       /* this hint has been removed, notify the watchers */
08014       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
08015          thiscb->change_cb(saved_hint->context, saved_hint->exten,
08016             AST_EXTENSION_REMOVED, thiscb->data);
08017          /* Ref that we added when putting into saved_hint->callbacks */
08018          ao2_ref(thiscb, -1);
08019       }
08020       ast_free(saved_hint);
08021    }
08022 
08023    ast_mutex_unlock(&context_merge_lock);
08024    endlocktime = ast_tvnow();
08025 
08026    /*
08027     * The old list and hashtab no longer are relevant, delete them
08028     * while the rest of asterisk is now freely using the new stuff
08029     * instead.
08030     */
08031 
08032    ast_hashtab_destroy(oldtable, NULL);
08033 
08034    for (tmp = oldcontextslist; tmp; ) {
08035       struct ast_context *next;  /* next starting point */
08036 
08037       next = tmp->next;
08038       __ast_internal_context_destroy(tmp);
08039       tmp = next;
08040    }
08041    enddeltime = ast_tvnow();
08042 
08043    ft = ast_tvdiff_us(writelocktime, begintime);
08044    ft /= 1000000.0;
08045    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
08046 
08047    ft = ast_tvdiff_us(endlocktime, writelocktime);
08048    ft /= 1000000.0;
08049    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
08050 
08051    ft = ast_tvdiff_us(enddeltime, endlocktime);
08052    ft /= 1000000.0;
08053    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
08054 
08055    ft = ast_tvdiff_us(enddeltime, begintime);
08056    ft /= 1000000.0;
08057    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
08058 }

int ast_parseable_goto ( struct ast_channel chan,
const char *  goto_string 
)
Note:
This function will handle locking the channel as needed.

Definition at line 11154 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().

11155 {
11156    return pbx_parseable_goto(chan, goto_string, 0);
11157 }

int ast_pbx_init ( void   ) 

Provided by pbx.c

Definition at line 11235 of file pbx.c.

References ao2_container_alloc, ast_register_atexit(), HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hints, pbx_shutdown(), statecbs, and statecbs_cmp().

Referenced by main().

11236 {
11237    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
11238    statecbs = ao2_container_alloc(1, NULL, statecbs_cmp);
11239 
11240    ast_register_atexit(pbx_shutdown);
11241 
11242    return (hints && statecbs) ? 0 : -1;
11243 }

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 9467 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.

Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().

09468 {
09469    struct ast_channel *chan;
09470    struct app_tmp *tmp;
09471    int res = -1, cdr_res = -1;
09472    struct outgoing_helper oh;
09473 
09474    memset(&oh, 0, sizeof(oh));
09475    oh.vars = vars;
09476    oh.account = account;
09477 
09478    if (locked_channel)
09479       *locked_channel = NULL;
09480    if (ast_strlen_zero(app)) {
09481       res = -1;
09482       goto outgoing_app_cleanup;
09483    }
09484    if (synchronous) {
09485       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09486       if (chan) {
09487          ast_set_variables(chan, vars);
09488          if (account)
09489             ast_cdr_setaccount(chan, account);
09490          if (chan->_state == AST_STATE_UP) {
09491             res = 0;
09492             ast_verb(4, "Channel %s was answered.\n", chan->name);
09493             tmp = ast_calloc(1, sizeof(*tmp));
09494             if (!tmp || ast_string_field_init(tmp, 252)) {
09495                if (tmp) {
09496                   ast_free(tmp);
09497                }
09498                res = -1;
09499             } else {
09500                ast_string_field_set(tmp, app, app);
09501                ast_string_field_set(tmp, data, appdata);
09502                tmp->chan = chan;
09503                if (synchronous > 1) {
09504                   if (locked_channel)
09505                      ast_channel_unlock(chan);
09506                   ast_pbx_run_app(tmp);
09507                } else {
09508                   if (locked_channel)
09509                      ast_channel_lock(chan);
09510                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09511                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
09512                      ast_string_field_free_memory(tmp);
09513                      ast_free(tmp);
09514                      if (locked_channel)
09515                         ast_channel_unlock(chan);
09516                      ast_hangup(chan);
09517                      res = -1;
09518                   } else {
09519                      if (locked_channel)
09520                         *locked_channel = chan;
09521                   }
09522                }
09523             }
09524          } else {
09525             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09526             if (chan->cdr) { /* update the cdr */
09527                /* here we update the status of the call, which sould be busy.
09528                 * if that fails then we set the status to failed */
09529                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09530                   ast_cdr_failed(chan->cdr);
09531             }
09532             ast_hangup(chan);
09533          }
09534       }
09535 
09536       if (res < 0) { /* the call failed for some reason */
09537          if (*reason == 0) { /* if the call failed (not busy or no answer)
09538                         * update the cdr with the failed message */
09539             cdr_res = ast_pbx_outgoing_cdr_failed();
09540             if (cdr_res != 0) {
09541                res = cdr_res;
09542                goto outgoing_app_cleanup;
09543             }
09544          }
09545       }
09546 
09547    } else {
09548       struct async_stat *as;
09549       if (!(as = ast_calloc(1, sizeof(*as)))) {
09550          res = -1;
09551          goto outgoing_app_cleanup;
09552       }
09553       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09554       if (!chan) {
09555          ast_free(as);
09556          res = -1;
09557          goto outgoing_app_cleanup;
09558       }
09559       as->chan = chan;
09560       ast_copy_string(as->app, app, sizeof(as->app));
09561       if (appdata)
09562          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09563       as->timeout = timeout;
09564       ast_set_variables(chan, vars);
09565       if (account)
09566          ast_cdr_setaccount(chan, account);
09567       /* Start a new thread, and get something handling this channel. */
09568       if (locked_channel)
09569          ast_channel_lock(chan);
09570       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09571          ast_log(LOG_WARNING, "Failed to start async wait\n");
09572          ast_free(as);
09573          if (locked_channel)
09574             ast_channel_unlock(chan);
09575          ast_hangup(chan);
09576          res = -1;
09577          goto outgoing_app_cleanup;
09578       } else {
09579          if (locked_channel)
09580             *locked_channel = chan;
09581       }
09582       res = 0;
09583    }
09584 outgoing_app_cleanup:
09585    ast_variables_destroy(vars);
09586    return res;
09587 }

static int ast_pbx_outgoing_cdr_failed ( void   )  [static]

Function to post an empty cdr after a spool call fails.

Note:
This function posts an empty cdr for a failed spool call

Definition at line 9271 of file pbx.c.

References ast_cdr_alloc(), ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_unref, ast_dummy_channel_alloc, and ast_channel::cdr.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

09272 {
09273    /* allocate a channel */
09274    struct ast_channel *chan = ast_dummy_channel_alloc();
09275 
09276    if (!chan)
09277       return -1;  /* failure */
09278 
09279    chan->cdr = ast_cdr_alloc();
09280    if (!chan->cdr) {
09281       /* allocation of the cdr failed */
09282       chan = ast_channel_unref(chan);   /* free the channel */
09283       return -1;                /* return failure */
09284    }
09285 
09286    /* allocation of the cdr was successful */
09287    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
09288    ast_cdr_start(chan->cdr);       /* record the start and stop time */
09289    ast_cdr_end(chan->cdr);
09290    ast_cdr_failed(chan->cdr);      /* set the status to failed */
09291    ast_cdr_detach(chan->cdr);      /* post and free the record */
09292    chan->cdr = NULL;
09293    chan = ast_channel_unref(chan);         /* free the channel */
09294 
09295    return 0;  /* success */
09296 }

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 9298 of file pbx.c.

References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.

Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().

09299 {
09300    struct ast_channel *chan;
09301    struct async_stat *as;
09302    int res = -1, cdr_res = -1;
09303    struct outgoing_helper oh;
09304 
09305    if (synchronous) {
09306       oh.context = context;
09307       oh.exten = exten;
09308       oh.priority = priority;
09309       oh.cid_num = cid_num;
09310       oh.cid_name = cid_name;
09311       oh.account = account;
09312       oh.vars = vars;
09313       oh.parent_channel = NULL;
09314 
09315       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09316       if (channel) {
09317          *channel = chan;
09318          if (chan)
09319             ast_channel_lock(chan);
09320       }
09321       if (chan) {
09322          if (chan->_state == AST_STATE_UP) {
09323                res = 0;
09324             ast_verb(4, "Channel %s was answered.\n", chan->name);
09325 
09326             if (synchronous > 1) {
09327                if (channel)
09328                   ast_channel_unlock(chan);
09329                if (ast_pbx_run(chan)) {
09330                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09331                   if (channel)
09332                      *channel = NULL;
09333                   ast_hangup(chan);
09334                   chan = NULL;
09335                   res = -1;
09336                }
09337             } else {
09338                if (ast_pbx_start(chan)) {
09339                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
09340                   if (channel) {
09341                      *channel = NULL;
09342                      ast_channel_unlock(chan);
09343                   }
09344                   ast_hangup(chan);
09345                   res = -1;
09346                }
09347                chan = NULL;
09348             }
09349          } else {
09350             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09351 
09352             if (chan->cdr) { /* update the cdr */
09353                /* here we update the status of the call, which sould be busy.
09354                 * if that fails then we set the status to failed */
09355                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09356                   ast_cdr_failed(chan->cdr);
09357             }
09358 
09359             if (channel) {
09360                *channel = NULL;
09361                ast_channel_unlock(chan);
09362             }
09363             ast_hangup(chan);
09364             chan = NULL;
09365          }
09366       }
09367 
09368       if (res < 0) { /* the call failed for some reason */
09369          if (*reason == 0) { /* if the call failed (not busy or no answer)
09370                         * update the cdr with the failed message */
09371             cdr_res = ast_pbx_outgoing_cdr_failed();
09372             if (cdr_res != 0) {
09373                res = cdr_res;
09374                goto outgoing_exten_cleanup;
09375             }
09376          }
09377 
09378          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
09379          /* check if "failed" exists */
09380          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
09381             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
09382             if (chan) {
09383                char failed_reason[4] = "";
09384                if (!ast_strlen_zero(context))
09385                   ast_copy_string(chan->context, context, sizeof(chan->context));
09386                set_ext_pri(chan, "failed", 1);
09387                ast_set_variables(chan, vars);
09388                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
09389                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
09390                if (account)
09391                   ast_cdr_setaccount(chan, account);
09392                if (ast_pbx_run(chan)) {
09393                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09394                   ast_hangup(chan);
09395                }
09396                chan = NULL;
09397             }
09398          }
09399       }
09400    } else {
09401       if (!(as = ast_calloc(1, sizeof(*as)))) {
09402          res = -1;
09403          goto outgoing_exten_cleanup;
09404       }
09405       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
09406       if (channel) {
09407          *channel = chan;
09408          if (chan)
09409             ast_channel_lock(chan);
09410       }
09411       if (!chan) {
09412          ast_free(as);
09413          res = -1;
09414          goto outgoing_exten_cleanup;
09415       }
09416       as->chan = chan;
09417       ast_copy_string(as->context, context, sizeof(as->context));
09418       set_ext_pri(as->chan,  exten, priority);
09419       as->timeout = timeout;
09420       ast_set_variables(chan, vars);
09421       if (account)
09422          ast_cdr_setaccount(chan, account);
09423       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09424          ast_log(LOG_WARNING, "Failed to start async wait\n");
09425          ast_free(as);
09426          if (channel) {
09427             *channel = NULL;
09428             ast_channel_unlock(chan);
09429          }
09430          ast_hangup(chan);
09431          res = -1;
09432          goto outgoing_exten_cleanup;
09433       }
09434       res = 0;
09435    }
09436 outgoing_exten_cleanup:
09437    ast_variables_destroy(vars);
09438    return res;
09439 }

enum ast_pbx_result ast_pbx_run ( struct ast_channel c  ) 

Execute the PBX in the current thread.

Parameters:
c channel to run the pbx on

This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.

Return values:
Zero on success
non-zero on failure

Definition at line 5879 of file pbx.c.

References ast_pbx_run_args().

Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_notify(), mgcp_ss(), skinny_newcall(), and unistim_ss().

05880 {
05881    return ast_pbx_run_args(c, NULL);
05882 }

static void* ast_pbx_run_app ( void *  data  )  [static]

run the application and free the descriptor once done

Definition at line 9451 of file pbx.c.

References app_tmp::app, ast_free, ast_hangup(), ast_log(), ast_string_field_free_memory, ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, pbx_exec(), and pbx_findapp().

Referenced by ast_pbx_outgoing_app().

09452 {
09453    struct app_tmp *tmp = data;
09454    struct ast_app *app;
09455    app = pbx_findapp(tmp->app);
09456    if (app) {
09457       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
09458       pbx_exec(tmp->chan, app, tmp->data);
09459    } else
09460       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
09461    ast_hangup(tmp->chan);
09462    ast_string_field_free_memory(tmp);
09463    ast_free(tmp);
09464    return NULL;
09465 }

enum ast_pbx_result ast_pbx_run_args ( struct ast_channel c,
struct ast_pbx_args args 
)

Execute the PBX in the current thread.

Parameters:
c channel to run the pbx on
args options for the pbx

This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.

Return values:
Zero on success
non-zero on failure

Definition at line 5859 of file pbx.c.

References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.

Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().

05860 {
05861    enum ast_pbx_result res = AST_PBX_SUCCESS;
05862 
05863    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05864       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05865       return AST_PBX_FAILED;
05866    }
05867 
05868    if (increase_call_count(c)) {
05869       return AST_PBX_CALL_LIMIT;
05870    }
05871 
05872    res = __ast_pbx_run(c, args);
05873 
05874    decrease_call_count();
05875 
05876    return res;
05877 }

enum ast_pbx_result ast_pbx_start ( struct ast_channel c  ) 

Create a new thread and start the PBX.

Parameters:
c channel to start the pbx on
See also:
ast_pbx_run for a synchronous function to run the PBX in the current thread, as opposed to starting a new one.
Return values:
Zero on success
non-zero on failure

Definition at line 5832 of file pbx.c.

References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().

Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), skinny_new(), and unistim_new().

05833 {
05834    pthread_t t;
05835 
05836    if (!c) {
05837       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05838       return AST_PBX_FAILED;
05839    }
05840 
05841    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05842       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05843       return AST_PBX_FAILED;
05844    }
05845 
05846    if (increase_call_count(c))
05847       return AST_PBX_CALL_LIMIT;
05848 
05849    /* Start a new thread, and get something handling this channel. */
05850    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05851       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05852       decrease_call_count();
05853       return AST_PBX_FAILED;
05854    }
05855 
05856    return AST_PBX_SUCCESS;
05857 }

int ast_processed_calls ( void   ) 

Retrieve the total number of calls processed through the PBX since last restart.

Definition at line 5889 of file pbx.c.

References totalcalls.

Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().

05890 {
05891    return totalcalls;
05892 }

int ast_rdlock_context ( struct ast_context con  ) 

Read locks a given context.

Parameters:
con context to lock
Return values:
0 on success
-1 on failure

Definition at line 10888 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().

10889 {
10890    return ast_rwlock_rdlock(&con->lock);
10891 }

int ast_rdlock_contexts ( void   ) 
int ast_register_application2 ( const char *  app,
int(*)(struct ast_channel *, const char *)  execute,
const char *  synopsis,
const char *  description,
void *  mod 
)

Dynamically register a new dial plan application.

Register an application.

Definition at line 6297 of file pbx.c.

References ast_app::arguments, ast_calloc, ast_free, ast_log(), ast_module_name(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_verb, AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), COLOR_BRCYAN, ast_app::docsrc, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, ast_app::seealso, ast_app::syntax, and term_color().

Referenced by ast_cc_init(), ast_features_init(), and load_pbx().

06298 {
06299    struct ast_app *tmp, *cur = NULL;
06300    char tmps[80];
06301    int length, res;
06302 #ifdef AST_XML_DOCS
06303    char *tmpxml;
06304 #endif
06305 
06306    AST_RWLIST_WRLOCK(&apps);
06307    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
06308       if (!(res = strcasecmp(app, tmp->name))) {
06309          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
06310          AST_RWLIST_UNLOCK(&apps);
06311          return -1;
06312       } else if (res < 0)
06313          break;
06314    }
06315 
06316    length = sizeof(*tmp) + strlen(app) + 1;
06317 
06318    if (!(tmp = ast_calloc(1, length))) {
06319       AST_RWLIST_UNLOCK(&apps);
06320       return -1;
06321    }
06322 
06323    if (ast_string_field_init(tmp, 128)) {
06324       AST_RWLIST_UNLOCK(&apps);
06325       ast_free(tmp);
06326       return -1;
06327    }
06328 
06329    strcpy(tmp->name, app);
06330    tmp->execute = execute;
06331    tmp->module = mod;
06332 
06333 #ifdef AST_XML_DOCS
06334    /* Try to lookup the docs in our XML documentation database */
06335    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
06336       /* load synopsis */
06337       tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
06338       ast_string_field_set(tmp, synopsis, tmpxml);
06339       ast_free(tmpxml);
06340 
06341       /* load description */
06342       tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
06343       ast_string_field_set(tmp, description, tmpxml);
06344       ast_free(tmpxml);
06345 
06346       /* load syntax */
06347       tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
06348       ast_string_field_set(tmp, syntax, tmpxml);
06349       ast_free(tmpxml);
06350 
06351       /* load arguments */
06352       tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
06353       ast_string_field_set(tmp, arguments, tmpxml);
06354       ast_free(tmpxml);
06355 
06356       /* load seealso */
06357       tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
06358       ast_string_field_set(tmp, seealso, tmpxml);
06359       ast_free(tmpxml);
06360       tmp->docsrc = AST_XML_DOC;
06361    } else {
06362 #endif
06363       ast_string_field_set(tmp, synopsis, synopsis);
06364       ast_string_field_set(tmp, description, description);
06365 #ifdef AST_XML_DOCS
06366       tmp->docsrc = AST_STATIC_DOC;
06367    }
06368 #endif
06369 
06370    /* Store in alphabetical order */
06371    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
06372       if (strcasecmp(tmp->name, cur->name) < 0) {
06373          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
06374          break;
06375       }
06376    }
06377    AST_RWLIST_TRAVERSE_SAFE_END;
06378    if (!cur)
06379       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
06380 
06381    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
06382 
06383    AST_RWLIST_UNLOCK(&apps);
06384 
06385    return 0;
06386 }

int ast_register_switch ( struct ast_switch sw  ) 

Register an alternative dialplan switch.

Parameters:
sw switch to register

This function registers a populated ast_switch structure with the asterisk switching architecture.

Return values:
0 success
non-zero failure

Definition at line 6392 of file pbx.c.

References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, and ast_switch::name.

Referenced by load_module().

06393 {
06394    struct ast_switch *tmp;
06395 
06396    AST_RWLIST_WRLOCK(&switches);
06397    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
06398       if (!strcasecmp(tmp->name, sw->name)) {
06399          AST_RWLIST_UNLOCK(&switches);
06400          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
06401          return -1;
06402       }
06403    }
06404    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
06405    AST_RWLIST_UNLOCK(&switches);
06406 
06407    return 0;
06408 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

Definition at line 5194 of file pbx.c.

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::context_name, ast_hint::exten, ast_hint::exten_name, hints, and OBJ_UNLINK.

Referenced by destroy_exten().

05195 {
05196    /* Cleanup the Notifys if hint is removed */
05197    struct ast_hint *hint;
05198 
05199    if (!e) {
05200       return -1;
05201    }
05202 
05203    hint = ao2_find(hints, e, OBJ_UNLINK);
05204    if (!hint) {
05205       return -1;
05206    }
05207 
05208    /*
05209     * The extension is being destroyed so we must save some
05210     * information to notify that the extension is deactivated.
05211     */
05212    ao2_lock(hint);
05213    ast_copy_string(hint->context_name,
05214       ast_get_context_name(ast_get_extension_context(hint->exten)),
05215       sizeof(hint->context_name));
05216    ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten),
05217       sizeof(hint->exten_name));
05218    hint->exten = NULL;
05219    ao2_unlock(hint);
05220 
05221    ao2_ref(hint, -1);
05222 
05223    return 0;
05224 }

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).

Parameters:
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.
Note:
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Return values:
0 on success
-1 on failure.

Definition at line 5378 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().

05379 {
05380    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05381 }

int ast_str_get_hint ( struct ast_str **  hint,
ssize_t  hintsize,
struct ast_str **  name,
ssize_t  namesize,
struct ast_channel c,
const char *  context,
const char *  exten 
)

Get hint for channel.

If an extension hint exists, return non-zero.

Definition at line 5333 of file pbx.c.

References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and ast_str_set().

Referenced by ast_str_retrieve_variable().

05334 {
05335    struct ast_exten *e = ast_hint_extension(c, context, exten);
05336 
05337    if (!e) {
05338       return 0;
05339    }
05340 
05341    if (hint) {
05342       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05343    }
05344    if (name) {
05345       const char *tmp = ast_get_extension_app_data(e);
05346       if (tmp) {
05347          ast_str_set(name, namesize, "%s", tmp);
05348       }
05349    }
05350    return -1;
05351 }

const char* ast_str_retrieve_variable ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel chan,
struct varshead *  headp,
const char *  var 
)
Parameters:
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 3403 of file pbx.c.

References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.

Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().

03404 {
03405    const char not_found = '\0';
03406    char *tmpvar;
03407    const char *ret;
03408    const char *s; /* the result */
03409    int offset, length;
03410    int i, need_substring;
03411    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03412    char workspace[20];
03413 
03414    if (c) {
03415       ast_channel_lock(c);
03416       places[0] = &c->varshead;
03417    }
03418    /*
03419     * Make a copy of var because parse_variable_name() modifies the string.
03420     * Then if called directly, we might need to run substring() on the result;
03421     * remember this for later in 'need_substring', 'offset' and 'length'
03422     */
03423    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03424    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03425 
03426    /*
03427     * Look first into predefined variables, then into variable lists.
03428     * Variable 's' points to the result, according to the following rules:
03429     * s == &not_found (set at the beginning) means that we did not find a
03430     * matching variable and need to look into more places.
03431     * If s != &not_found, s is a valid result string as follows:
03432     * s = NULL if the variable does not have a value;
03433     * you typically do this when looking for an unset predefined variable.
03434     * s = workspace if the result has been assembled there;
03435     * typically done when the result is built e.g. with an snprintf(),
03436     * so we don't need to do an additional copy.
03437     * s != workspace in case we have a string, that needs to be copied
03438     * (the ast_copy_string is done once for all at the end).
03439     * Typically done when the result is already available in some string.
03440     */
03441    s = &not_found;   /* default value */
03442    if (c) { /* This group requires a valid channel */
03443       /* Names with common parts are looked up a piece at a time using strncmp. */
03444       if (!strncmp(var, "CALL", 4)) {
03445          if (!strncmp(var + 4, "ING", 3)) {
03446             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03447                ast_str_set(str, maxlen, "%d",
03448                   ast_party_id_presentation(&c->caller.id));
03449                s = ast_str_buffer(*str);
03450             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03451                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03452                s = ast_str_buffer(*str);
03453             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03454                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03455                s = ast_str_buffer(*str);
03456             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03457                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03458                s = ast_str_buffer(*str);
03459             }
03460          }
03461       } else if (!strcmp(var, "HINT")) {
03462          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03463       } else if (!strcmp(var, "HINTNAME")) {
03464          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03465       } else if (!strcmp(var, "EXTEN")) {
03466          s = c->exten;
03467       } else if (!strcmp(var, "CONTEXT")) {
03468          s = c->context;
03469       } else if (!strcmp(var, "PRIORITY")) {
03470          ast_str_set(str, maxlen, "%d", c->priority);
03471          s = ast_str_buffer(*str);
03472       } else if (!strcmp(var, "CHANNEL")) {
03473          s = c->name;
03474       } else if (!strcmp(var, "UNIQUEID")) {
03475          s = c->uniqueid;
03476       } else if (!strcmp(var, "HANGUPCAUSE")) {
03477          ast_str_set(str, maxlen, "%d", c->hangupcause);
03478          s = ast_str_buffer(*str);
03479       }
03480    }
03481    if (s == &not_found) { /* look for more */
03482       if (!strcmp(var, "EPOCH")) {
03483          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03484          s = ast_str_buffer(*str);
03485       } else if (!strcmp(var, "SYSTEMNAME")) {
03486          s = ast_config_AST_SYSTEM_NAME;
03487       } else if (!strcmp(var, "ENTITYID")) {
03488          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03489          s = workspace;
03490       }
03491    }
03492    /* if not found, look into chanvars or global vars */
03493    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03494       struct ast_var_t *variables;
03495       if (!places[i])
03496          continue;
03497       if (places[i] == &globals)
03498          ast_rwlock_rdlock(&globalslock);
03499       AST_LIST_TRAVERSE(places[i], variables, entries) {
03500          if (!strcasecmp(ast_var_name(variables), var)) {
03501             s = ast_var_value(variables);
03502             break;
03503          }
03504       }
03505       if (places[i] == &globals)
03506          ast_rwlock_unlock(&globalslock);
03507    }
03508    if (s == &not_found || s == NULL) {
03509       ast_debug(5, "Result of '%s' is NULL\n", var);
03510       ret = NULL;
03511    } else {
03512       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03513       if (s != ast_str_buffer(*str)) {
03514          ast_str_set(str, maxlen, "%s", s);
03515       }
03516       ret = ast_str_buffer(*str);
03517       if (need_substring) {
03518          ret = ast_str_substring(*str, offset, length);
03519          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03520       }
03521    }
03522 
03523    if (c) {
03524       ast_channel_unlock(c);
03525    }
03526    return ret;
03527 }

void ast_str_substitute_variables ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel chan,
const char *  templ 
)
Parameters:
buf Result will be placed in this buffer.
maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
chan Channel variables from which to extract values, and channel to pass to any dialplan functions.
templ Variable template to expand.

Definition at line 4425 of file pbx.c.

References ast_str_substitute_variables_full().

Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().

04426 {
04427    size_t used;
04428    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04429 }

void ast_str_substitute_variables_full ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel c,
struct varshead *  headp,
const char *  templ,
size_t *  used 
)
Parameters:
buf Result will be placed in this buffer.
maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
c Channel variables from which to extract values, and channel to pass to any dialplan functions.
headp If no channel is specified, a channel list from which to extract variable values
templ Variable template to expand.
used Number of bytes read from the template.

Definition at line 4246 of file pbx.c.

References ast_channel_unref, ast_debug, ast_dummy_channel_alloc, ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.

Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().

04247 {
04248    /* Substitutes variables into buf, based on string templ */
04249    char *cp4 = NULL;
04250    const char *tmp, *whereweare;
04251    int orig_size = 0;
04252    int offset, offset2, isfunction;
04253    const char *nextvar, *nextexp, *nextthing;
04254    const char *vars, *vare;
04255    char *finalvars;
04256    int pos, brackets, needsub, len;
04257    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
04258 
04259    ast_str_reset(*buf);
04260    whereweare = tmp = templ;
04261    while (!ast_strlen_zero(whereweare)) {
04262       /* reset our buffer */
04263       ast_str_reset(substr3);
04264 
04265       /* Assume we're copying the whole remaining string */
04266       pos = strlen(whereweare);
04267       nextvar = NULL;
04268       nextexp = NULL;
04269       nextthing = strchr(whereweare, '$');
04270       if (nextthing) {
04271          switch (nextthing[1]) {
04272          case '{':
04273             nextvar = nextthing;
04274             pos = nextvar - whereweare;
04275             break;
04276          case '[':
04277             nextexp = nextthing;
04278             pos = nextexp - whereweare;
04279             break;
04280          default:
04281             pos = 1;
04282          }
04283       }
04284 
04285       if (pos) {
04286          /* Copy that many bytes */
04287          ast_str_append_substr(buf, maxlen, whereweare, pos);
04288 
04289          templ += pos;
04290          whereweare += pos;
04291       }
04292 
04293       if (nextvar) {
04294          /* We have a variable.  Find the start and end, and determine
04295             if we are going to have to recursively call ourselves on the
04296             contents */
04297          vars = vare = nextvar + 2;
04298          brackets = 1;
04299          needsub = 0;
04300 
04301          /* Find the end of it */
04302          while (brackets && *vare) {
04303             if ((vare[0] == '$') && (vare[1] == '{')) {
04304                needsub++;
04305             } else if (vare[0] == '{') {
04306                brackets++;
04307             } else if (vare[0] == '}') {
04308                brackets--;
04309             } else if ((vare[0] == '$') && (vare[1] == '['))
04310                needsub++;
04311             vare++;
04312          }
04313          if (brackets)
04314             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04315          len = vare - vars - 1;
04316 
04317          /* Skip totally over variable string */
04318          whereweare += (len + 3);
04319 
04320          /* Store variable name (and truncate) */
04321          ast_str_set_substr(&substr1, 0, vars, len);
04322          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
04323 
04324          /* Substitute if necessary */
04325          if (needsub) {
04326             size_t used;
04327             if (!substr2) {
04328                substr2 = ast_str_create(16);
04329             }
04330 
04331             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04332             finalvars = ast_str_buffer(substr2);
04333          } else {
04334             finalvars = ast_str_buffer(substr1);
04335          }
04336 
04337          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
04338          if (isfunction) {
04339             /* Evaluate function */
04340             if (c || !headp) {
04341                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04342             } else {
04343                struct varshead old;
04344                struct ast_channel *bogus = ast_dummy_channel_alloc();
04345                if (bogus) {
04346                   memcpy(&old, &bogus->varshead, sizeof(old));
04347                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
04348                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04349                   /* Don't deallocate the varshead that was passed in */
04350                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
04351                   ast_channel_unref(bogus);
04352                } else {
04353                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04354                }
04355             }
04356             ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)");
04357          } else {
04358             /* Retrieve variable value */
04359             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04360             cp4 = ast_str_buffer(substr3);
04361          }
04362          if (cp4) {
04363             ast_str_substring(substr3, offset, offset2);
04364             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04365          }
04366       } else if (nextexp) {
04367          /* We have an expression.  Find the start and end, and determine
04368             if we are going to have to recursively call ourselves on the
04369             contents */
04370          vars = vare = nextexp + 2;
04371          brackets = 1;
04372          needsub = 0;
04373 
04374          /* Find the end of it */
04375          while (brackets && *vare) {
04376             if ((vare[0] == '$') && (vare[1] == '[')) {
04377                needsub++;
04378                brackets++;
04379                vare++;
04380             } else if (vare[0] == '[') {
04381                brackets++;
04382             } else if (vare[0] == ']') {
04383                brackets--;
04384             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04385                needsub++;
04386                vare++;
04387             }
04388             vare++;
04389          }
04390          if (brackets)
04391             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04392          len = vare - vars - 1;
04393 
04394          /* Skip totally over expression */
04395          whereweare += (len + 3);
04396 
04397          /* Store variable name (and truncate) */
04398          ast_str_set_substr(&substr1, 0, vars, len);
04399 
04400          /* Substitute if necessary */
04401          if (needsub) {
04402             size_t used;
04403             if (!substr2) {
04404                substr2 = ast_str_create(16);
04405             }
04406 
04407             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04408             finalvars = ast_str_buffer(substr2);
04409          } else {
04410             finalvars = ast_str_buffer(substr1);
04411          }
04412 
04413          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04414             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04415          }
04416          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04417       }
04418    }
04419    *used = ast_str_strlen(*buf) - orig_size;
04420    ast_free(substr1);
04421    ast_free(substr2);
04422    ast_free(substr3);
04423 }

void ast_str_substitute_variables_varshead ( struct ast_str **  buf,
ssize_t  maxlen,
struct varshead *  headp,
const char *  templ 
)
Parameters:
buf Result will be placed in this buffer.
maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
headp If no channel is specified, a channel list from which to extract variable values
templ Variable template to expand.

Definition at line 4431 of file pbx.c.

References ast_str_substitute_variables_full().

Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().

04432 {
04433    size_t used;
04434    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04435 }

static const char* ast_str_substring ( struct ast_str value,
int  offset,
int  length 
) [static]

Definition at line 3338 of file pbx.c.

References ast_str_buffer(), ast_str_reset(), ast_str_strlen(), and ast_str_update().

Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().

03339 {
03340    int lr;  /* length of the input string after the copy */
03341 
03342    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
03343 
03344    /* Quick check if no need to do anything */
03345    if (offset == 0 && length >= lr) /* take the whole string */
03346       return ast_str_buffer(value);
03347 
03348    if (offset < 0)   {  /* translate negative offset into positive ones */
03349       offset = lr + offset;
03350       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03351          offset = 0;
03352    }
03353 
03354    /* too large offset result in empty string so we know what to return */
03355    if (offset >= lr) {
03356       ast_str_reset(value);
03357       return ast_str_buffer(value);
03358    }
03359 
03360    if (offset > 0) {
03361       /* Go ahead and chop off the beginning */
03362       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
03363       lr -= offset;
03364    }
03365 
03366    if (length >= 0 && length < lr) {   /* truncate if necessary */
03367       char *tmp = ast_str_buffer(value);
03368       tmp[length] = '\0';
03369       ast_str_update(value);
03370    } else if (length < 0) {
03371       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
03372          char *tmp = ast_str_buffer(value);
03373          tmp[lr + length] = '\0';
03374          ast_str_update(value);
03375       } else {
03376          ast_str_reset(value);
03377       }
03378    } else {
03379       /* Nothing to do, but update the buffer length */
03380       ast_str_update(value);
03381    }
03382 
03383    return ast_str_buffer(value);
03384 }

int ast_thread_inhibit_escalations ( void   ) 

Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.

Returns:
0 if successfuly marked current thread.
Non-zero if marking current thread failed.

Definition at line 4029 of file pbx.c.

References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.

Referenced by handle_tcptls_connection().

04030 {
04031    int *thread_inhibit_escalations;
04032 
04033    thread_inhibit_escalations = ast_threadstorage_get(
04034       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04035 
04036    if (thread_inhibit_escalations == NULL) {
04037       ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
04038       return -1;
04039    }
04040 
04041    *thread_inhibit_escalations = 1;
04042    return 0;
04043 }

int ast_unlock_context ( struct ast_context con  ) 
int ast_unlock_contexts ( void   ) 
int ast_unregister_application ( const char *  app  ) 

Unregister an application.

Parameters:
app name of the application (does not have to be the same string as the one that was registered)

This unregisters an application from Asterisk's internal application list.

Return values:
0 success
-1 failure

Definition at line 7643 of file pbx.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, ast_app::name, and unreference_cached_app().

Referenced by __unload_module(), cc_shutdown(), features_shutdown(), load_module(), unload_module(), and unload_pbx().

07644 {
07645    struct ast_app *tmp;
07646 
07647    AST_RWLIST_WRLOCK(&apps);
07648    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
07649       if (!strcasecmp(app, tmp->name)) {
07650          unreference_cached_app(tmp);
07651          AST_RWLIST_REMOVE_CURRENT(list);
07652          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
07653          ast_string_field_free_memory(tmp);
07654          ast_free(tmp);
07655          break;
07656       }
07657    }
07658    AST_RWLIST_TRAVERSE_SAFE_END;
07659    AST_RWLIST_UNLOCK(&apps);
07660 
07661    return tmp ? 0 : -1;
07662 }

void ast_unregister_switch ( struct ast_switch sw  ) 

Unregister an alternative switch.

Parameters:
sw switch to unregister

Unregisters a switch from asterisk.

Returns:
nothing

Definition at line 6410 of file pbx.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

06411 {
06412    AST_RWLIST_WRLOCK(&switches);
06413    AST_RWLIST_REMOVE(&switches, sw, list);
06414    AST_RWLIST_UNLOCK(&switches);
06415 }

struct ast_exten* ast_walk_context_extensions ( struct ast_context con,
struct ast_exten exten 
) [read]

Definition at line 11007 of file pbx.c.

References ast_exten::next, and ast_context::root.

Referenced by complete_dialplan_remove_extension(), context_used(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().

11009 {
11010    if (!exten)
11011       return con ? con->root : NULL;
11012    else
11013       return exten->next;
11014 }

struct ast_ignorepat* ast_walk_context_ignorepats ( struct ast_context con,
struct ast_ignorepat ip 
) [read]

Definition at line 11040 of file pbx.c.

References ast_context::ignorepats, and ast_ignorepat::next.

Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().

11042 {
11043    if (!ip)
11044       return con ? con->ignorepats : NULL;
11045    else
11046       return ip->next;
11047 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
) [read]
struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
) [read]

Definition at line 11016 of file pbx.c.

References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.

Referenced by context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().

11018 {
11019    if (!sw)
11020       return con ? AST_LIST_FIRST(&con->alts) : NULL;
11021    else
11022       return AST_LIST_NEXT(sw, list);
11023 }

struct ast_context* ast_walk_contexts ( struct ast_context con  )  [read]
struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
) [read]

Definition at line 11025 of file pbx.c.

References ast_exten::peer.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().

11027 {
11028    return priority ? priority->peer : exten;
11029 }

int ast_wrlock_context ( struct ast_context con  ) 

Write locks a given context.

Parameters:
con context to lock
Return values:
0 on success
-1 on failure

Definition at line 10883 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().

10884 {
10885    return ast_rwlock_wrlock(&con->lock);
10886 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

Definition at line 10865 of file pbx.c.

References ast_mutex_lock, and conlock.

Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().

10866 {
10867    return ast_mutex_lock(&conlock);
10868 }

static void* async_wait ( void *  data  )  [static]

Definition at line 9208 of file pbx.c.

References ast_channel::_state, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_free, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_remaining_ms(), AST_STATE_UP, ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, ast_frame::subclass, and async_stat::timeout.

Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

09209 {
09210    struct async_stat *as = data;
09211    struct ast_channel *chan = as->chan;
09212    int timeout = as->timeout;
09213    int res;
09214    struct ast_frame *f;
09215    struct ast_app *app;
09216    struct timeval start = ast_tvnow();
09217    int ms;
09218 
09219    while ((ms = ast_remaining_ms(start, timeout)) &&
09220          chan->_state != AST_STATE_UP) {
09221       res = ast_waitfor(chan, ms);
09222       if (res < 1)
09223          break;
09224 
09225       f = ast_read(chan);
09226       if (!f)
09227          break;
09228       if (f->frametype == AST_FRAME_CONTROL) {
09229          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
09230              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
09231             ast_frfree(f);
09232             break;
09233          }
09234       }
09235       ast_frfree(f);
09236    }
09237    if (chan->_state == AST_STATE_UP) {
09238       if (!ast_strlen_zero(as->app)) {
09239          app = pbx_findapp(as->app);
09240          if (app) {
09241             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
09242             pbx_exec(chan, app, as->appdata);
09243          } else
09244             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
09245       } else {
09246          if (!ast_strlen_zero(as->context))
09247             ast_copy_string(chan->context, as->context, sizeof(chan->context));
09248          if (!ast_strlen_zero(as->exten))
09249             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
09250          if (as->priority > 0)
09251             chan->priority = as->priority;
09252          /* Run the PBX */
09253          if (ast_pbx_run(chan)) {
09254             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
09255          } else {
09256             /* PBX will have taken care of this */
09257             chan = NULL;
09258          }
09259       }
09260    }
09261    ast_free(as);
09262    if (chan)
09263       ast_hangup(chan);
09264    return NULL;
09265 }

static void cli_match_char_tree ( struct match_char node,
char *  prefix,
int  fd 
) [static]

Definition at line 1657 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().

01658 {
01659    char extenstr[40];
01660    struct ast_str *my_prefix = ast_str_alloca(1024);
01661 
01662    extenstr[0] = '\0';
01663 
01664    if (node->exten) {
01665       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01666    }
01667 
01668    if (strlen(node->x) > 1) {
01669       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01670          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01671          node->exten ? node->exten->exten : "", extenstr);
01672    } else {
01673       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01674          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01675          node->exten ? node->exten->exten : "", extenstr);
01676    }
01677 
01678    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01679 
01680    if (node->next_char)
01681       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01682 
01683    if (node->alt_char)
01684       cli_match_char_tree(node->alt_char, prefix, fd);
01685 }

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.

Parameters:
c,buf,buflen,pos 
waittime is in milliseconds
Return values:
0 on timeout or done.
-1 on error.

Definition at line 5399 of file pbx.c.

References ast_channel::_softhangup, ast_channel_clear_softhangup(), ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::caller, ast_channel::context, ast_pbx::dtimeoutms, ast_party_caller::id, ast_party_id::number, ast_channel::pbx, S_COR, ast_party_number::str, and ast_party_number::valid.

Referenced by __ast_pbx_run().

05400 {
05401    int digit;
05402 
05403    buf[pos] = '\0';  /* make sure it is properly terminated */
05404    while (ast_matchmore_extension(c, c->context, buf, 1,
05405       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05406       /* As long as we're willing to wait, and as long as it's not defined,
05407          keep reading digits until we can't possibly get a right answer anymore.  */
05408       digit = ast_waitfordigit(c, waittime);
05409       if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05410          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05411       } else {
05412          if (!digit) /* No entry */
05413             break;
05414          if (digit < 0) /* Error, maybe a  hangup */
05415             return -1;
05416          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
05417             buf[pos++] = digit;
05418             buf[pos] = '\0';
05419          }
05420          waittime = c->pbx->dtimeoutms;
05421       }
05422    }
05423    return 0;
05424 }

static int compare_char ( const void *  a,
const void *  b 
) [static]

Definition at line 1083 of file pbx.c.

Referenced by get_pattern_node().

01084 {
01085    const unsigned char *ac = a;
01086    const unsigned char *bc = b;
01087 
01088    return *ac - *bc;
01089 }

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 6597 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().

06598 {
06599    struct ast_hint *hint;
06600    char *ret = NULL;
06601    int which = 0;
06602    int wordlen;
06603    struct ao2_iterator i;
06604 
06605    if (pos != 3)
06606       return NULL;
06607 
06608    wordlen = strlen(word);
06609 
06610    /* walk through all hints */
06611    i = ao2_iterator_init(hints, 0);
06612    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06613       ao2_lock(hint);
06614       if (!hint->exten) {
06615          /* The extension has already been destroyed */
06616          ao2_unlock(hint);
06617          continue;
06618       }
06619       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
06620          ret = ast_strdup(ast_get_extension_name(hint->exten));
06621          ao2_unlock(hint);
06622          ao2_ref(hint, -1);
06623          break;
06624       }
06625       ao2_unlock(hint);
06626    }
06627    ao2_iterator_destroy(&i);
06628 
06629    return ret;
06630 }

static char* complete_show_dialplan_context ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 6807 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().

06809 {
06810    struct ast_context *c = NULL;
06811    char *ret = NULL;
06812    int which = 0;
06813    int wordlen;
06814 
06815    /* we are do completion of [exten@]context on second position only */
06816    if (pos != 2)
06817       return NULL;
06818 
06819    ast_rdlock_contexts();
06820 
06821    wordlen = strlen(word);
06822 
06823    /* walk through all contexts and return the n-th match */
06824    while ( (c = ast_walk_contexts(c)) ) {
06825       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
06826          ret = ast_strdup(ast_get_context_name(c));
06827          break;
06828       }
06829    }
06830 
06831    ast_unlock_contexts();
06832 
06833    return ret;
06834 }

static void context_merge ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
struct ast_context context,
const char *  registrar 
) [static]

Definition at line 7784 of file pbx.c.

References ast_exten::app, ast_add_extension2(), ast_context_find_or_create(), ast_hashtab_end_traversal(), ast_hashtab_lookup(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_strdup, ast_verb, ast_exten::cidmatch, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, ast_exten::datad, ast_exten::exten, first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_context::registrar, ast_exten::registrar, and ast_context::root_table.

Referenced by ast_merge_contexts_and_delete().

07785 {
07786    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
07787    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
07788    struct ast_hashtab_iter *exten_iter;
07789    struct ast_hashtab_iter *prio_iter;
07790    int insert_count = 0;
07791    int first = 1;
07792 
07793    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
07794       the current registrar, and copy them to the new context. If the new context does not
07795       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
07796       only create the empty matching context if the old one meets the criteria */
07797 
07798    if (context->root_table) {
07799       exten_iter = ast_hashtab_start_traversal(context->root_table);
07800       while ((exten_item=ast_hashtab_next(exten_iter))) {
07801          if (new) {
07802             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
07803          } else {
07804             new_exten_item = NULL;
07805          }
07806          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
07807          while ((prio_item=ast_hashtab_next(prio_iter))) {
07808             int res1;
07809             char *dupdstr;
07810 
07811             if (new_exten_item) {
07812                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
07813             } else {
07814                new_prio_item = NULL;
07815             }
07816             if (strcmp(prio_item->registrar,registrar) == 0) {
07817                continue;
07818             }
07819             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
07820             if (!new) {
07821                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 */
07822             }
07823 
07824             /* copy in the includes, switches, and ignorepats */
07825             if (first) { /* but, only need to do this once */
07826                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07827                first = 0;
07828             }
07829 
07830             if (!new) {
07831                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
07832                ast_hashtab_end_traversal(prio_iter);
07833                ast_hashtab_end_traversal(exten_iter);
07834                return; /* no sense continuing. */
07835             }
07836             /* we will not replace existing entries in the new context with stuff from the old context.
07837                but, if this is because of some sort of registrar conflict, we ought to say something... */
07838 
07839             dupdstr = ast_strdup(prio_item->data);
07840 
07841             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
07842                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
07843             if (!res1 && new_exten_item && new_prio_item){
07844                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
07845                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
07846             } else {
07847                /* 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,
07848                 and no double frees take place, either! */
07849                insert_count++;
07850             }
07851          }
07852          ast_hashtab_end_traversal(prio_iter);
07853       }
07854       ast_hashtab_end_traversal(exten_iter);
07855    }
07856 
07857    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
07858         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
07859       /* we could have given it the registrar of the other module who incremented the refcount,
07860          but that's not available, so we give it the registrar we know about */
07861       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
07862 
07863       /* copy in the includes, switches, and ignorepats */
07864       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07865    }
07866 }

static void context_merge_incls_swits_igps_other_registrars ( struct ast_context new,
struct ast_context old,
const char *  registrar 
) [static]

Definition at line 7751 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().

07752 {
07753    struct ast_include *i;
07754    struct ast_ignorepat *ip;
07755    struct ast_sw *sw;
07756 
07757    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);
07758    /* copy in the includes, switches, and ignorepats */
07759    /* walk through includes */
07760    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
07761       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
07762          continue; /* not mine */
07763       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
07764    }
07765 
07766    /* walk through switches */
07767    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
07768       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
07769          continue; /* not mine */
07770       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));
07771    }
07772 
07773    /* walk thru ignorepats ... */
07774    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
07775       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
07776          continue; /* not mine */
07777       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
07778    }
07779 }

static void create_match_char_tree ( struct ast_context con  )  [static]

Definition at line 2279 of file pbx.c.

References add_exten_to_pattern_tree(), ast_hashtab_end_traversal(), ast_hashtab_get_stats(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_exten::exten, LOG_DEBUG, LOG_ERROR, ast_context::name, and ast_context::root_table.

Referenced by pbx_find_extension().

02280 {
02281    struct ast_hashtab_iter *t1;
02282    struct ast_exten *e1;
02283 #ifdef NEED_DEBUG
02284    int biggest_bucket, resizes, numobjs, numbucks;
02285 
02286    ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con);
02287    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02288    ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02289          numobjs, numbucks, biggest_bucket, resizes);
02290 #endif
02291    t1 = ast_hashtab_start_traversal(con->root_table);
02292    while ((e1 = ast_hashtab_next(t1))) {
02293       if (e1->exten) {
02294          add_exten_to_pattern_tree(con, e1, 0);
02295       } else {
02296          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02297       }
02298    }
02299    ast_hashtab_end_traversal(t1);
02300 }

static void decrease_call_count ( void   )  [static]

Definition at line 5790 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().

05791 {
05792    ast_mutex_lock(&maxcalllock);
05793    if (countcalls > 0)
05794       countcalls--;
05795    ast_mutex_unlock(&maxcalllock);
05796 }

static void destroy_exten ( struct ast_exten e  )  [static]
static void destroy_hint ( void *  obj  )  [static]

Definition at line 5164 of file pbx.c.

References ao2_callback, ao2_ref, AST_EXTENSION_DEACTIVATED, ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_state_cb::change_cb, ast_hint::context_name, ast_state_cb::data, ast_hint::exten, ast_hint::exten_name, and OBJ_UNLINK.

Referenced by ast_add_hint().

05165 {
05166    struct ast_hint *hint = obj;
05167 
05168    if (hint->callbacks) {
05169       struct ast_state_cb *state_cb;
05170       const char *context_name;
05171       const char *exten_name;
05172 
05173       if (hint->exten) {
05174          context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
05175          exten_name = ast_get_extension_name(hint->exten);
05176          hint->exten = NULL;
05177       } else {
05178          /* The extension has already been destroyed */
05179          context_name = hint->context_name;
05180          exten_name = hint->exten_name;
05181       }
05182       while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
05183          /* Notify with -1 and remove all callbacks */
05184          /* NOTE: The casts will not be needed for v1.10 and later */
05185          state_cb->change_cb((char *) context_name, (char *) exten_name,
05186             AST_EXTENSION_DEACTIVATED, state_cb->data);
05187          ao2_ref(state_cb, -1);
05188       }
05189       ao2_ref(hint->callbacks, -1);
05190    }
05191 }

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

Definition at line 2302 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().

02303 {
02304    /* destroy all the alternates */
02305    if (pattern_tree->alt_char) {
02306       destroy_pattern_tree(pattern_tree->alt_char);
02307       pattern_tree->alt_char = 0;
02308    }
02309    /* destroy all the nexts */
02310    if (pattern_tree->next_char) {
02311       destroy_pattern_tree(pattern_tree->next_char);
02312       pattern_tree->next_char = 0;
02313    }
02314    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02315    ast_free(pattern_tree);
02316 }

static void destroy_state_cb ( void *  doomed  )  [static]

Definition at line 4995 of file pbx.c.

References ast_state_cb::data, ast_state_cb::destroy_cb, and ast_state_cb::id.

Referenced by ast_extension_state_add_destroy().

04996 {
04997    struct ast_state_cb *state_cb = doomed;
04998 
04999    if (state_cb->destroy_cb) {
05000       state_cb->destroy_cb(state_cb->id, state_cb->data);
05001    }
05002 }

static void device_state_cb ( const struct ast_event event,
void *  unused 
) [static]

Definition at line 10733 of file pbx.c.

References ast_calloc, ast_event_get_ie_str(), AST_EVENT_IE_DEVICE, ast_free, ast_log(), ast_strlen_zero(), ast_taskprocessor_push(), statechange::dev, handle_statechange(), and LOG_ERROR.

Referenced by load_pbx().

10734 {
10735    const char *device;
10736    struct statechange *sc;
10737 
10738    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
10739    if (ast_strlen_zero(device)) {
10740       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
10741       return;
10742    }
10743 
10744    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
10745       return;
10746    strcpy(sc->dev, device);
10747    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
10748       ast_free(sc);
10749    }
10750 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 3529 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

03530 {
03531    struct pbx_exception *exception = data;
03532    ast_string_field_free_memory(exception);
03533    ast_free(exception);
03534 }

static int ext_cmp ( const char *  left,
const char *  right 
) [static]

Definition at line 2649 of file pbx.c.

References ext_cmp_exten(), and ext_cmp_pattern().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

02650 {
02651    /* Make sure non-pattern extens come first. */
02652    if (left[0] != '_') {
02653       if (right[0] == '_') {
02654          return -1;
02655       }
02656       /* Compare two non-pattern extens. */
02657       return ext_cmp_exten(left, right);
02658    }
02659    if (right[0] != '_') {
02660       return 1;
02661    }
02662 
02663    /*
02664     * OK, we need full pattern sorting routine.
02665     *
02666     * Skip past the underscores
02667     */
02668    return ext_cmp_pattern(left + 1, right + 1);
02669 }

static int ext_cmp_exten ( const char *  left,
const char *  right 
) [static]

Definition at line 2399 of file pbx.c.

Referenced by _extension_match_core(), and ext_cmp().

02400 {
02401    int cmp;
02402 
02403    for (;;) {
02404       /* Ignore '-' chars as eye candy fluff. */
02405       while (*left == '-') {
02406          ++left;
02407       }
02408       while (*right == '-') {
02409          ++right;
02410       }
02411 
02412       cmp = *left - *right;
02413       if (cmp) {
02414          break;
02415       }
02416       if (!*left) {
02417          /*
02418           * Get here only if both strings ended at the same time.  cmp
02419           * would be non-zero if only one string ended.
02420           */
02421          break;
02422       }
02423       ++left;
02424       ++right;
02425    }
02426    return cmp;
02427 }

static int ext_cmp_exten_partial ( const char *  left,
const char *  right 
) [static]

Definition at line 2356 of file pbx.c.

Referenced by _extension_match_core().

02357 {
02358    int cmp;
02359 
02360    for (;;) {
02361       /* Ignore '-' chars as eye candy fluff. */
02362       while (*left == '-') {
02363          ++left;
02364       }
02365       while (*right == '-') {
02366          ++right;
02367       }
02368 
02369       if (!*right) {
02370          /*
02371           * Right ended first for partial match or both ended at the same
02372           * time for a match.
02373           */
02374          cmp = 0;
02375          break;
02376       }
02377 
02378       cmp = *left - *right;
02379       if (cmp) {
02380          break;
02381       }
02382       ++left;
02383       ++right;
02384    }
02385    return cmp;
02386 }

static int ext_cmp_exten_strlen ( const char *  str  )  [static]

Definition at line 2326 of file pbx.c.

References len().

Referenced by _extension_match_core().

02327 {
02328    int len;
02329 
02330    len = 0;
02331    for (;;) {
02332       /* Ignore '-' chars as eye candy fluff. */
02333       while (*str == '-') {
02334          ++str;
02335       }
02336       if (!*str) {
02337          break;
02338       }
02339       ++str;
02340       ++len;
02341    }
02342    return len;
02343 }

static int ext_cmp_pattern ( const char *  left,
const char *  right 
) [static]

Definition at line 2601 of file pbx.c.

References ARRAY_LEN, and ext_cmp_pattern_pos().

Referenced by _extension_match_core(), and ext_cmp().

02602 {
02603    int cmp;
02604    int left_pos;
02605    int right_pos;
02606 
02607    for (;;) {
02608       unsigned char left_bitwise[32] = { 0, };
02609       unsigned char right_bitwise[32] = { 0, };
02610 
02611       left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
02612       right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
02613       cmp = left_pos - right_pos;
02614       if (!cmp) {
02615          /*
02616           * Are the character sets different, even though they score the same?
02617           *
02618           * Note: Must swap left and right to get the sense of the
02619           * comparison correct.  Otherwise, we would need to multiply by
02620           * -1 instead.
02621           */
02622          cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
02623       }
02624       if (cmp) {
02625          break;
02626       }
02627       if (!left) {
02628          /*
02629           * Get here only if both patterns ended at the same time.  cmp
02630           * would be non-zero if only one pattern ended.
02631           */
02632          break;
02633       }
02634    }
02635    return cmp;
02636 }

static int ext_cmp_pattern_pos ( const char **  p,
unsigned char *  bitwise 
) [static]

helper functions to sort extension patterns in the desired way, so that more specific patterns appear first.

The function compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, bits 8-15 are the number of characters in the set, and bits 16-20 are for special cases. This way more specific patterns (smaller character sets) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x001xx one character, character set starting with xx 0x0yyxx yy characters, character set starting with xx 0x18000 '.' (one or more of anything) 0x28000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is ignored. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.

Definition at line 2486 of file pbx.c.

References ast_log(), BITS_PER, and LOG_WARNING.

Referenced by ext_cmp_pattern().

02487 {
02488 #define BITS_PER  8  /* Number of bits per unit (byte). */
02489    unsigned char c;
02490    unsigned char cmin;
02491    int count;
02492    const char *end;
02493 
02494    do {
02495       /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
02496       do {
02497          c = *(*p)++;
02498       } while (c == '-');
02499 
02500       /* always return unless we have a set of chars */
02501       switch (c) {
02502       default:
02503          /* ordinary character */
02504          bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
02505          return 0x0100 | c;
02506 
02507       case 'n':
02508       case 'N':
02509          /* 2..9 */
02510          bitwise[6] = 0x3f;
02511          bitwise[7] = 0xc0;
02512          return 0x0800 | '2';
02513 
02514       case 'x':
02515       case 'X':
02516          /* 0..9 */
02517          bitwise[6] = 0xff;
02518          bitwise[7] = 0xc0;
02519          return 0x0A00 | '0';
02520 
02521       case 'z':
02522       case 'Z':
02523          /* 1..9 */
02524          bitwise[6] = 0x7f;
02525          bitwise[7] = 0xc0;
02526          return 0x0900 | '1';
02527 
02528       case '.':
02529          /* wildcard */
02530          return 0x18000;
02531 
02532       case '!':
02533          /* earlymatch */
02534          return 0x28000;   /* less specific than '.' */
02535 
02536       case '\0':
02537          /* empty string */
02538          *p = NULL;
02539          return 0x30000;
02540 
02541       case '[':
02542          /* char set */
02543          break;
02544       }
02545       /* locate end of set */
02546       end = strchr(*p, ']');
02547 
02548       if (!end) {
02549          ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02550          return 0x40000;   /* XXX make this entry go last... */
02551       }
02552 
02553       count = 0;
02554       cmin = 0xFF;
02555       for (; *p < end; ++*p) {
02556          unsigned char c1; /* first char in range */
02557          unsigned char c2; /* last char in range */
02558 
02559          c1 = (*p)[0];
02560          if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02561             c2 = (*p)[2];
02562             *p += 2;    /* skip a total of 3 chars */
02563          } else {        /* individual character */
02564             c2 = c1;
02565          }
02566          if (c1 < cmin) {
02567             cmin = c1;
02568          }
02569          for (; c1 <= c2; ++c1) {
02570             unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
02571 
02572             /*
02573              * Note: If two character sets score the same, the one with the
02574              * lowest ASCII values will compare as coming first.  Must fill
02575              * in most significant bits for lower ASCII values to accomplish
02576              * the desired sort order.
02577              */
02578             if (!(bitwise[c1 / BITS_PER] & mask)) {
02579                /* Add the character to the set. */
02580                bitwise[c1 / BITS_PER] |= mask;
02581                count += 0x100;
02582             }
02583          }
02584       }
02585       ++*p;
02586    } while (!count);/* While the char set was empty. */
02587    return count | cmin;
02588 }

static int ext_strncpy ( char *  dst,
const char *  src,
int  len 
) [static]

copy a string skipping whitespace

Definition at line 8750 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

08751 {
08752    int count = 0;
08753    int insquares = 0;
08754 
08755    while (*src && (count < len - 1)) {
08756       if (*src == '[') {
08757          insquares = 1;
08758       } else if (*src == ']') {
08759          insquares = 0;
08760       } else if (*src == ' ' && !insquares) {
08761          src++;
08762          continue;
08763       }
08764       *dst = *src;
08765       dst++;
08766       src++;
08767       count++;
08768    }
08769    *dst = '\0';
08770 
08771    return count;
08772 }

static int extension_match_core ( const char *  pattern,
const char *  data,
enum ext_match_t  mode 
) [static]

Definition at line 2888 of file pbx.c.

References _extension_match_core(), ast_add_profile(), ast_mark(), and ast_strlen_zero().

Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().

02889 {
02890    int i;
02891    static int prof_id = -2;   /* marker for 'unallocated' id */
02892    if (prof_id == -2) {
02893       prof_id = ast_add_profile("ext_match", 0);
02894    }
02895    ast_mark(prof_id, 1);
02896    i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
02897    ast_mark(prof_id, 0);
02898    return i;
02899 }

static struct ast_context * find_context ( const char *  context  )  [static, read]

lookup for a context with a given name,

Return values:
found context or NULL if not found.

Definition at line 5924 of file pbx.c.

References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.

05925 {
05926    struct fake_context item;
05927 
05928    ast_copy_string(item.name, context, sizeof(item.name));
05929 
05930    return ast_hashtab_lookup(contexts_table, &item);
05931 }

static struct ast_context * find_context_locked ( const char *  context  )  [static, read]

lookup for a context with a given name,

Return values:
with conlock held if found.
NULL if not found.

Definition at line 5938 of file pbx.c.

References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, and fake_context::name.

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), and ast_context_unlockmacro().

05939 {
05940    struct ast_context *c;
05941    struct fake_context item;
05942 
05943    ast_copy_string(item.name, context, sizeof(item.name));
05944 
05945    ast_rdlock_contexts();
05946    c = ast_hashtab_lookup(contexts_table, &item);
05947    if (!c) {
05948       ast_unlock_contexts();
05949    }
05950 
05951    return c;
05952 }

static int find_hint_by_cb_id ( void *  obj,
void *  arg,
int  flags 
) [static]

Remove a watcher from the callback list.

Definition at line 5099 of file pbx.c.

References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.

Referenced by ast_extension_state_del().

05100 {
05101    struct ast_state_cb *state_cb;
05102    const struct ast_hint *hint = obj;
05103    int *id = arg;
05104 
05105    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
05106       ao2_ref(state_cb, -1);
05107       return CMP_MATCH | CMP_STOP;
05108    }
05109 
05110    return 0;
05111 }

static char* func_args ( char *  function  )  [static]

return a pointer to the arguments of the function, and terminates the function name with '\0'

Definition at line 3998 of file pbx.c.

References args, ast_log(), and LOG_WARNING.

Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().

03999 {
04000    char *args = strchr(function, '(');
04001 
04002    if (!args) {
04003       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
04004    } else {
04005       char *p;
04006       *args++ = '\0';
04007       if ((p = strrchr(args, ')'))) {
04008          *p = '\0';
04009       } else {
04010          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
04011       }
04012    }
04013    return args;
04014 }

static struct ast_exten * get_canmatch_exten ( struct match_char node  )  [static, read]

Definition at line 1687 of file pbx.c.

References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.

01688 {
01689    /* find the exten at the end of the rope */
01690    struct match_char *node2 = node;
01691 
01692    for (node2 = node; node2; node2 = node2->next_char) {
01693       if (node2->exten) {
01694 #ifdef NEED_DEBUG_HERE
01695          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01696 #endif
01697          return node2->exten;
01698       }
01699    }
01700 #ifdef NEED_DEBUG_HERE
01701    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01702 #endif
01703    return 0;
01704 }

static const char* get_pattern_node ( struct pattern_node node,
const char *  src,
int  pattern,
const char *  extenbuf 
) [static]

Definition at line 2036 of file pbx.c.

References ast_log(), pattern_node::buf, compare_char(), first, INC_DST_OVERFLOW_CHECK, last, LOG_ERROR, LOG_WARNING, and pattern_node::specif.

Referenced by add_exten_to_pattern_tree().

02037 {
02038 #define INC_DST_OVERFLOW_CHECK                     \
02039    do {                                   \
02040       if (dst - node->buf < sizeof(node->buf) - 1) {  \
02041          ++dst;                              \
02042       } else {                            \
02043          overflow = 1;                       \
02044       }                                   \
02045    } while (0)
02046 
02047    node->specif = 0;
02048    node->buf[0] = '\0';
02049    while (*src) {
02050       if (*src == '[' && pattern) {
02051          char *dst = node->buf;
02052          const char *src_next;
02053          int length;
02054          int overflow = 0;
02055 
02056          /* get past the '[' */
02057          ++src;
02058          for (;;) {
02059             if (*src == '\\') {
02060                /* Escaped character. */
02061                ++src;
02062                if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
02063                   *dst = *src++;
02064                   INC_DST_OVERFLOW_CHECK;
02065                }
02066             } else if (*src == '-') {
02067                unsigned char first;
02068                unsigned char last;
02069 
02070                src_next = src;
02071                first = *(src_next - 1);
02072                last = *++src_next;
02073 
02074                if (last == '\\') {
02075                   /* Escaped character. */
02076                   last = *++src_next;
02077                }
02078 
02079                /* Possible char range. */
02080                if (node->buf[0] && last) {
02081                   /* Expand the char range. */
02082                   while (++first <= last) {
02083                      *dst = first;
02084                      INC_DST_OVERFLOW_CHECK;
02085                   }
02086                   src = src_next + 1;
02087                } else {
02088                   /*
02089                    * There was no left or right char for the range.
02090                    * It is just a '-'.
02091                    */
02092                   *dst = *src++;
02093                   INC_DST_OVERFLOW_CHECK;
02094                }
02095             } else if (*src == '\0') {
02096                ast_log(LOG_WARNING,
02097                   "A matching ']' was not found for '[' in exten pattern '%s'\n",
02098                   extenbuf);
02099                break;
02100             } else if (*src == ']') {
02101                ++src;
02102                break;
02103             } else {
02104                *dst = *src++;
02105                INC_DST_OVERFLOW_CHECK;
02106             }
02107          }
02108          /* null terminate the exploded range */
02109          *dst = '\0';
02110 
02111          if (overflow) {
02112             ast_log(LOG_ERROR,
02113                "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
02114                extenbuf);
02115             node->buf[0] = '\0';
02116             continue;
02117          }
02118 
02119          /* Sort the characters in character set. */
02120          length = strlen(node->buf);
02121          if (!length) {
02122             ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
02123                extenbuf);
02124             node->buf[0] = '\0';
02125             continue;
02126          }
02127          qsort(node->buf, length, 1, compare_char);
02128 
02129          /* Remove duplicate characters from character set. */
02130          dst = node->buf;
02131          src_next = node->buf;
02132          while (*src_next++) {
02133             if (*dst != *src_next) {
02134                *++dst = *src_next;
02135             }
02136          }
02137 
02138          length = strlen(node->buf);
02139          length <<= 8;
02140          node->specif = length | (unsigned char) node->buf[0];
02141          break;
02142       } else if (*src == '-') {
02143          /* Skip dashes in all extensions. */
02144          ++src;
02145       } else {
02146          if (*src == '\\') {
02147             /*
02148              * XXX The escape character here does not remove any special
02149              * meaning to characters except the '[', '\\', and '-'
02150              * characters since they are special only in this function.
02151              */
02152             node->buf[0] = *++src;
02153             if (!node->buf[0]) {
02154                break;
02155             }
02156          } else {
02157             node->buf[0] = *src;
02158             if (pattern) {
02159                /* make sure n,x,z patterns are canonicalized to N,X,Z */
02160                if (node->buf[0] == 'n') {
02161                   node->buf[0] = 'N';
02162                } else if (node->buf[0] == 'x') {
02163                   node->buf[0] = 'X';
02164                } else if (node->buf[0] == 'z') {
02165                   node->buf[0] = 'Z';
02166                }
02167             }
02168          }
02169          node->buf[1] = '\0';
02170          node->specif = 1;
02171          ++src;
02172          break;
02173       }
02174    }
02175    return src;
02176 
02177 #undef INC_DST_OVERFLOW_CHECK
02178 }

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 8105 of file pbx.c.

References ast_log(), ast_strlen_zero(), LOG_WARNING, and lookup_name().

Referenced by ast_build_timing().

08106 {
08107    int start, end; /* start and ending position */
08108    unsigned int mask = 0;
08109    char *part;
08110 
08111    /* Check for whole range */
08112    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
08113       return (1 << max) - 1;
08114    }
08115 
08116    while ((part = strsep(&src, "&"))) {
08117       /* Get start and ending position */
08118       char *endpart = strchr(part, '-');
08119       if (endpart) {
08120          *endpart++ = '\0';
08121       }
08122       /* Find the start */
08123       if ((start = lookup_name(part, names, max)) < 0) {
08124          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
08125          continue;
08126       }
08127       if (endpart) { /* find end of range */
08128          if ((end = lookup_name(endpart, names, max)) < 0) {
08129             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
08130             continue;
08131          }
08132       } else {
08133          end = start;
08134       }
08135       /* Fill the mask. Remember that ranges are cyclic */
08136       mask |= (1 << end);   /* initialize with last element */
08137       while (start != end) {
08138          mask |= (1 << start);
08139          if (++start >= max) {
08140             start = 0;
08141          }
08142       }
08143    }
08144    return mask;
08145 }

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 8148 of file pbx.c.

References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.

Referenced by ast_build_timing().

08149 {
08150    char *endpart, *part;
08151    int x;
08152    int st_h, st_m;
08153    int endh, endm;
08154    int minute_start, minute_end;
08155 
08156    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
08157    memset(i->minmask, 0, sizeof(i->minmask));
08158 
08159    /* 1-minute per bit */
08160    /* Star is all times */
08161    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
08162       /* 48, because each hour takes 2 integers; 30 bits each */
08163       for (x = 0; x < 48; x++) {
08164          i->minmask[x] = 0x3fffffff; /* 30 bits */
08165       }
08166       return;
08167    }
08168    /* Otherwise expect a range */
08169    while ((part = strsep(&times, "&"))) {
08170       if (!(endpart = strchr(part, '-'))) {
08171          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
08172             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
08173             continue;
08174          }
08175          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
08176          continue;
08177       }
08178       *endpart++ = '\0';
08179       /* why skip non digits? Mostly to skip spaces */
08180       while (*endpart && !isdigit(*endpart)) {
08181          endpart++;
08182       }
08183       if (!*endpart) {
08184          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
08185          continue;
08186       }
08187       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
08188          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
08189          continue;
08190       }
08191       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
08192          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
08193          continue;
08194       }
08195       minute_start = st_h * 60 + st_m;
08196       minute_end = endh * 60 + endm;
08197       /* Go through the time and enable each appropriate bit */
08198       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
08199          i->minmask[x / 30] |= (1 << (x % 30));
08200       }
08201       /* Do the last one */
08202       i->minmask[x / 30] |= (1 << (x % 30));
08203    }
08204    /* All done */
08205    return;
08206 }

static char* handle_debug_dialplan ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Send ack once.

Definition at line 7134 of file pbx.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), dialplan_counters::total_context, ast_cli_entry::usage, and ast_cli_args::word.

07135 {
07136    char *exten = NULL, *context = NULL;
07137    /* Variables used for different counters */
07138    struct dialplan_counters counters;
07139    const char *incstack[AST_PBX_MAX_STACK];
07140 
07141    switch (cmd) {
07142    case CLI_INIT:
07143       e->command = "dialplan debug";
07144       e->usage =
07145          "Usage: dialplan debug [context]\n"
07146          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
07147       return NULL;
07148    case CLI_GENERATE:
07149       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
07150    }
07151 
07152    memset(&counters, 0, sizeof(counters));
07153 
07154    if (a->argc != 2 && a->argc != 3)
07155       return CLI_SHOWUSAGE;
07156 
07157    /* we obtain [exten@]context? if yes, split them ... */
07158    /* note: we ignore the exten totally here .... */
07159    if (a->argc == 3) {
07160       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
07161          context = ast_strdupa(a->argv[2]);
07162          exten = strsep(&context, "@");
07163          /* change empty strings to NULL */
07164          if (ast_strlen_zero(exten))
07165             exten = NULL;
07166       } else { /* no '@' char, only context given */
07167          context = ast_strdupa(a->argv[2]);
07168       }
07169       if (ast_strlen_zero(context))
07170          context = NULL;
07171    }
07172    /* else Show complete dial plan, context and exten are NULL */
07173    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
07174 
07175    /* check for input failure and throw some error messages */
07176    if (context && !counters.context_existence) {
07177       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
07178       return CLI_FAILURE;
07179    }
07180 
07181 
07182    ast_cli(a->fd,"-= %d %s. =-\n",
07183          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
07184 
07185    /* everything ok */
07186    return CLI_SUCCESS;
07187 }

static char* handle_set_chanvar ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 7507 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.

07508 {
07509    struct ast_channel *chan;
07510    const char *chan_name, *var_name, *var_value;
07511 
07512    switch (cmd) {
07513    case CLI_INIT:
07514       e->command = "dialplan set chanvar";
07515       e->usage =
07516          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
07517          "       Set channel variable <varname> to <value>\n";
07518       return NULL;
07519    case CLI_GENERATE:
07520       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07521    }
07522 
07523    if (a->argc != e->args + 3)
07524       return CLI_SHOWUSAGE;
07525 
07526    chan_name = a->argv[e->args];
07527    var_name = a->argv[e->args + 1];
07528    var_value = a->argv[e->args + 2];
07529 
07530    if (!(chan = ast_channel_get_by_name(chan_name))) {
07531       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
07532       return CLI_FAILURE;
07533    }
07534 
07535    pbx_builtin_setvar_helper(chan, var_name, var_value);
07536 
07537    chan = ast_channel_unref(chan);
07538 
07539    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
07540 
07541    return CLI_SUCCESS;
07542 }

static char* handle_set_extenpatternmatchnew ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 7544 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.

07545 {
07546    int oldval = 0;
07547 
07548    switch (cmd) {
07549    case CLI_INIT:
07550       e->command = "dialplan set extenpatternmatchnew true";
07551       e->usage =
07552          "Usage: dialplan set extenpatternmatchnew true|false\n"
07553          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07554       return NULL;
07555    case CLI_GENERATE:
07556       return NULL;
07557    }
07558 
07559    if (a->argc != 4)
07560       return CLI_SHOWUSAGE;
07561 
07562    oldval =  pbx_set_extenpatternmatchnew(1);
07563 
07564    if (oldval)
07565       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
07566    else
07567       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
07568 
07569    return CLI_SUCCESS;
07570 }

static char* handle_set_global ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 7485 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.

07486 {
07487    switch (cmd) {
07488    case CLI_INIT:
07489       e->command = "dialplan set global";
07490       e->usage =
07491          "Usage: dialplan set global <name> <value>\n"
07492          "       Set global dialplan variable <name> to <value>\n";
07493       return NULL;
07494    case CLI_GENERATE:
07495       return NULL;
07496    }
07497 
07498    if (a->argc != e->args + 2)
07499       return CLI_SHOWUSAGE;
07500 
07501    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
07502    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
07503 
07504    return CLI_SUCCESS;
07505 }

static char* handle_show_application ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 6496 of file pbx.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_complete_applications(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.

06497 {
06498    struct ast_app *aa;
06499    int app, no_registered_app = 1;
06500 
06501    switch (cmd) {
06502    case CLI_INIT:
06503       e->command = "core show application";
06504       e->usage =
06505          "Usage: core show application <application> [<application> [<application> [...]]]\n"
06506          "       Describes a particular application.\n";
06507       return NULL;
06508    case CLI_GENERATE:
06509       /*
06510        * There is a possibility to show informations about more than one
06511        * application at one time. You can type 'show application Dial Echo' and
06512        * you will see informations about these two applications ...
06513        */
06514       return ast_complete_applications(a->line, a->word, a->n);
06515    }
06516 
06517    if (a->argc < 4) {
06518       return CLI_SHOWUSAGE;
06519    }
06520 
06521    AST_RWLIST_RDLOCK(&apps);
06522    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06523       /* Check for each app that was supplied as an argument */
06524       for (app = 3; app < a->argc; app++) {
06525          if (strcasecmp(aa->name, a->argv[app])) {
06526             continue;
06527          }
06528 
06529          /* We found it! */
06530          no_registered_app = 0;
06531 
06532          print_app_docs(aa, a->fd);
06533       }
06534    }
06535    AST_RWLIST_UNLOCK(&apps);
06536 
06537    /* we found at least one app? no? */
06538    if (no_registered_app) {
06539       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
06540       return CLI_FAILURE;
06541    }
06542 
06543    return CLI_SUCCESS;
06544 }

static char* handle_show_applications ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 6721 of file pbx.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_app::description, ast_cli_args::fd, ast_cli_args::n, ast_app::name, ast_cli_args::pos, ast_app::synopsis, ast_cli_entry::usage, and ast_cli_args::word.

06722 {
06723    struct ast_app *aa;
06724    int like = 0, describing = 0;
06725    int total_match = 0;    /* Number of matches in like clause */
06726    int total_apps = 0;     /* Number of apps registered */
06727    static const char * const choices[] = { "like", "describing", NULL };
06728 
06729    switch (cmd) {
06730    case CLI_INIT:
06731       e->command = "core show applications [like|describing]";
06732       e->usage =
06733          "Usage: core show applications [{like|describing} <text>]\n"
06734          "       List applications which are currently available.\n"
06735          "       If 'like', <text> will be a substring of the app name\n"
06736          "       If 'describing', <text> will be a substring of the description\n";
06737       return NULL;
06738    case CLI_GENERATE:
06739       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
06740    }
06741 
06742    AST_RWLIST_RDLOCK(&apps);
06743 
06744    if (AST_RWLIST_EMPTY(&apps)) {
06745       ast_cli(a->fd, "There are no registered applications\n");
06746       AST_RWLIST_UNLOCK(&apps);
06747       return CLI_SUCCESS;
06748    }
06749 
06750    /* core list applications like <keyword> */
06751    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
06752       like = 1;
06753    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
06754       describing = 1;
06755    }
06756 
06757    /* core list applications describing <keyword1> [<keyword2>] [...] */
06758    if ((!like) && (!describing)) {
06759       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
06760    } else {
06761       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
06762    }
06763 
06764    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06765       int printapp = 0;
06766       total_apps++;
06767       if (like) {
06768          if (strcasestr(aa->name, a->argv[4])) {
06769             printapp = 1;
06770             total_match++;
06771          }
06772       } else if (describing) {
06773          if (aa->description) {
06774             /* Match all words on command line */
06775             int i;
06776             printapp = 1;
06777             for (i = 4; i < a->argc; i++) {
06778                if (!strcasestr(aa->description, a->argv[i])) {
06779                   printapp = 0;
06780                } else {
06781                   total_match++;
06782                }
06783             }
06784          }
06785       } else {
06786          printapp = 1;
06787       }
06788 
06789       if (printapp) {
06790          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
06791       }
06792    }
06793    if ((!like) && (!describing)) {
06794       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
06795    } else {
06796       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
06797    }
06798 
06799    AST_RWLIST_UNLOCK(&apps);
06800 
06801    return CLI_SUCCESS;
06802 }

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 7450 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.

07451 {
07452    struct ast_channel *chan = NULL;
07453    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
07454 
07455    switch (cmd) {
07456    case CLI_INIT:
07457       e->command = "dialplan show chanvar";
07458       e->usage =
07459          "Usage: dialplan show chanvar <channel>\n"
07460          "       List current channel variables and their values\n";
07461       return NULL;
07462    case CLI_GENERATE:
07463       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07464    }
07465 
07466    if (a->argc != e->args + 1)
07467       return CLI_SHOWUSAGE;
07468 
07469    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
07470       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
07471       return CLI_FAILURE;
07472    }
07473 
07474    pbx_builtin_serialize_variables(chan, &vars);
07475 
07476    if (ast_str_strlen(vars)) {
07477       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
07478    }
07479 
07480    chan = ast_channel_unref(chan);
07481 
07482    return CLI_SUCCESS;
07483 }

static char* handle_show_dialplan ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 7067 of file pbx.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, ast_cli_entry::usage, and ast_cli_args::word.

07068 {
07069    char *exten = NULL, *context = NULL;
07070    /* Variables used for different counters */
07071    struct dialplan_counters counters;
07072    const char *incstack[AST_PBX_MAX_STACK];
07073 
07074    switch (cmd) {
07075    case CLI_INIT:
07076       e->command = "dialplan show";
07077       e->usage =
07078          "Usage: dialplan show [[exten@]context]\n"
07079          "       Show dialplan\n";
07080       return NULL;
07081    case CLI_GENERATE:
07082       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
07083    }
07084 
07085    memset(&counters, 0, sizeof(counters));
07086 
07087    if (a->argc != 2 && a->argc != 3)
07088       return CLI_SHOWUSAGE;
07089 
07090    /* we obtain [exten@]context? if yes, split them ... */
07091    if (a->argc == 3) {
07092       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
07093          context = ast_strdupa(a->argv[2]);
07094          exten = strsep(&context, "@");
07095          /* change empty strings to NULL */
07096          if (ast_strlen_zero(exten))
07097             exten = NULL;
07098       } else { /* no '@' char, only context given */
07099          context = ast_strdupa(a->argv[2]);
07100       }
07101       if (ast_strlen_zero(context))
07102          context = NULL;
07103    }
07104    /* else Show complete dial plan, context and exten are NULL */
07105    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
07106 
07107    /* check for input failure and throw some error messages */
07108    if (context && !counters.context_existence) {
07109       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
07110       return CLI_FAILURE;
07111    }
07112 
07113    if (exten && !counters.extension_existence) {
07114       if (context)
07115          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
07116             exten, context);
07117       else
07118          ast_cli(a->fd,
07119             "There is no existence of '%s' extension in all contexts\n",
07120             exten);
07121       return CLI_FAILURE;
07122    }
07123 
07124    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
07125             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
07126             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
07127             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
07128 
07129    /* everything ok */
07130    return CLI_SUCCESS;
07131 }

static char* handle_show_function ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3651 of file pbx.c.

References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), ast_free, ast_malloc, AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_custom_function::docsrc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, S_OR, synopsis, term_color(), ast_cli_entry::usage, and ast_cli_args::word.

03652 {
03653    struct ast_custom_function *acf;
03654    /* Maximum number of characters added by terminal coloring is 22 */
03655    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03656    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03657    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03658    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03659    char *ret = NULL;
03660    int which = 0;
03661    int wordlen;
03662 
03663    switch (cmd) {
03664    case CLI_INIT:
03665       e->command = "core show function";
03666       e->usage =
03667          "Usage: core show function <function>\n"
03668          "       Describe a particular dialplan function.\n";
03669       return NULL;
03670    case CLI_GENERATE:
03671       wordlen = strlen(a->word);
03672       /* case-insensitive for convenience in this 'complete' function */
03673       AST_RWLIST_RDLOCK(&acf_root);
03674       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03675          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03676             ret = ast_strdup(acf->name);
03677             break;
03678          }
03679       }
03680       AST_RWLIST_UNLOCK(&acf_root);
03681 
03682       return ret;
03683    }
03684 
03685    if (a->argc < 4) {
03686       return CLI_SHOWUSAGE;
03687    }
03688 
03689    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03690       ast_cli(a->fd, "No function by that name registered.\n");
03691       return CLI_FAILURE;
03692    }
03693 
03694    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03695    if (!(syntax = ast_malloc(syntax_size))) {
03696       ast_cli(a->fd, "Memory allocation failure!\n");
03697       return CLI_FAILURE;
03698    }
03699 
03700    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03701    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03702    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03703    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03704    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03705    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03706    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03707    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03708 #ifdef AST_XML_DOCS
03709    if (acf->docsrc == AST_XML_DOC) {
03710       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03711       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03712       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03713       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03714    } else
03715 #endif
03716    {
03717       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03718       synopsis = ast_malloc(synopsis_size);
03719 
03720       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03721       description = ast_malloc(description_size);
03722 
03723       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03724       arguments = ast_malloc(arguments_size);
03725 
03726       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03727       seealso = ast_malloc(seealso_size);
03728 
03729       /* check allocated memory. */
03730       if (!synopsis || !description || !arguments || !seealso) {
03731          ast_free(synopsis);
03732          ast_free(description);
03733          ast_free(arguments);
03734          ast_free(seealso);
03735          ast_free(syntax);
03736          return CLI_FAILURE;
03737       }
03738 
03739       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03740       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03741       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03742       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03743    }
03744 
03745    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03746          infotitle, syntitle, synopsis, destitle, description,
03747          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03748 
03749    ast_free(arguments);
03750    ast_free(synopsis);
03751    ast_free(description);
03752    ast_free(seealso);
03753    ast_free(syntax);
03754 
03755    return CLI_SUCCESS;
03756 }

static char* handle_show_functions ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3609 of file pbx.c.

References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, S_OR, and ast_cli_entry::usage.

03610 {
03611    struct ast_custom_function *acf;
03612    int count_acf = 0;
03613    int like = 0;
03614 
03615    switch (cmd) {
03616    case CLI_INIT:
03617       e->command = "core show functions [like]";
03618       e->usage =
03619          "Usage: core show functions [like <text>]\n"
03620          "       List builtin functions, optionally only those matching a given string\n";
03621       return NULL;
03622    case CLI_GENERATE:
03623       return NULL;
03624    }
03625 
03626    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03627       like = 1;
03628    } else if (a->argc != 3) {
03629       return CLI_SHOWUSAGE;
03630    }
03631 
03632    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03633 
03634    AST_RWLIST_RDLOCK(&acf_root);
03635    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03636       if (!like || strstr(acf->name, a->argv[4])) {
03637          count_acf++;
03638          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03639             S_OR(acf->name, ""),
03640             S_OR(acf->syntax, ""),
03641             S_OR(acf->synopsis, ""));
03642       }
03643    }
03644    AST_RWLIST_UNLOCK(&acf_root);
03645 
03646    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03647 
03648    return CLI_SUCCESS;
03649 }

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 7392 of file pbx.c.

References ast_cli(), AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, globals, globalslock, and ast_cli_entry::usage.

07393 {
07394    int i = 0;
07395    struct ast_var_t *newvariable;
07396 
07397    switch (cmd) {
07398    case CLI_INIT:
07399       e->command = "dialplan show globals";
07400       e->usage =
07401          "Usage: dialplan show globals\n"
07402          "       List current global dialplan variables and their values\n";
07403       return NULL;
07404    case CLI_GENERATE:
07405       return NULL;
07406    }
07407 
07408    ast_rwlock_rdlock(&globalslock);
07409    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
07410       i++;
07411       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
07412    }
07413    ast_rwlock_unlock(&globalslock);
07414    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
07415 
07416    return CLI_SUCCESS;
07417 }

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 6633 of file pbx.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

06634 {
06635    struct ast_hint *hint;
06636    int watchers;
06637    int num = 0, extenlen;
06638    struct ao2_iterator i;
06639 
06640    switch (cmd) {
06641    case CLI_INIT:
06642       e->command = "core show hint";
06643       e->usage =
06644          "Usage: core show hint <exten>\n"
06645          "       List registered hint\n";
06646       return NULL;
06647    case CLI_GENERATE:
06648       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
06649    }
06650 
06651    if (a->argc < 4)
06652       return CLI_SHOWUSAGE;
06653 
06654    if (ao2_container_count(hints) == 0) {
06655       ast_cli(a->fd, "There are no registered dialplan hints\n");
06656       return CLI_SUCCESS;
06657    }
06658    
06659    extenlen = strlen(a->argv[3]);
06660    i = ao2_iterator_init(hints, 0);
06661    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06662       ao2_lock(hint);
06663       if (!hint->exten) {
06664          /* The extension has already been destroyed */
06665          ao2_unlock(hint);
06666          continue;
06667       }
06668       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
06669          watchers = ao2_container_count(hint->callbacks);
06670          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06671             ast_get_extension_name(hint->exten),
06672             ast_get_context_name(ast_get_extension_context(hint->exten)),
06673             ast_get_extension_app(hint->exten),
06674             ast_extension_state2str(hint->laststate), watchers);
06675          num++;
06676       }
06677       ao2_unlock(hint);
06678    }
06679    ao2_iterator_destroy(&i);
06680    if (!num)
06681       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
06682    else
06683       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
06684    return CLI_SUCCESS;
06685 }

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 6547 of file pbx.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, and ast_cli_entry::usage.

06548 {
06549    struct ast_hint *hint;
06550    int num = 0;
06551    int watchers;
06552    struct ao2_iterator i;
06553 
06554    switch (cmd) {
06555    case CLI_INIT:
06556       e->command = "core show hints";
06557       e->usage =
06558          "Usage: core show hints\n"
06559          "       List registered hints\n";
06560       return NULL;
06561    case CLI_GENERATE:
06562       return NULL;
06563    }
06564 
06565    if (ao2_container_count(hints) == 0) {
06566       ast_cli(a->fd, "There are no registered dialplan hints\n");
06567       return CLI_SUCCESS;
06568    }
06569    /* ... we have hints ... */
06570    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
06571 
06572    i = ao2_iterator_init(hints, 0);
06573    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06574       ao2_lock(hint);
06575       if (!hint->exten) {
06576          /* The extension has already been destroyed */
06577          ao2_unlock(hint);
06578          continue;
06579       }
06580       watchers = ao2_container_count(hint->callbacks);
06581       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06582          ast_get_extension_name(hint->exten),
06583          ast_get_context_name(ast_get_extension_context(hint->exten)),
06584          ast_get_extension_app(hint->exten),
06585          ast_extension_state2str(hint->laststate), watchers);
06586       ao2_unlock(hint);
06587       num++;
06588    }
06589    ao2_iterator_destroy(&i);
06590 
06591    ast_cli(a->fd, "----------------\n");
06592    ast_cli(a->fd, "- %d hints registered\n", num);
06593    return CLI_SUCCESS;
06594 }

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 6689 of file pbx.c.

References ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_switch::description, ast_cli_args::fd, ast_switch::name, and ast_cli_entry::usage.

06690 {
06691    struct ast_switch *sw;
06692 
06693    switch (cmd) {
06694    case CLI_INIT:
06695       e->command = "core show switches";
06696       e->usage =
06697          "Usage: core show switches\n"
06698          "       List registered switches\n";
06699       return NULL;
06700    case CLI_GENERATE:
06701       return NULL;
06702    }
06703 
06704    AST_RWLIST_RDLOCK(&switches);
06705 
06706    if (AST_RWLIST_EMPTY(&switches)) {
06707       AST_RWLIST_UNLOCK(&switches);
06708       ast_cli(a->fd, "There are no registered alternative switches\n");
06709       return CLI_SUCCESS;
06710    }
06711 
06712    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
06713    AST_RWLIST_TRAVERSE(&switches, sw, list)
06714       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
06715 
06716    AST_RWLIST_UNLOCK(&switches);
06717 
06718    return CLI_SUCCESS;
06719 }

static int handle_statechange ( void *  datap  )  [static]

Definition at line 4893 of file pbx.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_extension_state3(), ast_free, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_hint::callbacks, ast_state_cb::change_cb, context_merge_lock, ast_state_cb::data, statechange::dev, ast_hint::exten, hints, ast_hint::laststate, parse(), and statecbs.

Referenced by device_state_cb().

04894 {
04895    struct ast_hint *hint;
04896    struct ast_str *hint_app;
04897    struct statechange *sc = datap;
04898    struct ao2_iterator i;
04899    struct ao2_iterator cb_iter;
04900    char context_name[AST_MAX_CONTEXT];
04901    char exten_name[AST_MAX_EXTENSION];
04902 
04903    hint_app = ast_str_create(1024);
04904    if (!hint_app) {
04905       ast_free(sc);
04906       return -1;
04907    }
04908 
04909    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
04910    i = ao2_iterator_init(hints, 0);
04911    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
04912       struct ast_state_cb *state_cb;
04913       char *cur, *parse;
04914       int state;
04915 
04916       ao2_lock(hint);
04917       if (!hint->exten) {
04918          /* The extension has already been destroyed */
04919          ao2_unlock(hint);
04920          continue;
04921       }
04922 
04923       /* Does this hint monitor the device that changed state? */
04924       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04925       parse = ast_str_buffer(hint_app);
04926       while ((cur = strsep(&parse, "&"))) {
04927          if (!strcasecmp(cur, sc->dev)) {
04928             /* The hint monitors the device. */
04929             break;
04930          }
04931       }
04932       if (!cur) {
04933          /* The hint does not monitor the device. */
04934          ao2_unlock(hint);
04935          continue;
04936       }
04937 
04938       /*
04939        * Save off strings in case the hint extension gets destroyed
04940        * while we are notifying the watchers.
04941        */
04942       ast_copy_string(context_name,
04943          ast_get_context_name(ast_get_extension_context(hint->exten)),
04944          sizeof(context_name));
04945       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
04946          sizeof(exten_name));
04947       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04948       ao2_unlock(hint);
04949 
04950       /*
04951        * Get device state for this hint.
04952        *
04953        * NOTE: We cannot hold any locks while determining the hint
04954        * device state or notifying the watchers without causing a
04955        * deadlock.  (conlock, hints, and hint)
04956        */
04957       state = ast_extension_state3(hint_app);
04958       if (state == hint->laststate) {
04959          continue;
04960       }
04961 
04962       /* Device state changed since last check - notify the watchers. */
04963       hint->laststate = state;   /* record we saw the change */
04964 
04965       /* For general callbacks */
04966       cb_iter = ao2_iterator_init(statecbs, 0);
04967       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04968          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04969       }
04970       ao2_iterator_destroy(&cb_iter);
04971 
04972       /* For extension callbacks */
04973       cb_iter = ao2_iterator_init(hint->callbacks, 0);
04974       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04975          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04976       }
04977       ao2_iterator_destroy(&cb_iter);
04978    }
04979    ao2_iterator_destroy(&i);
04980    ast_mutex_unlock(&context_merge_lock);
04981 
04982    ast_free(hint_app);
04983    ast_free(sc);
04984    return 0;
04985 }

static char* handle_unset_extenpatternmatchnew ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 7572 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.

07573 {
07574    int oldval = 0;
07575 
07576    switch (cmd) {
07577    case CLI_INIT:
07578       e->command = "dialplan set extenpatternmatchnew false";
07579       e->usage =
07580          "Usage: dialplan set extenpatternmatchnew true|false\n"
07581          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07582       return NULL;
07583    case CLI_GENERATE:
07584       return NULL;
07585    }
07586 
07587    if (a->argc != 4)
07588       return CLI_SHOWUSAGE;
07589 
07590    oldval =  pbx_set_extenpatternmatchnew(0);
07591 
07592    if (!oldval)
07593       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
07594    else
07595       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
07596 
07597    return CLI_SUCCESS;
07598 }

static int hashtab_compare_exten_labels ( const void *  ah_a,
const void *  ah_b 
) [static]

Definition at line 1137 of file pbx.c.

References ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

01138 {
01139    const struct ast_exten *ac = ah_a;
01140    const struct ast_exten *bc = ah_b;
01141    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01142 }

static int hashtab_compare_exten_numbers ( const void *  ah_a,
const void *  ah_b 
) [static]

Definition at line 1130 of file pbx.c.

References ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01131 {
01132    const struct ast_exten *ac = ah_a;
01133    const struct ast_exten *bc = ah_b;
01134    return ac->priority != bc->priority;
01135 }

static int hashtab_compare_extens ( const void *  ha_a,
const void *  ah_b 
) [static]

Definition at line 1102 of file pbx.c.

References AST_EXT_MATCHCID_ANY, AST_EXT_MATCHCID_OFF, ast_strlen_zero(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.

Referenced by ast_add_extension2_lockopt().

01103 {
01104    const struct ast_exten *ac = ah_a;
01105    const struct ast_exten *bc = ah_b;
01106    int x = strcmp(ac->exten, bc->exten);
01107    if (x) { /* if exten names are diff, then return */
01108       return x;
01109    }
01110 
01111    /* but if they are the same, do the cidmatch values match? */
01112    /* not sure which side may be using ast_ext_matchcid_types, so check both */
01113    if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) {
01114       return 0;
01115    }
01116    if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) {
01117       return 0;
01118    }
01119    if (ac->matchcid != bc->matchcid) {
01120       return 1;
01121    }
01122    /* all other cases already disposed of, match now required on callerid string (cidmatch) */
01123    /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
01124    if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) {
01125       return 0;
01126    }
01127    return strcmp(ac->cidmatch, bc->cidmatch);
01128 }

static unsigned int hashtab_hash_extens ( const void *  obj  )  [static]

Definition at line 1150 of file pbx.c.

References AST_EXT_MATCHCID_ON, ast_hashtab_hash_string(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.

Referenced by ast_add_extension2_lockopt().

01151 {
01152    const struct ast_exten *ac = obj;
01153    unsigned int x = ast_hashtab_hash_string(ac->exten);
01154    unsigned int y = 0;
01155    if (ac->matchcid == AST_EXT_MATCHCID_ON)
01156       y = ast_hashtab_hash_string(ac->cidmatch);
01157    return x+y;
01158 }

static unsigned int hashtab_hash_labels ( const void *  obj  )  [static]

Definition at line 1166 of file pbx.c.

References ast_hashtab_hash_string(), ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

01167 {
01168    const struct ast_exten *ac = obj;
01169    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01170 }

static unsigned int hashtab_hash_priority ( const void *  obj  )  [static]

Definition at line 1160 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01161 {
01162    const struct ast_exten *ac = obj;
01163    return ast_hashtab_hash_int(ac->priority);
01164 }

static int hint_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 11203 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_hint::exten.

Referenced by ast_pbx_init().

11204 {
11205    const struct ast_hint *hint = obj;
11206    const struct ast_exten *exten = arg;
11207 
11208    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
11209 }

static int hint_hash ( const void *  obj,
const int  flags 
) [static]

Definition at line 11183 of file pbx.c.

References ast_get_extension_name(), ast_str_case_hash(), ast_strlen_zero(), ast_hint::exten, and ast_hint::exten_name.

Referenced by ast_pbx_init().

11184 {
11185    const struct ast_hint *hint = obj;
11186    const char *exten_name;
11187    int res;
11188 
11189    exten_name = ast_get_extension_name(hint->exten);
11190    if (ast_strlen_zero(exten_name)) {
11191       /*
11192        * If the exten or extension name isn't set, return 0 so that
11193        * the ao2_find() search will start in the first bucket.
11194        */
11195       res = 0;
11196    } else {
11197       res = ast_str_case_hash(exten_name);
11198    }
11199 
11200    return res;
11201 }

static int hint_id_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 5148 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

05149 {
05150    const struct ast_state_cb *cb = obj;
05151    int *id = arg;
05152 
05153    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
05154 }

static int hints_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 10756 of file pbx.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_hint::exten, hints, and ast_hint::laststate.

10758 {
10759    struct ast_data *data_hint;
10760    struct ast_hint *hint;
10761    int watchers;
10762    struct ao2_iterator i;
10763 
10764    if (ao2_container_count(hints) == 0) {
10765       return 0;
10766    }
10767 
10768    i = ao2_iterator_init(hints, 0);
10769    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
10770       watchers = ao2_container_count(hint->callbacks);
10771       data_hint = ast_data_add_node(data_root, "hint");
10772       if (!data_hint) {
10773          continue;
10774       }
10775       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
10776       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
10777       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
10778       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
10779       ast_data_add_int(data_hint, "watchers", watchers);
10780 
10781       if (!ast_data_search_match(search, data_hint)) {
10782          ast_data_remove_node(data_root, data_hint);
10783       }
10784    }
10785    ao2_iterator_destroy(&i);
10786 
10787    return 0;
10788 }

static int include_valid ( struct ast_include i  )  [inline, static]

Definition at line 1523 of file pbx.c.

References ast_check_timing(), ast_include::hastime, and ast_include::timing.

Referenced by pbx_find_extension().

01524 {
01525    if (!i->hastime)
01526       return 1;
01527 
01528    return ast_check_timing(&(i->timing));
01529 }

static int increase_call_count ( const struct ast_channel c  )  [static]

Increase call count for channel.

Return values:
0 on success
non-zero if a configured limit (maxcalls, maxload, minmemfree) was reached

Definition at line 5743 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, countcalls, LOG_WARNING, maxcalllock, option_maxcalls, option_maxload, option_minmemfree, and totalcalls.

Referenced by ast_pbx_run_args(), and ast_pbx_start().

05744 {
05745    int failed = 0;
05746    double curloadavg;
05747 #if defined(HAVE_SYSINFO)
05748    long curfreemem;
05749    struct sysinfo sys_info;
05750 #endif
05751 
05752    ast_mutex_lock(&maxcalllock);
05753    if (option_maxcalls) {
05754       if (countcalls >= option_maxcalls) {
05755          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
05756          failed = -1;
05757       }
05758    }
05759    if (option_maxload) {
05760       getloadavg(&curloadavg, 1);
05761       if (curloadavg >= option_maxload) {
05762          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
05763          failed = -1;
05764       }
05765    }
05766 #if defined(HAVE_SYSINFO)
05767    if (option_minmemfree) {
05768       if (!sysinfo(&sys_info)) {
05769          /* make sure that the free system memory is above the configured low watermark
05770           * convert the amount of freeram from mem_units to MB */
05771          curfreemem = sys_info.freeram * sys_info.mem_unit;
05772          curfreemem /= 1024 * 1024;
05773          if (curfreemem < option_minmemfree) {
05774             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
05775             failed = -1;
05776          }
05777       }
05778    }
05779 #endif
05780 
05781    if (!failed) {
05782       countcalls++;
05783       totalcalls++;
05784    }
05785    ast_mutex_unlock(&maxcalllock);
05786 
05787    return failed;
05788 }

static void insert_in_next_chars_alt_char_list ( struct match_char **  parent_ptr,
struct match_char node 
) [static]

Definition at line 1941 of file pbx.c.

References match_char::alt_char, and match_char::specificity.

Referenced by add_pattern_node().

01942 {
01943    struct match_char *curr, *lcurr;
01944 
01945    /* insert node into the tree at "current", so the alt_char list from current is
01946       sorted in increasing value as you go to the leaves */
01947    if (!(*parent_ptr)) {
01948       *parent_ptr = node;
01949       return;
01950    }
01951 
01952    if ((*parent_ptr)->specificity > node->specificity) {
01953       /* insert at head */
01954       node->alt_char = (*parent_ptr);
01955       *parent_ptr = node;
01956       return;
01957    } 
01958 
01959    lcurr = *parent_ptr;
01960    for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
01961       if (curr->specificity > node->specificity) {
01962          node->alt_char = curr;
01963          lcurr->alt_char = node;
01964          break;
01965       }
01966       lcurr = curr;
01967    }
01968 
01969    if (!curr) {
01970       lcurr->alt_char = node;
01971    }
01972 
01973 }

static int is_read_allowed ( struct ast_custom_function acfptr  )  [static]

Determines whether execution of a custom function's read function is allowed.

Parameters:
acfptr Custom function to check
Returns:
True (non-zero) if reading is allowed.
False (zero) if reading is not allowed.

Definition at line 4076 of file pbx.c.

References ast_debug, ast_custom_function::name, read_escalates(), and thread_inhibits_escalations().

Referenced by ast_func_read(), and ast_func_read2().

04077 {
04078    if (!acfptr) {
04079       return 1;
04080    }
04081 
04082    if (!read_escalates(acfptr)) {
04083       return 1;
04084    }
04085 
04086    if (!thread_inhibits_escalations()) {
04087       return 1;
04088    }
04089 
04090    if (live_dangerously) {
04091       /* Global setting overrides the thread's preference */
04092       ast_debug(2, "Reading %s from a dangerous context\n",
04093          acfptr->name);
04094       return 1;
04095    }
04096 
04097    /* We have no reason to allow this function to execute */
04098    return 0;
04099 }

static int is_write_allowed ( struct ast_custom_function acfptr  )  [static]

Determines whether execution of a custom function's write function is allowed.

Parameters:
acfptr Custom function to check
Returns:
True (non-zero) if writing is allowed.
False (zero) if writing is not allowed.

Definition at line 4109 of file pbx.c.

References ast_debug, ast_custom_function::name, thread_inhibits_escalations(), and write_escalates().

Referenced by ast_func_write().

04110 {
04111    if (!acfptr) {
04112       return 1;
04113    }
04114 
04115    if (!write_escalates(acfptr)) {
04116       return 1;
04117    }
04118 
04119    if (!thread_inhibits_escalations()) {
04120       return 1;
04121    }
04122 
04123    if (live_dangerously) {
04124       /* Global setting overrides the thread's preference */
04125       ast_debug(2, "Writing %s from a dangerous context\n",
04126          acfptr->name);
04127       return 1;
04128    }
04129 
04130    /* We have no reason to allow this function to execute */
04131    return 0;
04132 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 10824 of file pbx.c.

References __ast_custom_function_register(), ARRAY_LEN, ast_cli_register_multiple(), ast_data_register_multiple_core, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register_xml, ast_register_application2(), ast_register_atexit(), ast_taskprocessor_get(), ast_verb, builtins, device_state_cb(), device_state_sub, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), pbx_cli, pbx_data_providers, testtime_function, and unload_pbx().

Referenced by main().

10825 {
10826    int x;
10827 
10828    ast_register_atexit(unload_pbx);
10829 
10830    /* Initialize the PBX */
10831    ast_verb(1, "Asterisk PBX Core Initializing\n");
10832    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
10833       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
10834    }
10835 
10836    ast_verb(1, "Registering builtin applications:\n");
10837    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
10838    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
10839    __ast_custom_function_register(&exception_function, NULL);
10840    __ast_custom_function_register(&testtime_function, NULL);
10841 
10842    /* Register builtin applications */
10843    for (x = 0; x < ARRAY_LEN(builtins); x++) {
10844       ast_verb(1, "[%s]\n", builtins[x].name);
10845       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
10846          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
10847          return -1;
10848       }
10849    }
10850 
10851    /* Register manager application */
10852    ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
10853 
10854    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
10855          AST_EVENT_IE_END))) {
10856       return -1;
10857    }
10858 
10859    return 0;
10860 }

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 8082 of file pbx.c.

Referenced by get_range().

08083 {
08084    int i;
08085 
08086    if (names && *s > '9') {
08087       for (i = 0; names[i]; i++) {
08088          if (!strcasecmp(s, names[i])) {
08089             return i;
08090          }
08091       }
08092    }
08093 
08094    /* Allow months and weekdays to be specified as numbers, as well */
08095    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
08096       /* What the array offset would have been: "1" would be at offset 0 */
08097       return i - 1;
08098    }
08099    return -1; /* error return */
08100 }

static void manager_dpsendack ( struct mansession s,
const struct message m 
) [static]

Send ack once.

Definition at line 7190 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

07191 {
07192    astman_send_listack(s, m, "DialPlan list will follow", "start");
07193 }

static int manager_show_dialplan ( struct mansession s,
const struct message m 
) [static]

Manager listing of dial plan.

Definition at line 7335 of file pbx.c.

References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, manager_dpsendack(), manager_show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by load_pbx().

07336 {
07337    const char *exten, *context;
07338    const char *id = astman_get_header(m, "ActionID");
07339    char idtext[256];
07340 
07341    /* Variables used for different counters */
07342    struct dialplan_counters counters;
07343 
07344    if (!ast_strlen_zero(id))
07345       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
07346    else
07347       idtext[0] = '\0';
07348 
07349    memset(&counters, 0, sizeof(counters));
07350 
07351    exten = astman_get_header(m, "Extension");
07352    context = astman_get_header(m, "Context");
07353 
07354    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
07355 
07356    if (!ast_strlen_zero(context) && !counters.context_existence) {
07357       char errorbuf[BUFSIZ];
07358 
07359       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
07360       astman_send_error(s, m, errorbuf);
07361       return 0;
07362    }
07363    if (!ast_strlen_zero(exten) && !counters.extension_existence) {
07364       char errorbuf[BUFSIZ];
07365 
07366       if (!ast_strlen_zero(context))
07367          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
07368       else
07369          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
07370       astman_send_error(s, m, errorbuf);
07371       return 0;
07372    }
07373 
07374    if (!counters.total_items) {
07375       manager_dpsendack(s, m);
07376    }
07377 
07378    astman_append(s, "Event: ShowDialPlanComplete\r\n"
07379       "EventList: Complete\r\n"
07380       "ListItems: %d\r\n"
07381       "ListExtensions: %d\r\n"
07382       "ListPriorities: %d\r\n"
07383       "ListContexts: %d\r\n"
07384       "%s"
07385       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
07386 
07387    /* everything ok */
07388    return 0;
07389 }

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 7199 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().

07203 {
07204    struct ast_context *c;
07205    int res = 0, old_total_exten = dpc->total_exten;
07206 
07207    if (ast_strlen_zero(exten))
07208       exten = NULL;
07209    if (ast_strlen_zero(context))
07210       context = NULL;
07211 
07212    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
07213 
07214    /* try to lock contexts */
07215    if (ast_rdlock_contexts()) {
07216       astman_send_error(s, m, "Failed to lock contexts");
07217       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
07218       return -1;
07219    }
07220 
07221    c = NULL;      /* walk all contexts ... */
07222    while ( (c = ast_walk_contexts(c)) ) {
07223       struct ast_exten *e;
07224       struct ast_include *i;
07225       struct ast_ignorepat *ip;
07226 
07227       if (context && strcmp(ast_get_context_name(c), context) != 0)
07228          continue;   /* not the name we want */
07229 
07230       dpc->context_existence = 1;
07231       dpc->total_context++;
07232 
07233       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
07234 
07235       if (ast_rdlock_context(c)) {  /* failed to lock */
07236          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
07237          continue;
07238       }
07239 
07240       /* XXX note- an empty context is not printed */
07241       e = NULL;      /* walk extensions in context  */
07242       while ( (e = ast_walk_context_extensions(c, e)) ) {
07243          struct ast_exten *p;
07244 
07245          /* looking for extension? is this our extension? */
07246          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
07247             /* not the one we are looking for, continue */
07248             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
07249             continue;
07250          }
07251          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
07252 
07253          dpc->extension_existence = 1;
07254 
07255          dpc->total_exten++;
07256 
07257          p = NULL;      /* walk next extension peers */
07258          while ( (p = ast_walk_extension_priorities(e, p)) ) {
07259             int prio = ast_get_extension_priority(p);
07260 
07261             dpc->total_prio++;
07262             if (!dpc->total_items++)
07263                manager_dpsendack(s, m);
07264             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07265             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
07266 
07267             /* XXX maybe make this conditional, if p != e ? */
07268             if (ast_get_extension_label(p))
07269                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
07270 
07271             if (prio == PRIORITY_HINT) {
07272                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
07273             } else {
07274                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));
07275             }
07276             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
07277          }
07278       }
07279 
07280       i = NULL;      /* walk included and write info ... */
07281       while ( (i = ast_walk_context_includes(c, i)) ) {
07282          if (exten) {
07283             /* Check all includes for the requested extension */
07284             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
07285          } else {
07286             if (!dpc->total_items++)
07287                manager_dpsendack(s, m);
07288             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07289             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));
07290             astman_append(s, "\r\n");
07291             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
07292          }
07293       }
07294 
07295       ip = NULL;  /* walk ignore patterns and write info ... */
07296       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
07297          const char *ipname = ast_get_ignorepat_name(ip);
07298          char ignorepat[AST_MAX_EXTENSION];
07299 
07300          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
07301          if (!exten || ast_extension_match(ignorepat, exten)) {
07302             if (!dpc->total_items++)
07303                manager_dpsendack(s, m);
07304             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07305             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
07306             astman_append(s, "\r\n");
07307          }
07308       }
07309       if (!rinclude) {
07310          struct ast_sw *sw = NULL;
07311          while ( (sw = ast_walk_context_switches(c, sw)) ) {
07312             if (!dpc->total_items++)
07313                manager_dpsendack(s, m);
07314             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07315             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));  
07316             astman_append(s, "\r\n");
07317             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
07318          }
07319       }
07320 
07321       ast_unlock_context(c);
07322    }
07323    ast_unlock_contexts();
07324 
07325    if (dpc->total_exten == old_total_exten) {
07326       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
07327       /* Nothing new under the sun */
07328       return -1;
07329    } else {
07330       return res;
07331    }
07332 }

static int matchcid ( const char *  cidpattern,
const char *  callerid 
) [static]

Definition at line 2959 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

02960 {
02961    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02962       failing to get a number should count as a match, otherwise not */
02963 
02964    if (ast_strlen_zero(callerid)) {
02965       return ast_strlen_zero(cidpattern) ? 1 : 0;
02966    }
02967 
02968    return ast_extension_match(cidpattern, callerid);
02969 }

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 1765 of file pbx.c.

References match_char::alt_char, ast_debug, ast_log(), scoreboard::canmatch, match_char::deleted, E_CANMATCH, E_MATCHMORE, ast_exten::exten, scoreboard::exten, match_char::exten, match_char::is_pattern, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, NEW_MATCHER_RECURSE, match_char::next_char, match_char::specificity, update_scoreboard(), and match_char::x.

Referenced by pbx_find_extension().

01766 {
01767    struct match_char *p; /* note minimal stack storage requirements */
01768    struct ast_exten pattern = { .label = label };
01769 #ifdef DEBUG_THIS
01770    if (tree)
01771       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
01772    else
01773       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
01774 #endif
01775    for (p = tree; p; p = p->alt_char) {
01776       if (p->is_pattern) {
01777          if (p->x[0] == 'N') {
01778             if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
01779 #define  NEW_MATCHER_CHK_MATCH          \
01780                if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */             \
01781                   if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */   \
01782                      update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p);                 \
01783                      if (!p->deleted) {                                                                                           \
01784                         if (action == E_FINDLABEL) {                                                                             \
01785                            if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) {                                  \
01786                               ast_debug(4, "Found label in preferred extension\n");                                            \
01787                               return;                                                                                          \
01788                            }                                                                                                    \
01789                         } else {                                                                                                 \
01790                            ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten);                       \
01791                            return; /* the first match, by definition, will be the best, because of the sorted tree */           \
01792                         }                                                                                                        \
01793                      }                                                                                                            \
01794                   }                                                                                                                \
01795                }
01796                
01797 #define  NEW_MATCHER_RECURSE             \
01798                if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0)                 \
01799                                                 || p->next_char->x[0] == '!')) {                                          \
01800                   if (*(str + 1) || p->next_char->x[0] == '!') {                                                         \
01801                      new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
01802                      if (score->exten)  {                                                                             \
01803                           ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten);                         \
01804                         return; /* the first match is all we need */                                                 \
01805                      }                                                                                    \
01806                   } else {                                                                                             \
01807                      new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action);    \
01808                      if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {      \
01809                           ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten :     \
01810                                         "NULL");                                                                        \
01811                         return; /* the first match is all we need */                                                 \
01812                      }                                                                                    \
01813                   }                                                                                                    \
01814                } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) {                                                                  \
01815                   score->canmatch = 1;                                                                                 \
01816                   score->canmatch_exten = get_canmatch_exten(p);                                                       \
01817                   if (action == E_CANMATCH || action == E_MATCHMORE) {                                                 \
01818                        ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str);                                  \
01819                      return;                                                                                          \
01820                   }                                                                                        \
01821                }
01822                
01823                NEW_MATCHER_CHK_MATCH;
01824                NEW_MATCHER_RECURSE;
01825             }
01826          } else if (p->x[0] == 'Z') {
01827             if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
01828                NEW_MATCHER_CHK_MATCH;
01829                NEW_MATCHER_RECURSE;
01830             }
01831          } else if (p->x[0] == 'X') { 
01832             if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
01833                NEW_MATCHER_CHK_MATCH;
01834                NEW_MATCHER_RECURSE;
01835             }
01836          } else if (p->x[0] == '.' && p->x[1] == 0) {
01837             /* how many chars will the . match against? */
01838             int i = 0;
01839             const char *str2 = str;
01840             while (*str2 && *str2 != '/') {
01841                str2++;
01842                i++;
01843             }
01844             if (p->exten && *str2 != '/') {
01845                update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
01846                if (score->exten) {
01847                   ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
01848                   return; /* the first match is all we need */
01849                }
01850             }
01851             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01852                new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
01853                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01854                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
01855                   return; /* the first match is all we need */
01856                }
01857             }
01858          } else if (p->x[0] == '!' && p->x[1] == 0) {
01859             /* how many chars will the . match against? */
01860             int i = 1;
01861             const char *str2 = str;
01862             while (*str2 && *str2 != '/') {
01863                str2++;
01864                i++;
01865             }
01866             if (p->exten && *str2 != '/') {
01867                update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
01868                if (score->exten) {
01869                   ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
01870                   return; /* the first match is all we need */
01871                }
01872             }
01873             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01874                new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
01875                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01876                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
01877                   return; /* the first match is all we need */
01878                }
01879             }
01880          } else if (p->x[0] == '/' && p->x[1] == 0) {
01881             /* the pattern in the tree includes the cid match! */
01882             if (p->next_char && callerid && *callerid) {
01883                new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
01884                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01885                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
01886                   return; /* the first match is all we need */
01887                }
01888             }
01889          } else if (strchr(p->x, *str)) {
01890             ast_debug(4, "Nothing strange about this match\n");
01891             NEW_MATCHER_CHK_MATCH;
01892             NEW_MATCHER_RECURSE;
01893          }
01894       } else if (strchr(p->x, *str)) {
01895          ast_debug(4, "Nothing strange about this match\n");
01896          NEW_MATCHER_CHK_MATCH;
01897          NEW_MATCHER_RECURSE;
01898       }
01899    }
01900    ast_debug(4, "return at end of func\n");
01901 }

static int parse_variable_name ( char *  var,
int *  offset,
int *  length,
int *  isfunc 
) [static]

extract offset:length from variable name.

Returns:
1 if there is a offset:length part, which is trimmed off (values go into variables)

Definition at line 3269 of file pbx.c.

Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().

03270 {
03271    int parens = 0;
03272 
03273    *offset = 0;
03274    *length = INT_MAX;
03275    *isfunc = 0;
03276    for (; *var; var++) {
03277       if (*var == '(') {
03278          (*isfunc)++;
03279          parens++;
03280       } else if (*var == ')') {
03281          parens--;
03282       } else if (*var == ':' && parens == 0) {
03283          *var++ = '\0';
03284          sscanf(var, "%30d:%30d", offset, length);
03285          return 1; /* offset:length valid */
03286       }
03287    }
03288    return 0;
03289 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 10632 of file pbx.c.

References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), globals, and globalslock.

Referenced by handle_cli_dialplan_reload(), pbx_shutdown(), and reload().

10633 {
10634    struct ast_var_t *vardata;
10635 
10636    ast_rwlock_wrlock(&globalslock);
10637    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10638       ast_var_delete(vardata);
10639    ast_rwlock_unlock(&globalslock);
10640 }

const char* pbx_builtin_getvar_helper ( struct ast_channel chan,
const char *  name 
)

Return a pointer to the value of the corresponding channel variable.

Note:
Will lock the channel.
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 10398 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.

Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_exec(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().

10399 {
10400    struct ast_var_t *variables;
10401    const char *ret = NULL;
10402    int i;
10403    struct varshead *places[2] = { NULL, &globals };
10404 
10405    if (!name)
10406       return NULL;
10407 
10408    if (chan) {
10409       ast_channel_lock(chan);
10410       places[0] = &chan->varshead;
10411    }
10412 
10413    for (i = 0; i < 2; i++) {
10414       if (!places[i])
10415          continue;
10416       if (places[i] == &globals)
10417          ast_rwlock_rdlock(&globalslock);
10418       AST_LIST_TRAVERSE(places[i], variables, entries) {
10419          if (!strcmp(name, ast_var_name(variables))) {
10420             ret = ast_var_value(variables);
10421             break;
10422          }
10423       }
10424       if (places[i] == &globals)
10425          ast_rwlock_unlock(&globalslock);
10426       if (ret)
10427          break;
10428    }
10429 
10430    if (chan)
10431       ast_channel_unlock(chan);
10432 
10433    return ret;
10434 }

static int pbx_builtin_gotoif ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 10654 of file pbx.c.

References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), and pbx_checkcondition().

10655 {
10656    char *condition, *branch1, *branch2, *branch;
10657    char *stringp;
10658 
10659    if (ast_strlen_zero(data)) {
10660       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
10661       return 0;
10662    }
10663 
10664    stringp = ast_strdupa(data);
10665    condition = strsep(&stringp,"?");
10666    branch1 = strsep(&stringp,":");
10667    branch2 = strsep(&stringp,"");
10668    branch = pbx_checkcondition(condition) ? branch1 : branch2;
10669 
10670    if (ast_strlen_zero(branch)) {
10671       ast_debug(1, "Not taking any branch\n");
10672       return 0;
10673    }
10674 
10675    return pbx_builtin_goto(chan, branch);
10676 }

int pbx_builtin_importvar ( struct ast_channel chan,
const char *  data 
) [static]

Todo:
XXX should do !ast_strlen_zero(..) of the args ?

Definition at line 10592 of file pbx.c.

References ast_alloca, ast_channel_get_by_name(), ast_channel_unref, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), value, and VAR_BUF_SIZE.

10593 {
10594    char *name;
10595    char *value;
10596    char *channel;
10597    char tmp[VAR_BUF_SIZE];
10598    static int deprecation_warning = 0;
10599 
10600    if (ast_strlen_zero(data)) {
10601       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
10602       return 0;
10603    }
10604    tmp[0] = 0;
10605    if (!deprecation_warning) {
10606       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
10607       deprecation_warning = 1;
10608    }
10609 
10610    value = ast_strdupa(data);
10611    name = strsep(&value,"=");
10612    channel = strsep(&value,",");
10613    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
10614       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
10615       if (chan2) {
10616          char *s = ast_alloca(strlen(value) + 4);
10617          sprintf(s, "${%s}", value);
10618          pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
10619          chan2 = ast_channel_unref(chan2);
10620       }
10621       pbx_builtin_setvar_helper(chan, name, tmp);
10622    }
10623 
10624    return(0);
10625 }

static int pbx_builtin_incomplete ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 9919 of file pbx.c.

References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_CONTROL_INCOMPLETE, ast_indicate(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().

09920 {
09921    const char *options = data;
09922    int answer = 1;
09923 
09924    /* Some channels can receive DTMF in unanswered state; some cannot */
09925    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
09926       answer = 0;
09927    }
09928 
09929    /* If the channel is hungup, stop waiting */
09930    if (ast_check_hangup(chan)) {
09931       return -1;
09932    } else if (chan->_state != AST_STATE_UP && answer) {
09933       __ast_answer(chan, 0, 1);
09934    }
09935 
09936    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
09937 
09938    return AST_PBX_INCOMPLETE;
09939 }

static int pbx_builtin_noop ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 10627 of file pbx.c.

10628 {
10629    return 0;
10630 }

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.

Note:
Will lock the channel.

Definition at line 10436 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.

Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().

10437 {
10438    struct ast_var_t *newvariable;
10439    struct varshead *headp;
10440 
10441    if (name[strlen(name)-1] == ')') {
10442       char *function = ast_strdupa(name);
10443 
10444       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10445       ast_func_write(chan, function, value);
10446       return;
10447    }
10448 
10449    if (chan) {
10450       ast_channel_lock(chan);
10451       headp = &chan->varshead;
10452    } else {
10453       ast_rwlock_wrlock(&globalslock);
10454       headp = &globals;
10455    }
10456 
10457    if (value && (newvariable = ast_var_assign(name, value))) {
10458       if (headp == &globals)
10459          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10460       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10461    }
10462 
10463    if (chan)
10464       ast_channel_unlock(chan);
10465    else
10466       ast_rwlock_unlock(&globalslock);
10467 }

int pbx_builtin_raise_exception ( struct ast_channel chan,
const char *  reason 
)

Definition at line 3578 of file pbx.c.

References raise_exception().

03579 {
03580    /* Priority will become 1, next time through the AUTOLOOP */
03581    return raise_exception(chan, reason, 0);
03582 }

static int pbx_builtin_saycharacters ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 10715 of file pbx.c.

References ast_say_character_str().

10716 {
10717    int res = 0;
10718 
10719    if (data)
10720       res = ast_say_character_str(chan, data, "", chan->language);
10721    return res;
10722 }

static int pbx_builtin_saydigits ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 10706 of file pbx.c.

References ast_say_digit_str().

10707 {
10708    int res = 0;
10709 
10710    if (data)
10711       res = ast_say_digit_str(chan, data, "", chan->language);
10712    return res;
10713 }

static int pbx_builtin_saynumber ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 10678 of file pbx.c.

References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), and LOG_WARNING.

10679 {
10680    char tmp[256];
10681    char *number = tmp;
10682    char *options;
10683 
10684    if (ast_strlen_zero(data)) {
10685       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
10686       return -1;
10687    }
10688    ast_copy_string(tmp, data, sizeof(tmp));
10689    strsep(&number, ",");
10690    options = strsep(&number, ",");
10691    if (options) {
10692       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
10693          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
10694          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
10695          return -1;
10696       }
10697    }
10698 
10699    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
10700       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
10701    }
10702 
10703    return 0;
10704 }

static int pbx_builtin_sayphonetic ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 10724 of file pbx.c.

References ast_say_phonetic_str().

10725 {
10726    int res = 0;
10727 
10728    if (data)
10729       res = ast_say_phonetic_str(chan, data, "", chan->language);
10730    return res;
10731 }

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.

Parameters:
chan Channel from which to read variables
buf Dynamic string in which to place the result (should be allocated with ast_str_create).
See also:
ast_str_create
Note:
Will lock the channel.

Definition at line 10367 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.

Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().

10368 {
10369    struct ast_var_t *variables;
10370    const char *var, *val;
10371    int total = 0;
10372 
10373    if (!chan)
10374       return 0;
10375 
10376    ast_str_reset(*buf);
10377 
10378    ast_channel_lock(chan);
10379 
10380    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10381       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10382          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10383          ) {
10384          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10385             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10386             break;
10387          } else
10388             total++;
10389       } else
10390          break;
10391    }
10392 
10393    ast_channel_unlock(chan);
10394 
10395    return total;
10396 }

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.

Note:
Will lock the channel.

Definition at line 10526 of file pbx.c.

References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), and value.

Referenced by ast_compile_ael2().

10527 {
10528    char *name, *value, *mydata;
10529 
10530    if (ast_compat_app_set) {
10531       return pbx_builtin_setvar_multiple(chan, data);
10532    }
10533 
10534    if (ast_strlen_zero(data)) {
10535       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10536       return 0;
10537    }
10538 
10539    mydata = ast_strdupa(data);
10540    name = strsep(&mydata, "=");
10541    value = mydata;
10542    if (!value) {
10543       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10544       return 0;
10545    }
10546 
10547    if (strchr(name, ' ')) {
10548       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10549    }
10550 
10551    pbx_builtin_setvar_helper(chan, name, value);
10552 
10553    return 0;
10554 }

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.

Note:
Will lock the channel. May also be used to set a channel dialplan function to a particular value.
See also:
ast_func_write
Returns:
-1 if the dialplan function fails to be set
Version:
1.8 changed the function to return an error code

Definition at line 10469 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.

Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().

10470 {
10471    struct ast_var_t *newvariable;
10472    struct varshead *headp;
10473    const char *nametail = name;
10474 
10475    if (name[strlen(name) - 1] == ')') {
10476       char *function = ast_strdupa(name);
10477 
10478       return ast_func_write(chan, function, value);
10479    }
10480 
10481    if (chan) {
10482       ast_channel_lock(chan);
10483       headp = &chan->varshead;
10484    } else {
10485       ast_rwlock_wrlock(&globalslock);
10486       headp = &globals;
10487    }
10488 
10489    /* For comparison purposes, we have to strip leading underscores */
10490    if (*nametail == '_') {
10491       nametail++;
10492       if (*nametail == '_')
10493          nametail++;
10494    }
10495 
10496    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10497       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10498          /* there is already such a variable, delete it */
10499          AST_LIST_REMOVE_CURRENT(entries);
10500          ast_var_delete(newvariable);
10501          break;
10502       }
10503    }
10504    AST_LIST_TRAVERSE_SAFE_END;
10505 
10506    if (value && (newvariable = ast_var_assign(name, value))) {
10507       if (headp == &globals)
10508          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10509       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10510       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10511          "Channel: %s\r\n"
10512          "Variable: %s\r\n"
10513          "Value: %s\r\n"
10514          "Uniqueid: %s\r\n",
10515          chan ? chan->name : "none", name, value,
10516          chan ? chan->uniqueid : "none");
10517    }
10518 
10519    if (chan)
10520       ast_channel_unlock(chan);
10521    else
10522       ast_rwlock_unlock(&globalslock);
10523    return 0;
10524 }

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.

Note:
Will lock the channel.

Definition at line 10556 of file pbx.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, pbx_builtin_setvar_helper(), ast_channel::priority, and value.

Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().

10557 {
10558    char *data;
10559    int x;
10560    AST_DECLARE_APP_ARGS(args,
10561       AST_APP_ARG(pair)[24];
10562    );
10563    AST_DECLARE_APP_ARGS(pair,
10564       AST_APP_ARG(name);
10565       AST_APP_ARG(value);
10566    );
10567 
10568    if (ast_strlen_zero(vdata)) {
10569       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10570       return 0;
10571    }
10572 
10573    data = ast_strdupa(vdata);
10574    AST_STANDARD_APP_ARGS(args, data);
10575 
10576    for (x = 0; x < args.argc; x++) {
10577       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10578       if (pair.argc == 2) {
10579          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10580          if (strchr(pair.name, ' '))
10581             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);
10582       } else if (!chan) {
10583          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10584       } else {
10585          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10586       }
10587    }
10588 
10589    return 0;
10590 }

int pbx_checkcondition ( const char *  condition  ) 

Evaluate a condition.

Return values:
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 10642 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().

10643 {
10644    int res;
10645    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10646       return 0;
10647    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10648       return res;
10649    } else {                                         /* Strings are true */
10650       return 1;
10651    }
10652 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1531 of file pbx.c.

References ast_free.

Referenced by __ast_pbx_run().

01532 {
01533    ast_free(p);
01534 }

int pbx_exec ( struct ast_channel c,
struct ast_app app,
const char *  data 
)

Execute an application.

Parameters:
c channel to execute on
app which app to execute
data the data passed into the app

This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.

Return values:
0 success
-1 failure
Parameters:
c Channel
app Application
data Data for execution

Definition at line 1451 of file pbx.c.

References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.

Referenced by aelsub_exec(), answer_exec_run(), ast_app_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(), realtime_exec(), try_calling(), and tryexec_exec().

01454 {
01455    int res;
01456    struct ast_module_user *u = NULL;
01457    const char *saved_c_appl;
01458    const char *saved_c_data;
01459 
01460    if (c->cdr && !ast_check_hangup(c))
01461       ast_cdr_setapp(c->cdr, app->name, data);
01462 
01463    /* save channel values */
01464    saved_c_appl= c->appl;
01465    saved_c_data= c->data;
01466 
01467    c->appl = app->name;
01468    c->data = data;
01469    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01470 
01471    if (app->module)
01472       u = __ast_module_user_add(app->module, c);
01473    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01474          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01475       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01476          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01477          app->name, (char *) data);
01478    }
01479    res = app->execute(c, S_OR(data, ""));
01480    if (app->module && u)
01481       __ast_module_user_remove(app->module, u);
01482    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01483    /* restore channel values */
01484    c->appl = saved_c_appl;
01485    c->data = saved_c_data;
01486    return res;
01487 }

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,

Return values:
0 on success.
-1 on failure.
Note:
The channel is auto-serviced in this function, because doing an extension match may block for a long time. For example, if the lookup has to use a network dialplan switch, such as DUNDi or IAX2, it may take a while. However, the channel auto-service code will queue up any important signalling frames to be processed after this is done.

Definition at line 4663 of file pbx.c.

References ast_exten::app, app, ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_strdupa, ast_strlen_zero(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, ast_exten::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_DIALPLAN, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, manager_event, ast_switch::name, ast_app::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables_helper(), ast_channel::priority, ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), and VERBOSITY_ATLEAST.

Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().

04666 {
04667    struct ast_exten *e;
04668    struct ast_app *app;
04669    char *substitute = NULL;
04670    int res;
04671    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04672    char passdata[EXT_DATA_SIZE];
04673 
04674    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04675 
04676    ast_rdlock_contexts();
04677    if (found)
04678       *found = 0;
04679 
04680    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04681    if (e) {
04682       if (found)
04683          *found = 1;
04684       if (matching_action) {
04685          ast_unlock_contexts();
04686          return -1;  /* success, we found it */
04687       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04688          res = e->priority;
04689          ast_unlock_contexts();
04690          return res; /* the priority we were looking for */
04691       } else { /* spawn */
04692          if (!e->cached_app)
04693             e->cached_app = pbx_findapp(e->app);
04694          app = e->cached_app;
04695          if (ast_strlen_zero(e->data)) {
04696             *passdata = '\0';
04697          } else {
04698             const char *tmp;
04699             if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
04700                /* no variables to substitute, copy on through */
04701                ast_copy_string(passdata, e->data, sizeof(passdata));
04702             } else {
04703                /* save e->data on stack for later processing after lock released */
04704                substitute = ast_strdupa(e->data);
04705             }
04706          }
04707          ast_unlock_contexts();
04708          if (!app) {
04709             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04710             return -1;
04711          }
04712          if (c->context != context)
04713             ast_copy_string(c->context, context, sizeof(c->context));
04714          if (c->exten != exten)
04715             ast_copy_string(c->exten, exten, sizeof(c->exten));
04716          c->priority = priority;
04717          if (substitute) {
04718             pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
04719          }
04720 #ifdef CHANNEL_TRACE
04721          ast_channel_trace_update(c);
04722 #endif
04723          ast_debug(1, "Launching '%s'\n", app->name);
04724          if (VERBOSITY_ATLEAST(3)) {
04725             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
04726             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
04727                exten, context, priority,
04728                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
04729                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
04730                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
04731                "in new stack");
04732          }
04733          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
04734                "Channel: %s\r\n"
04735                "Context: %s\r\n"
04736                "Extension: %s\r\n"
04737                "Priority: %d\r\n"
04738                "Application: %s\r\n"
04739                "AppData: %s\r\n"
04740                "Uniqueid: %s\r\n",
04741                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
04742          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04743       }
04744    } else if (q.swo) {  /* not found here, but in another switch */
04745       if (found)
04746          *found = 1;
04747       ast_unlock_contexts();
04748       if (matching_action) {
04749          return -1;
04750       } else {
04751          if (!q.swo->exec) {
04752             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04753             res = -1;
04754          }
04755          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04756       }
04757    } else { /* not found anywhere, see what happened */
04758       ast_unlock_contexts();
04759       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04760       switch (q.status) {
04761       case STATUS_NO_CONTEXT:
04762          if (!matching_action && !combined_find_spawn)
04763             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04764          break;
04765       case STATUS_NO_EXTENSION:
04766          if (!matching_action && !combined_find_spawn)
04767             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04768          break;
04769       case STATUS_NO_PRIORITY:
04770          if (!matching_action && !combined_find_spawn)
04771             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04772          break;
04773       case STATUS_NO_LABEL:
04774          if (context && !combined_find_spawn)
04775             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04776          break;
04777       default:
04778          ast_debug(1, "Shouldn't happen!\n");
04779       }
04780 
04781       return (matching_action) ? 0 : -1;
04782    }
04783 }

struct ast_exten* pbx_find_extension ( struct ast_channel chan,
struct ast_context bypass,
struct pbx_find_info q,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action 
) [read]

Definition at line 2971 of file pbx.c.

References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().

Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().

02975 {
02976    int x, res;
02977    struct ast_context *tmp = NULL;
02978    struct ast_exten *e = NULL, *eroot = NULL;
02979    struct ast_include *i = NULL;
02980    struct ast_sw *sw = NULL;
02981    struct ast_exten pattern = {NULL, };
02982    struct scoreboard score = {0, };
02983    struct ast_str *tmpdata = NULL;
02984 
02985    pattern.label = label;
02986    pattern.priority = priority;
02987 #ifdef NEED_DEBUG_HERE
02988    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02989 #endif
02990 
02991    /* Initialize status if appropriate */
02992    if (q->stacklen == 0) {
02993       q->status = STATUS_NO_CONTEXT;
02994       q->swo = NULL;
02995       q->data = NULL;
02996       q->foundcontext = NULL;
02997    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02998       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02999       return NULL;
03000    }
03001 
03002    /* Check first to see if we've already been checked */
03003    for (x = 0; x < q->stacklen; x++) {
03004       if (!strcasecmp(q->incstack[x], context))
03005          return NULL;
03006    }
03007 
03008    if (bypass) { /* bypass means we only look there */
03009       tmp = bypass;
03010    } else {      /* look in contexts */
03011       tmp = find_context(context);
03012       if (!tmp) {
03013          return NULL;
03014       }
03015    }
03016 
03017    if (q->status < STATUS_NO_EXTENSION)
03018       q->status = STATUS_NO_EXTENSION;
03019 
03020    /* Do a search for matching extension */
03021 
03022    eroot = NULL;
03023    score.total_specificity = 0;
03024    score.exten = 0;
03025    score.total_length = 0;
03026    if (!tmp->pattern_tree && tmp->root_table) {
03027       create_match_char_tree(tmp);
03028 #ifdef NEED_DEBUG
03029       ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context);
03030       log_match_char_tree(tmp->pattern_tree," ");
03031 #endif
03032    }
03033 #ifdef NEED_DEBUG
03034    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
03035    log_match_char_tree(tmp->pattern_tree, "::  ");
03036 #endif
03037 
03038    do {
03039       if (!ast_strlen_zero(overrideswitch)) {
03040          char *osw = ast_strdupa(overrideswitch), *name;
03041          struct ast_switch *asw;
03042          ast_switch_f *aswf = NULL;
03043          char *datap;
03044          int eval = 0;
03045 
03046          name = strsep(&osw, "/");
03047          asw = pbx_findswitch(name);
03048 
03049          if (!asw) {
03050             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
03051             break;
03052          }
03053 
03054          if (osw && strchr(osw, '$')) {
03055             eval = 1;
03056          }
03057 
03058          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03059             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
03060             break;
03061          } else if (eval) {
03062             /* Substitute variables now */
03063             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03064             datap = ast_str_buffer(tmpdata);
03065          } else {
03066             datap = osw;
03067          }
03068 
03069          /* equivalent of extension_match_core() at the switch level */
03070          if (action == E_CANMATCH)
03071             aswf = asw->canmatch;
03072          else if (action == E_MATCHMORE)
03073             aswf = asw->matchmore;
03074          else /* action == E_MATCH */
03075             aswf = asw->exists;
03076          if (!aswf) {
03077             res = 0;
03078          } else {
03079             if (chan) {
03080                ast_autoservice_start(chan);
03081             }
03082             res = aswf(chan, context, exten, priority, callerid, datap);
03083             if (chan) {
03084                ast_autoservice_stop(chan);
03085             }
03086          }
03087          if (res) {  /* Got a match */
03088             q->swo = asw;
03089             q->data = datap;
03090             q->foundcontext = context;
03091             /* XXX keep status = STATUS_NO_CONTEXT ? */
03092             return NULL;
03093          }
03094       }
03095    } while (0);
03096 
03097    if (extenpatternmatchnew) {
03098       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
03099       eroot = score.exten;
03100 
03101       if (score.last_char == '!' && action == E_MATCHMORE) {
03102          /* We match an extension ending in '!'.
03103           * The decision in this case is final and is NULL (no match).
03104           */
03105 #ifdef NEED_DEBUG_HERE
03106          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
03107 #endif
03108          return NULL;
03109       }
03110 
03111       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
03112          q->status = STATUS_SUCCESS;
03113 #ifdef NEED_DEBUG_HERE
03114          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
03115 #endif
03116          return score.canmatch_exten;
03117       }
03118 
03119       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
03120          if (score.node) {
03121             struct ast_exten *z = trie_find_next_match(score.node);
03122             if (z) {
03123 #ifdef NEED_DEBUG_HERE
03124                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
03125 #endif
03126             } else {
03127                if (score.canmatch_exten) {
03128 #ifdef NEED_DEBUG_HERE
03129                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
03130 #endif
03131                   return score.canmatch_exten;
03132                } else {
03133 #ifdef NEED_DEBUG_HERE
03134                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
03135 #endif
03136                }
03137             }
03138             return z;
03139          }
03140 #ifdef NEED_DEBUG_HERE
03141          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
03142 #endif
03143          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
03144       }
03145 
03146       if (eroot) {
03147          /* found entry, now look for the right priority */
03148          if (q->status < STATUS_NO_PRIORITY)
03149             q->status = STATUS_NO_PRIORITY;
03150          e = NULL;
03151          if (action == E_FINDLABEL && label ) {
03152             if (q->status < STATUS_NO_LABEL)
03153                q->status = STATUS_NO_LABEL;
03154             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03155          } else {
03156             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03157          }
03158          if (e) { /* found a valid match */
03159             q->status = STATUS_SUCCESS;
03160             q->foundcontext = context;
03161 #ifdef NEED_DEBUG_HERE
03162             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
03163 #endif
03164             return e;
03165          }
03166       }
03167    } else {   /* the old/current default exten pattern match algorithm */
03168 
03169       /* scan the list trying to match extension and CID */
03170       eroot = NULL;
03171       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
03172          int match = extension_match_core(eroot->exten, exten, action);
03173          /* 0 on fail, 1 on match, 2 on earlymatch */
03174 
03175          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
03176             continue;   /* keep trying */
03177          if (match == 2 && action == E_MATCHMORE) {
03178             /* We match an extension ending in '!'.
03179              * The decision in this case is final and is NULL (no match).
03180              */
03181             return NULL;
03182          }
03183          /* found entry, now look for the right priority */
03184          if (q->status < STATUS_NO_PRIORITY)
03185             q->status = STATUS_NO_PRIORITY;
03186          e = NULL;
03187          if (action == E_FINDLABEL && label ) {
03188             if (q->status < STATUS_NO_LABEL)
03189                q->status = STATUS_NO_LABEL;
03190             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03191          } else {
03192             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03193          }
03194          if (e) { /* found a valid match */
03195             q->status = STATUS_SUCCESS;
03196             q->foundcontext = context;
03197             return e;
03198          }
03199       }
03200    }
03201 
03202    /* Check alternative switches */
03203    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
03204       struct ast_switch *asw = pbx_findswitch(sw->name);
03205       ast_switch_f *aswf = NULL;
03206       char *datap;
03207 
03208       if (!asw) {
03209          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
03210          continue;
03211       }
03212 
03213       /* Substitute variables now */
03214       if (sw->eval) {
03215          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03216             ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
03217             continue;
03218          }
03219          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03220       }
03221 
03222       /* equivalent of extension_match_core() at the switch level */
03223       if (action == E_CANMATCH)
03224          aswf = asw->canmatch;
03225       else if (action == E_MATCHMORE)
03226          aswf = asw->matchmore;
03227       else /* action == E_MATCH */
03228          aswf = asw->exists;
03229       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
03230       if (!aswf)
03231          res = 0;
03232       else {
03233          if (chan)
03234             ast_autoservice_start(chan);
03235          res = aswf(chan, context, exten, priority, callerid, datap);
03236          if (chan)
03237             ast_autoservice_stop(chan);
03238       }
03239       if (res) {  /* Got a match */
03240          q->swo = asw;
03241          q->data = datap;
03242          q->foundcontext = context;
03243          /* XXX keep status = STATUS_NO_CONTEXT ? */
03244          return NULL;
03245       }
03246    }
03247    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
03248    /* Now try any includes we have in this context */
03249    for (i = tmp->includes; i; i = i->next) {
03250       if (include_valid(i)) {
03251          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
03252 #ifdef NEED_DEBUG_HERE
03253             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
03254 #endif
03255             return e;
03256          }
03257          if (q->swo)
03258             return NULL;
03259       }
03260    }
03261    return NULL;
03262 }

struct ast_app* pbx_findapp ( const char *  app  )  [read]
static struct ast_switch* pbx_findswitch ( const char *  sw  )  [static, read]

Definition at line 1509 of file pbx.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.

Referenced by pbx_find_extension().

01510 {
01511    struct ast_switch *asw;
01512 
01513    AST_RWLIST_RDLOCK(&switches);
01514    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01515       if (!strcasecmp(asw->name, sw))
01516          break;
01517    }
01518    AST_RWLIST_UNLOCK(&switches);
01519 
01520    return asw;
01521 }

void pbx_live_dangerously ( int  new_live_dangerously  ) 

Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).

These dialplan functions (such as SHELL) provide an opportunity for privilege escalation. They are okay to invoke from the dialplan, but external protocols with permission controls should not normally invoke them.

This function can globally enable/disable the execution of dangerous functions from external protocols.

Parameters:
new_live_dangerously If true, enable the execution of escalating functions from external protocols.

Definition at line 4016 of file pbx.c.

References ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by ast_readconfig().

04017 {
04018    if (new_live_dangerously && !live_dangerously) {
04019       ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
04020          "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
04021    }
04022 
04023    if (!new_live_dangerously && live_dangerously) {
04024       ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
04025    }
04026    live_dangerously = new_live_dangerously;
04027 }

static int pbx_parseable_goto ( struct ast_channel chan,
const char *  goto_string,
int  async 
) [static]

Definition at line 11099 of file pbx.c.

References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_party_id::number, ast_channel::priority, S_COR, ast_party_number::str, and ast_party_number::valid.

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

11100 {
11101    char *exten, *pri, *context;
11102    char *stringp;
11103    int ipri;
11104    int mode = 0;
11105 
11106    if (ast_strlen_zero(goto_string)) {
11107       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
11108       return -1;
11109    }
11110    stringp = ast_strdupa(goto_string);
11111    context = strsep(&stringp, ","); /* guaranteed non-null */
11112    exten = strsep(&stringp, ",");
11113    pri = strsep(&stringp, ",");
11114    if (!exten) {  /* Only a priority in this one */
11115       pri = context;
11116       exten = NULL;
11117       context = NULL;
11118    } else if (!pri) {   /* Only an extension and priority in this one */
11119       pri = exten;
11120       exten = context;
11121       context = NULL;
11122    }
11123    if (*pri == '+') {
11124       mode = 1;
11125       pri++;
11126    } else if (*pri == '-') {
11127       mode = -1;
11128       pri++;
11129    }
11130    if (sscanf(pri, "%30d", &ipri) != 1) {
11131       ipri = ast_findlabel_extension(chan, context ? context : chan->context,
11132          exten ? exten : chan->exten, pri,
11133          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
11134       if (ipri < 1) {
11135          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
11136          return -1;
11137       } else
11138          mode = 0;
11139    }
11140    /* At this point we have a priority and maybe an extension and a context */
11141 
11142    if (mode)
11143       ipri = chan->priority + (ipri * mode);
11144 
11145    if (async)
11146       ast_async_goto(chan, context, exten, ipri);
11147    else
11148       ast_explicit_goto(chan, context, exten, ipri);
11149 
11150    return 0;
11151 
11152 }

void pbx_retrieve_variable ( struct ast_channel c,
const char *  var,
char **  ret,
char *  workspace,
int  workspacelen,
struct varshead *  headp 
)

Support for Asterisk built-in variables in the dialplan.

Retrieve the value of a builtin variable or variable from the channel variable stack.

Note:
See also

Definition at line 3392 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().

03393 {
03394    struct ast_str *str = ast_str_create(16);
03395    const char *cret;
03396 
03397    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03398    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03399    *ret = cret ? workspace : NULL;
03400    ast_free(str);
03401 }

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 5894 of file pbx.c.

References autofallthrough.

Referenced by pbx_load_module().

05895 {
05896    int oldval = autofallthrough;
05897    autofallthrough = newval;
05898    return oldval;
05899 }

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 5901 of file pbx.c.

References extenpatternmatchnew.

Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().

05902 {
05903    int oldval = extenpatternmatchnew;
05904    extenpatternmatchnew = newval;
05905    return oldval;
05906 }

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.

Since:
1.6.1

Definition at line 5908 of file pbx.c.

References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.

Referenced by pbx_load_module().

05909 {
05910    if (overrideswitch) {
05911       ast_free(overrideswitch);
05912    }
05913    if (!ast_strlen_zero(newval)) {
05914       overrideswitch = ast_strdup(newval);
05915    } else {
05916       overrideswitch = NULL;
05917    }
05918 }

static void pbx_shutdown ( void   )  [static]

Definition at line 11219 of file pbx.c.

References ao2_ref, ast_hashtab_destroy(), contexts_table, hints, pbx_builtin_clear_globals(), and statecbs.

Referenced by ast_pbx_init().

11220 {
11221    if (hints) {
11222       ao2_ref(hints, -1);
11223       hints = NULL;
11224    }
11225    if (statecbs) {
11226       ao2_ref(statecbs, -1);
11227       statecbs = NULL;
11228    }
11229    if (contexts_table) {
11230       ast_hashtab_destroy(contexts_table, NULL);
11231    }
11232    pbx_builtin_clear_globals();
11233 }

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 
)

Definition at line 4437 of file pbx.c.

References ast_alloca, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.

Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().

04438 {
04439    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04440    char *cp4 = NULL;
04441    const char *tmp, *whereweare, *orig_cp2 = cp2;
04442    int length, offset, offset2, isfunction;
04443    char *workspace = NULL;
04444    char *ltmp = NULL, *var = NULL;
04445    char *nextvar, *nextexp, *nextthing;
04446    char *vars, *vare;
04447    int pos, brackets, needsub, len;
04448 
04449    *cp2 = 0; /* just in case nothing ends up there */
04450    whereweare=tmp=cp1;
04451    while (!ast_strlen_zero(whereweare) && count) {
04452       /* Assume we're copying the whole remaining string */
04453       pos = strlen(whereweare);
04454       nextvar = NULL;
04455       nextexp = NULL;
04456       nextthing = strchr(whereweare, '$');
04457       if (nextthing) {
04458          switch (nextthing[1]) {
04459          case '{':
04460             nextvar = nextthing;
04461             pos = nextvar - whereweare;
04462             break;
04463          case '[':
04464             nextexp = nextthing;
04465             pos = nextexp - whereweare;
04466             break;
04467          default:
04468             pos = 1;
04469          }
04470       }
04471 
04472       if (pos) {
04473          /* Can't copy more than 'count' bytes */
04474          if (pos > count)
04475             pos = count;
04476 
04477          /* Copy that many bytes */
04478          memcpy(cp2, whereweare, pos);
04479 
04480          count -= pos;
04481          cp2 += pos;
04482          whereweare += pos;
04483          *cp2 = 0;
04484       }
04485 
04486       if (nextvar) {
04487          /* We have a variable.  Find the start and end, and determine
04488             if we are going to have to recursively call ourselves on the
04489             contents */
04490          vars = vare = nextvar + 2;
04491          brackets = 1;
04492          needsub = 0;
04493 
04494          /* Find the end of it */
04495          while (brackets && *vare) {
04496             if ((vare[0] == '$') && (vare[1] == '{')) {
04497                needsub++;
04498             } else if (vare[0] == '{') {
04499                brackets++;
04500             } else if (vare[0] == '}') {
04501                brackets--;
04502             } else if ((vare[0] == '$') && (vare[1] == '['))
04503                needsub++;
04504             vare++;
04505          }
04506          if (brackets)
04507             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04508          len = vare - vars - 1;
04509 
04510          /* Skip totally over variable string */
04511          whereweare += (len + 3);
04512 
04513          if (!var)
04514             var = ast_alloca(VAR_BUF_SIZE);
04515 
04516          /* Store variable name (and truncate) */
04517          ast_copy_string(var, vars, len + 1);
04518 
04519          /* Substitute if necessary */
04520          if (needsub) {
04521             size_t used;
04522             if (!ltmp)
04523                ltmp = ast_alloca(VAR_BUF_SIZE);
04524 
04525             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04526             vars = ltmp;
04527          } else {
04528             vars = var;
04529          }
04530 
04531          if (!workspace)
04532             workspace = ast_alloca(VAR_BUF_SIZE);
04533 
04534          workspace[0] = '\0';
04535 
04536          parse_variable_name(vars, &offset, &offset2, &isfunction);
04537          if (isfunction) {
04538             /* Evaluate function */
04539             if (c || !headp)
04540                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04541             else {
04542                struct varshead old;
04543                struct ast_channel *c = ast_dummy_channel_alloc();
04544                if (c) {
04545                   memcpy(&old, &c->varshead, sizeof(old));
04546                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04547                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04548                   /* Don't deallocate the varshead that was passed in */
04549                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04550                   c = ast_channel_unref(c);
04551                } else {
04552                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04553                }
04554             }
04555             ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
04556          } else {
04557             /* Retrieve variable value */
04558             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04559          }
04560          if (cp4) {
04561             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04562 
04563             length = strlen(cp4);
04564             if (length > count)
04565                length = count;
04566             memcpy(cp2, cp4, length);
04567             count -= length;
04568             cp2 += length;
04569             *cp2 = 0;
04570          }
04571       } else if (nextexp) {
04572          /* We have an expression.  Find the start and end, and determine
04573             if we are going to have to recursively call ourselves on the
04574             contents */
04575          vars = vare = nextexp + 2;
04576          brackets = 1;
04577          needsub = 0;
04578 
04579          /* Find the end of it */
04580          while (brackets && *vare) {
04581             if ((vare[0] == '$') && (vare[1] == '[')) {
04582                needsub++;
04583                brackets++;
04584                vare++;
04585             } else if (vare[0] == '[') {
04586                brackets++;
04587             } else if (vare[0] == ']') {
04588                brackets--;
04589             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04590                needsub++;
04591                vare++;
04592             }
04593             vare++;
04594          }
04595          if (brackets)
04596             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04597          len = vare - vars - 1;
04598 
04599          /* Skip totally over expression */
04600          whereweare += (len + 3);
04601 
04602          if (!var)
04603             var = ast_alloca(VAR_BUF_SIZE);
04604 
04605          /* Store variable name (and truncate) */
04606          ast_copy_string(var, vars, len + 1);
04607 
04608          /* Substitute if necessary */
04609          if (needsub) {
04610             size_t used;
04611             if (!ltmp)
04612                ltmp = ast_alloca(VAR_BUF_SIZE);
04613 
04614             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04615             vars = ltmp;
04616          } else {
04617             vars = var;
04618          }
04619 
04620          length = ast_expr(vars, cp2, count, c);
04621 
04622          if (length) {
04623             ast_debug(1, "Expression result is '%s'\n", cp2);
04624             count -= length;
04625             cp2 += length;
04626             *cp2 = 0;
04627          }
04628       }
04629    }
04630    *used = cp2 - orig_cp2;
04631 }

void pbx_substitute_variables_varshead ( struct varshead *  headp,
const char *  cp1,
char *  cp2,
int  count 
)

Definition at line 4639 of file pbx.c.

References pbx_substitute_variables_helper_full().

Referenced by do_say(), dundi_lookup_local(), and loopback_subst().

04640 {
04641    size_t used;
04642    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04643 }

static void* pbx_thread ( void *  data  )  [static]

Definition at line 5812 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

05813 {
05814    /* Oh joyeous kernel, we're a new thread, with nothing to do but
05815       answer this channel and get it going.
05816    */
05817    /* NOTE:
05818       The launcher of this function _MUST_ increment 'countcalls'
05819       before invoking the function; it will be decremented when the
05820       PBX has finished running on the channel
05821     */
05822    struct ast_channel *c = data;
05823 
05824    __ast_pbx_run(c, NULL);
05825    decrease_call_count();
05826 
05827    pthread_exit(NULL);
05828 
05829    return NULL;
05830 }

static void print_app_docs ( struct ast_app aa,
int  fd 
) [static]

Definition at line 6421 of file pbx.c.

References ast_app::arguments, ast_cli(), ast_free, ast_malloc, AST_MAX_APP, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), COLOR_CYAN, COLOR_MAGENTA, ast_app::description, ast_switch::description, ast_app::docsrc, ast_app::name, S_OR, ast_app::seealso, ast_app::synopsis, synopsis, ast_app::syntax, and term_color().

Referenced by handle_show_application().

06422 {
06423    /* Maximum number of characters added by terminal coloring is 22 */
06424    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
06425    char seealsotitle[40];
06426    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
06427    char *seealso = NULL;
06428    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
06429 
06430    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
06431    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
06432 
06433    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
06434    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
06435    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
06436    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
06437    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
06438 
06439 #ifdef AST_XML_DOCS
06440    if (aa->docsrc == AST_XML_DOC) {
06441       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
06442       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
06443       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
06444       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
06445 
06446       if (!synopsis || !description || !arguments || !seealso) {
06447          goto return_cleanup;
06448       }
06449    } else
06450 #endif
06451    {
06452       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06453       synopsis = ast_malloc(synopsis_size);
06454 
06455       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06456       description = ast_malloc(description_size);
06457 
06458       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06459       arguments = ast_malloc(arguments_size);
06460 
06461       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06462       seealso = ast_malloc(seealso_size);
06463 
06464       if (!synopsis || !description || !arguments || !seealso) {
06465          goto return_cleanup;
06466       }
06467 
06468       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
06469       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
06470       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
06471       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
06472    }
06473 
06474    /* Handle the syntax the same for both XML and raw docs */
06475    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06476    if (!(syntax = ast_malloc(syntax_size))) {
06477       goto return_cleanup;
06478    }
06479    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
06480 
06481    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
06482          infotitle, syntitle, synopsis, destitle, description,
06483          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
06484 
06485 return_cleanup:
06486    ast_free(description);
06487    ast_free(arguments);
06488    ast_free(synopsis);
06489    ast_free(seealso);
06490    ast_free(syntax);
06491 }

static void print_ext ( struct ast_exten e,
char *  buf,
int  buflen 
) [static]

helper function to print an extension

Definition at line 6847 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().

06848 {
06849    int prio = ast_get_extension_priority(e);
06850    if (prio == PRIORITY_HINT) {
06851       snprintf(buf, buflen, "hint: %s",
06852          ast_get_extension_app(e));
06853    } else {
06854       snprintf(buf, buflen, "%d. %s(%s)",
06855          prio, ast_get_extension_app(e),
06856          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06857    }
06858 }

static int raise_exception ( struct ast_channel chan,
const char *  reason,
int  priority 
) [static]

Definition at line 3552 of file pbx.c.

References ast_calloc_with_stringfields, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().

Referenced by __ast_pbx_run(), pbx_builtin_raise_exception(), and pbx_builtin_waitexten().

03553 {
03554    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03555    struct pbx_exception *exception = NULL;
03556 
03557    if (!ds) {
03558       ds = ast_datastore_alloc(&exception_store_info, NULL);
03559       if (!ds)
03560          return -1;
03561       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03562          ast_datastore_free(ds);
03563          return -1;
03564       }
03565       ds->data = exception;
03566       ast_channel_datastore_add(chan, ds);
03567    } else
03568       exception = ds->data;
03569 
03570    ast_string_field_set(exception, reason, reason);
03571    ast_string_field_set(exception, context, chan->context);
03572    ast_string_field_set(exception, exten, chan->exten);
03573    exception->priority = chan->priority;
03574    set_ext_pri(chan, "e", priority);
03575    return 0;
03576 }

static int read_escalates ( const struct ast_custom_function acf  )  [static]

Returns true if given custom function escalates privileges on read.

Parameters:
acf Custom function to query.
Returns:
True (non-zero) if reads escalate privileges.
False (zero) if reads just read.

Definition at line 3813 of file pbx.c.

References ast_custom_escalating_function::acf, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_escalating_function::read_escalates.

Referenced by is_read_allowed().

03813                                                                  {
03814    int res = 0;
03815    struct ast_custom_escalating_function *cur_escalation;
03816 
03817    AST_RWLIST_RDLOCK(&escalation_root);
03818    AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) {
03819       if (cur_escalation->acf == acf) {
03820          res = cur_escalation->read_escalates;
03821          break;
03822       }
03823    }
03824    AST_RWLIST_UNLOCK(&escalation_root);
03825    return res;
03826 }

static void set_ext_pri ( struct ast_channel c,
const char *  exten,
int  pri 
) [static]

helper function to set extension and priority

Definition at line 5384 of file pbx.c.

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_channel::exten, and ast_channel::priority.

Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten(), pbx_builtin_waitexten(), and raise_exception().

05385 {
05386    ast_channel_lock(c);
05387    ast_copy_string(c->exten, exten, sizeof(c->exten));
05388    c->priority = pri;
05389    ast_channel_unlock(c);
05390 }

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 7012 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().

07013 {
07014    struct ast_context *c = NULL;
07015    int res = 0, old_total_exten = dpc->total_exten;
07016 
07017    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
07018 
07019    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
07020    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
07021    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
07022    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
07023    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
07024    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
07025    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
07026    ast_rdlock_contexts();
07027 
07028    /* walk all contexts ... */
07029    while ( (c = ast_walk_contexts(c)) ) {
07030       int context_info_printed = 0;
07031 
07032       if (context && strcmp(ast_get_context_name(c), context))
07033          continue;   /* skip this one, name doesn't match */
07034 
07035       dpc->context_existence = 1;
07036 
07037       if (!c->pattern_tree) {
07038          /* Ignore check_return warning from Coverity for ast_exists_extension below */
07039          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
07040       }
07041 
07042       ast_rdlock_context(c);
07043 
07044       dpc->total_context++;
07045       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
07046          ast_get_context_name(c), ast_get_context_registrar(c));
07047       context_info_printed = 1;
07048 
07049       if (c->pattern_tree)
07050       {
07051          cli_match_char_tree(c->pattern_tree, " ", fd);
07052       } else {
07053          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
07054       }
07055 
07056       ast_unlock_context(c);
07057 
07058       /* if we print something in context, make an empty line */
07059       if (context_info_printed)
07060          ast_cli(fd, "\n");
07061    }
07062    ast_unlock_contexts();
07063 
07064    return (dpc->total_exten == old_total_exten) ? -1 : res;
07065 }

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 6861 of file pbx.c.

References ast_cli(), AST_EXT_MATCHCID_ON, ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

Referenced by handle_show_dialplan().

06862 {
06863    struct ast_context *c = NULL;
06864    int res = 0, old_total_exten = dpc->total_exten;
06865 
06866    ast_rdlock_contexts();
06867 
06868    /* walk all contexts ... */
06869    while ( (c = ast_walk_contexts(c)) ) {
06870       struct ast_exten *e;
06871       struct ast_include *i;
06872       struct ast_ignorepat *ip;
06873       char buf[256], buf2[256];
06874       int context_info_printed = 0;
06875 
06876       if (context && strcmp(ast_get_context_name(c), context))
06877          continue;   /* skip this one, name doesn't match */
06878 
06879       dpc->context_existence = 1;
06880 
06881       ast_rdlock_context(c);
06882 
06883       /* are we looking for exten too? if yes, we print context
06884        * only if we find our extension.
06885        * Otherwise print context even if empty ?
06886        * XXX i am not sure how the rinclude is handled.
06887        * I think it ought to go inside.
06888        */
06889       if (!exten) {
06890          dpc->total_context++;
06891          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06892             ast_get_context_name(c), ast_get_context_registrar(c));
06893          context_info_printed = 1;
06894       }
06895 
06896       /* walk extensions ... */
06897       e = NULL;
06898       while ( (e = ast_walk_context_extensions(c, e)) ) {
06899          struct ast_exten *p;
06900 
06901          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
06902             continue;   /* skip, extension match failed */
06903 
06904          dpc->extension_existence = 1;
06905 
06906          /* may we print context info? */
06907          if (!context_info_printed) {
06908             dpc->total_context++;
06909             if (rinclude) { /* TODO Print more info about rinclude */
06910                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
06911                   ast_get_context_name(c), ast_get_context_registrar(c));
06912             } else {
06913                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06914                   ast_get_context_name(c), ast_get_context_registrar(c));
06915             }
06916             context_info_printed = 1;
06917          }
06918          dpc->total_prio++;
06919 
06920          /* write extension name and first peer */
06921          if (e->matchcid == AST_EXT_MATCHCID_ON)
06922             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
06923          else
06924             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
06925 
06926          print_ext(e, buf2, sizeof(buf2));
06927 
06928          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
06929             ast_get_extension_registrar(e));
06930 
06931          dpc->total_exten++;
06932          /* walk next extension peers */
06933          p = e;   /* skip the first one, we already got it */
06934          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06935             const char *el = ast_get_extension_label(p);
06936             dpc->total_prio++;
06937             if (el)
06938                snprintf(buf, sizeof(buf), "   [%s]", el);
06939             else
06940                buf[0] = '\0';
06941             print_ext(p, buf2, sizeof(buf2));
06942 
06943             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
06944                ast_get_extension_registrar(p));
06945          }
06946       }
06947 
06948       /* walk included and write info ... */
06949       i = NULL;
06950       while ( (i = ast_walk_context_includes(c, i)) ) {
06951          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
06952          if (exten) {
06953             /* Check all includes for the requested extension */
06954             if (includecount >= AST_PBX_MAX_STACK) {
06955                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
06956             } else {
06957                int dupe = 0;
06958                int x;
06959                for (x = 0; x < includecount; x++) {
06960                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
06961                      dupe++;
06962                      break;
06963                   }
06964                }
06965                if (!dupe) {
06966                   includes[includecount] = ast_get_include_name(i);
06967                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
06968                } else {
06969                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
06970                }
06971             }
06972          } else {
06973             ast_cli(fd, "  Include =>        %-45s [%s]\n",
06974                buf, ast_get_include_registrar(i));
06975          }
06976       }
06977 
06978       /* walk ignore patterns and write info ... */
06979       ip = NULL;
06980       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06981          const char *ipname = ast_get_ignorepat_name(ip);
06982          char ignorepat[AST_MAX_EXTENSION];
06983          snprintf(buf, sizeof(buf), "'%s'", ipname);
06984          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06985          if (!exten || ast_extension_match(ignorepat, exten)) {
06986             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
06987                buf, ast_get_ignorepat_registrar(ip));
06988          }
06989       }
06990       if (!rinclude) {
06991          struct ast_sw *sw = NULL;
06992          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06993             snprintf(buf, sizeof(buf), "'%s/%s'",
06994                ast_get_switch_name(sw),
06995                ast_get_switch_data(sw));
06996             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
06997                buf, ast_get_switch_registrar(sw));
06998          }
06999       }
07000 
07001       ast_unlock_context(c);
07002 
07003       /* if we print something in context, make an empty line */
07004       if (context_info_printed)
07005          ast_cli(fd, "\n");
07006    }
07007    ast_unlock_contexts();
07008 
07009    return (dpc->total_exten == old_total_exten) ? -1 : res;
07010 }

static int statecbs_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 11211 of file pbx.c.

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

11212 {
11213    const struct ast_state_cb *state_cb = obj;
11214    ast_state_cb_type change_cb = arg;
11215 
11216    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
11217 }

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.

Parameters:
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 3302 of file pbx.c.

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

03303 {
03304    char *ret = workspace;
03305    int lr;  /* length of the input string after the copy */
03306 
03307    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
03308 
03309    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
03310 
03311    /* Quick check if no need to do anything */
03312    if (offset == 0 && length >= lr) /* take the whole string */
03313       return ret;
03314 
03315    if (offset < 0)   {  /* translate negative offset into positive ones */
03316       offset = lr + offset;
03317       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03318          offset = 0;
03319    }
03320 
03321    /* too large offset result in empty string so we know what to return */
03322    if (offset >= lr)
03323       return ret + lr;  /* the final '\0' */
03324 
03325    ret += offset;    /* move to the start position */
03326    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
03327       ret[length] = '\0';
03328    else if (length < 0) {
03329       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
03330          ret[lr + length - offset] = '\0';
03331       else
03332          ret[0] = '\0';
03333    }
03334 
03335    return ret;
03336 }

static int thread_inhibits_escalations ( void   )  [static]

Indicates whether the current thread inhibits the execution of dangerous functions.

Returns:
True (non-zero) if dangerous function execution is inhibited.
False (zero) if dangerous function execution is allowed.

Definition at line 4052 of file pbx.c.

References ast_log(), ast_threadstorage_get(), LOG_ERROR, and thread_inhibit_escalations_tl.

Referenced by is_read_allowed(), and is_write_allowed().

04053 {
04054    int *thread_inhibit_escalations;
04055 
04056    thread_inhibit_escalations = ast_threadstorage_get(
04057       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04058 
04059    if (thread_inhibit_escalations == NULL) {
04060       ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
04061       /* On error, assume that we are inhibiting */
04062       return 1;
04063    }
04064 
04065    return *thread_inhibit_escalations;
04066 }

static struct ast_exten* trie_find_next_match ( struct match_char node  )  [static, read]

Definition at line 1706 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().

01707 {
01708    struct match_char *m3;
01709    struct match_char *m4;
01710    struct ast_exten *e3;
01711 
01712    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01713       return node->exten;
01714    }
01715 
01716    if (node && node->x[0] == '!' && !node->x[1]) {
01717       return node->exten;
01718    }
01719 
01720    if (!node || !node->next_char) {
01721       return NULL;
01722    }
01723 
01724    m3 = node->next_char;
01725 
01726    if (m3->exten) {
01727       return m3->exten;
01728    }
01729    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01730       if (m4->exten) {
01731          return m4->exten;
01732       }
01733    }
01734    for (m4 = m3; m4; m4 = m4->alt_char) {
01735       e3 = trie_find_next_match(m3);
01736       if (e3) {
01737          return e3;
01738       }
01739    }
01740 
01741    return NULL;
01742 }

static void unload_pbx ( void   )  [static]
static void unreference_cached_app ( struct ast_app app  )  [static]

Definition at line 7624 of file pbx.c.

References ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), and ast_walk_extension_priorities().

Referenced by ast_unregister_application().

07625 {
07626    struct ast_context *context = NULL;
07627    struct ast_exten *eroot = NULL, *e = NULL;
07628 
07629    ast_rdlock_contexts();
07630    while ((context = ast_walk_contexts(context))) {
07631       while ((eroot = ast_walk_context_extensions(context, eroot))) {
07632          while ((e = ast_walk_extension_priorities(eroot, e))) {
07633             if (e->cached_app == app)
07634                e->cached_app = NULL;
07635          }
07636       }
07637    }
07638    ast_unlock_contexts();
07639 
07640    return;
07641 }

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 1610 of file pbx.c.

References ast_log(), ast_exten::exten, scoreboard::exten, scoreboard::last_char, LOG_NOTICE, scoreboard::node, scoreboard::total_length, and scoreboard::total_specificity.

Referenced by new_find_extension().

01611 {
01612    /* if this extension is marked as deleted, then skip this -- if it never shows
01613       on the scoreboard, it will never be found, nor will halt the traversal. */
01614    if (deleted)
01615       return;
01616    board->total_specificity = spec;
01617    board->total_length = length;
01618    board->exten = exten;
01619    board->last_char = last;
01620    board->node = node;
01621 #ifdef NEED_DEBUG_HERE
01622    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01623 #endif
01624 }

static void wait_for_hangup ( struct ast_channel chan,
const void *  data 
) [static]

Definition at line 9805 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().

09806 {
09807    int res;
09808    struct ast_frame *f;
09809    double waitsec;
09810    int waittime;
09811 
09812    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
09813       waitsec = -1;
09814    if (waitsec > -1) {
09815       waittime = waitsec * 1000.0;
09816       ast_safe_sleep(chan, waittime);
09817    } else do {
09818       res = ast_waitfor(chan, -1);
09819       if (res < 0)
09820          return;
09821       f = ast_read(chan);
09822       if (f)
09823          ast_frfree(f);
09824    } while(f);
09825 }

static int write_escalates ( const struct ast_custom_function acf  )  [static]

Returns true if given custom function escalates privileges on write.

Parameters:
acf Custom function to query.
Returns:
True (non-zero) if writes escalate privileges.
False (zero) if writes just write.

Definition at line 3835 of file pbx.c.

References ast_custom_escalating_function::acf, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_escalating_function::write_escalates.

Referenced by is_write_allowed().

03835                                                                   {
03836    int res = 0;
03837    struct ast_custom_escalating_function *cur_escalation;
03838 
03839    AST_RWLIST_RDLOCK(&escalation_root);
03840    AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) {
03841       if (cur_escalation->acf == acf) {
03842          res = cur_escalation->write_escalates;
03843          break;
03844       }
03845    }
03846    AST_RWLIST_UNLOCK(&escalation_root);
03847    return res;
03848 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 1176 of file pbx.c.

Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().

struct ast_app_option background_opts[128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} [static]

Definition at line 807 of file pbx.c.

Referenced by pbx_builtin_background().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Referenced by load_pbx(), and unload_pbx().

ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Lock for the ast_context list.

Note:
This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643

Definition at line 1248 of file pbx.c.

Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().

ast_mutex_t context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.

Definition at line 1253 of file pbx.c.

Referenced by ast_merge_contexts_and_delete(), and handle_statechange().

struct ast_context* contexts [static]
struct ast_hashtab* contexts_table = NULL [static]
int countcalls [static]

Definition at line 1184 of file pbx.c.

Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().

const char* const days[] [static]

Definition at line 8208 of file pbx.c.

Referenced by ast_build_timing().

struct ast_event_sub* device_state_sub [static]

Subscription for device state change events.

Definition at line 1181 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

Definition at line 820 of file pbx.c.

Initial value:
 {
   .name = "EXCEPTION",
   .read = acf_exception_read,
}

Definition at line 3604 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

Initial value:
 {
   .type = "EXCEPTION",
   .destroy = exception_store_free,
}

Definition at line 3536 of file pbx.c.

Referenced by acf_exception_read(), and raise_exception().

int extenpatternmatchnew = 0 [static]

Definition at line 1177 of file pbx.c.

Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().

Referenced by ast_extension_state2str().

struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } [static]

Definition at line 823 of file pbx.c.

Referenced by ast_extension_state2().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]
ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [static]
struct ao2_container* hints [static]
Note:
When holding this container's lock, do _not_ do anything that will cause conlock to be taken, unless you _already_ hold it. The ast_merge_contexts_and_delete function will take the locks in conlock/hints order, so any other paths that require both locks must also take them in that order.

Definition at line 1268 of file pbx.c.

Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add_destroy(), ast_extension_state_del(), ast_merge_contexts_and_delete(), ast_pbx_init(), ast_remove_hint(), complete_core_show_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), and pbx_shutdown().

Initial value:

Definition at line 10790 of file pbx.c.

int live_dangerously [static]

Set to true (non-zero) to globally allow all dangerous dialplan functions to run.

Definition at line 828 of file pbx.c.

Referenced by ast_readconfig().

ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 1183 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

const char* const months[] [static]

Definition at line 8220 of file pbx.c.

Referenced by ast_build_timing().

char* overrideswitch = NULL [static]

Definition at line 1178 of file pbx.c.

Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().

struct ast_cli_entry pbx_cli[] [static]

Definition at line 7603 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

Initial value:
 {
   AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider),
}

Definition at line 10795 of file pbx.c.

Referenced by load_pbx().

struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} [static]

Definition at line 9946 of file pbx.c.

Referenced by pbx_builtin_resetcdr().

struct ao2_container* statecbs [static]
int stateid = 1 [static]

Definition at line 1259 of file pbx.c.

Referenced by ast_extension_state_add_destroy().

struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } [static]

Definition at line 822 of file pbx.c.

Referenced by pbx_find_extension().

Initial value:
 {
   .name = "TESTTIME",
   .write = testtime_write,
}

Definition at line 10037 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

struct ast_threadstorage thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , } [static]

Definition at line 828 of file pbx.c.

Referenced by ast_thread_inhibit_escalations(), and thread_inhibits_escalations().

int totalcalls [static]

Definition at line 1185 of file pbx.c.

Referenced by ast_processed_calls(), increase_call_count(), and timing_read().

struct ast_app_option waitexten_opts[128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} [static]

Definition at line 815 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Generated on 3 Apr 2014 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1