Wed Jan 27 20:02:43 2016

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"

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

#define STATUS_NO_EXTENSION   2

Definition at line 2950 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2952 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2951 of file pbx.c.

#define STATUS_SUCCESS   5

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

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

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

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

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

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

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

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

11100 {
11101    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
11102 
11103    if (!chan)
11104       return -2;
11105 
11106    if (context == NULL)
11107       context = chan->context;
11108    if (exten == NULL)
11109       exten = chan->exten;
11110 
11111    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
11112    if (ast_exists_extension(chan, context, exten, priority,
11113       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
11114       return goto_func(chan, context, exten, priority);
11115    else {
11116       return AST_PBX_GOTO_FAILED;
11117    }
11118 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

09625 {
09626    struct ast_include *tmpi;
09627    struct ast_sw *sw;
09628    struct ast_exten *e, *el, *en;
09629    struct ast_ignorepat *ipi;
09630    struct ast_context *tmp = con;
09631 
09632    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
09633       struct ast_include *tmpil = tmpi;
09634       tmpi = tmpi->next;
09635       ast_free(tmpil);
09636    }
09637    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
09638       struct ast_ignorepat *ipl = ipi;
09639       ipi = ipi->next;
09640       ast_free(ipl);
09641    }
09642    if (tmp->registrar)
09643       ast_free(tmp->registrar);
09644 
09645    /* destroy the hash tabs */
09646    if (tmp->root_table) {
09647       ast_hashtab_destroy(tmp->root_table, 0);
09648    }
09649    /* and destroy the pattern tree */
09650    if (tmp->pattern_tree)
09651       destroy_pattern_tree(tmp->pattern_tree);
09652 
09653    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
09654       ast_free(sw);
09655    for (e = tmp->root; e;) {
09656       for (en = e->peer; en;) {
09657          el = en;
09658          en = en->peer;
09659          destroy_exten(el);
09660       }
09661       el = e;
09662       e = e->next;
09663       destroy_exten(el);
09664    }
09665    tmp->root = NULL;
09666    ast_rwlock_destroy(&tmp->lock);
09667    ast_mutex_destroy(&tmp->macrolock);
09668    ast_free(tmp);
09669 }

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

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

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

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

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

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

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

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

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

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

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

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

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

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

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

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

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

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

Definition at line 1916 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

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

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5885 of file pbx.c.

References countcalls.

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

05886 {
05887    return countcalls;
05888 }

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

08648 {
08649    int ret = -1;
08650    struct ast_context *c;
08651 
08652    c = find_context_locked(context);
08653    if (c) {
08654       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08655          application, data, datad, registrar);
08656       ast_unlock_contexts();
08657    }
08658 
08659    return ret;
08660 }

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

09010 {
09011    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
09012       application, data, datad, registrar, 1);
09013 }

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

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

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

08628 {
08629    int ret = -1;
08630    struct ast_context *c;
08631 
08632    c = find_context(context);
08633    if (c) {
08634       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
08635          application, data, datad, registrar, 1);
08636    }
08637 
08638    return ret;
08639 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 5224 of file pbx.c.

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

Referenced by add_priority(), and ast_add_extension2_lockopt().

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

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

08686 {
08687    int res = 0;
08688    struct ast_channel *tmpchan;
08689    struct {
08690       char *accountcode;
08691       char *exten;
08692       char *context;
08693       char *linkedid;
08694       char *name;
08695       struct ast_cdr *cdr;
08696       int amaflags;
08697       int state;
08698       format_t readformat;
08699       format_t writeformat;
08700    } tmpvars = { 0, };
08701 
08702    ast_channel_lock(chan);
08703    if (chan->pbx) { /* This channel is currently in the PBX */
08704       ast_explicit_goto(chan, context, exten, priority + 1);
08705       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08706       ast_channel_unlock(chan);
08707       return res;
08708    }
08709 
08710    /* In order to do it when the channel doesn't really exist within
08711     * the PBX, we have to make a new channel, masquerade, and start the PBX
08712     * at the new location */
08713    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08714    tmpvars.exten = ast_strdupa(chan->exten);
08715    tmpvars.context = ast_strdupa(chan->context);
08716    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08717    tmpvars.name = ast_strdupa(chan->name);
08718    tmpvars.amaflags = chan->amaflags;
08719    tmpvars.state = chan->_state;
08720    tmpvars.writeformat = chan->writeformat;
08721    tmpvars.readformat = chan->readformat;
08722    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08723 
08724    ast_channel_unlock(chan);
08725 
08726    /* Do not hold any channel locks while calling channel_alloc() since the function
08727     * locks the channel container when linking the new channel in. */
08728    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08729       ast_cdr_discard(tmpvars.cdr);
08730       return -1;
08731    }
08732 
08733    /* copy the cdr info over */
08734    if (tmpvars.cdr) {
08735       ast_cdr_discard(tmpchan->cdr);
08736       tmpchan->cdr = tmpvars.cdr;
08737       tmpvars.cdr = NULL;
08738    }
08739 
08740    /* Make formats okay */
08741    tmpchan->readformat = tmpvars.readformat;
08742    tmpchan->writeformat = tmpvars.writeformat;
08743 
08744    /* Setup proper location. Never hold another channel lock while calling this function. */
08745    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08746 
08747    /* Masquerade into tmp channel */
08748    if (ast_channel_masquerade(tmpchan, chan)) {
08749       /* Failed to set up the masquerade.  It's probably chan_local
08750        * in the middle of optimizing itself out.  Sad. :( */
08751       ast_hangup(tmpchan);
08752       tmpchan = NULL;
08753       res = -1;
08754    } else {
08755       ast_do_masquerade(tmpchan);
08756       /* Start the PBX going on our stolen channel */
08757       if (ast_pbx_start(tmpchan)) {
08758          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08759          ast_hangup(tmpchan);
08760          res = -1;
08761       }
08762    }
08763 
08764    return res;
08765 }

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

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

08768 {
08769    struct ast_channel *chan;
08770    int res = -1;
08771 
08772    if ((chan = ast_channel_get_by_name(channame))) {
08773       res = ast_async_goto(chan, context, exten, priority);
08774       chan = ast_channel_unref(chan);
08775    }
08776 
08777    return res;
08778 }

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

References __ast_goto_if_exists().

11126 {
11127    return __ast_goto_if_exists(chan, context, exten, priority, 1);
11128 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

11191 {
11192    return pbx_parseable_goto(chan, goto_string, 1);
11193 }

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

08269 {
08270    char *info;
08271    int j, num_fields, last_sep = -1;
08272 
08273    i->timezone = NULL;
08274 
08275    /* Check for empty just in case */
08276    if (ast_strlen_zero(info_in)) {
08277       return 0;
08278    }
08279 
08280    /* make a copy just in case we were passed a static string */
08281    info = ast_strdupa(info_in);
08282 
08283    /* count the number of fields in the timespec */
08284    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
08285       if (info[j] == ',') {
08286          last_sep = j;
08287          num_fields++;
08288       }
08289    }
08290 
08291    /* save the timezone, if it is specified */
08292    if (num_fields == 5) {
08293       i->timezone = ast_strdup(info + last_sep + 1);
08294    }
08295 
08296    /* Assume everything except time */
08297    i->monthmask = 0xfff;   /* 12 bits */
08298    i->daymask = 0x7fffffffU; /* 31 bits */
08299    i->dowmask = 0x7f; /* 7 bits */
08300    /* on each call, use strsep() to move info to the next argument */
08301    get_timerange(i, strsep(&info, "|,"));
08302    if (info)
08303       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
08304    if (info)
08305       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
08306    if (info)
08307       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
08308    return 1;
08309 }

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

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

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

Change hint for an extension.

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

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

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

References ast_check_timing2(), and ast_tvnow().

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

08312 {
08313    return ast_check_timing2(i, ast_tvnow());
08314 }

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

08317 {
08318    struct ast_tm tm;
08319 
08320    ast_localtime(&tv, &tm, i->timezone);
08321 
08322    /* If it's not the right month, return */
08323    if (!(i->monthmask & (1 << tm.tm_mon)))
08324       return 0;
08325 
08326    /* If it's not that time of the month.... */
08327    /* Warning, tm_mday has range 1..31! */
08328    if (!(i->daymask & (1 << (tm.tm_mday-1))))
08329       return 0;
08330 
08331    /* If it's not the right day of the week */
08332    if (!(i->dowmask & (1 << tm.tm_wday)))
08333       return 0;
08334 
08335    /* Sanity check the hour just to be safe */
08336    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
08337       ast_log(LOG_WARNING, "Insane time...\n");
08338       return 0;
08339    }
08340 
08341    /* Now the tough part, we calculate if it fits
08342       in the right time based on min/hour */
08343    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))))
08344       return 0;
08345 
08346    /* If we got this far, then we're good */
08347    return 1;
08348 }

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

11196 {
11197    struct ast_app *app = NULL;
11198    int which = 0;
11199    char *ret = NULL;
11200    size_t wordlen = strlen(word);
11201 
11202    AST_RWLIST_RDLOCK(&apps);
11203    AST_RWLIST_TRAVERSE(&apps, app, list) {
11204       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
11205          ret = ast_strdup(app->name);
11206          break;
11207       }
11208    }
11209    AST_RWLIST_UNLOCK(&apps);
11210 
11211    return ret;
11212 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08553 {
08554    int ret = -1;
08555    struct ast_context *c;
08556 
08557    c = find_context_locked(context);
08558    if (c) {
08559       ret = ast_context_add_ignorepat2(c, value, registrar);
08560       ast_unlock_contexts();
08561    }
08562    return ret;
08563 }

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

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

08566 {
08567    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08568    int length;
08569    char *pattern;
08570    length = sizeof(struct ast_ignorepat);
08571    length += strlen(value) + 1;
08572    if (!(ignorepat = ast_calloc(1, length)))
08573       return -1;
08574    /* The cast to char * is because we need to write the initial value.
08575     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08576     * sees the cast as dereferencing a type-punned pointer and warns about
08577     * it.  This is the workaround (we're telling gcc, yes, that's really
08578     * what we wanted to do).
08579     */
08580    pattern = (char *) ignorepat->pattern;
08581    strcpy(pattern, value);
08582    ignorepat->next = NULL;
08583    ignorepat->registrar = registrar;
08584    ast_wrlock_context(con);
08585    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08586       ignorepatl = ignorepatc;
08587       if (!strcasecmp(ignorepatc->pattern, value)) {
08588          /* Already there */
08589          ast_unlock_context(con);
08590          ast_free(ignorepat);
08591          errno = EEXIST;
08592          return -1;
08593       }
08594    }
08595    if (ignorepatl)
08596       ignorepatl->next = ignorepat;
08597    else
08598       con->ignorepats = ignorepat;
08599    ast_unlock_context(con);
08600    return 0;
08601 
08602 }

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

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

Referenced by handle_cli_dialplan_add_include().

08097 {
08098    int ret = -1;
08099    struct ast_context *c;
08100 
08101    c = find_context_locked(context);
08102    if (c) {
08103       ret = ast_context_add_include2(c, include, registrar);
08104       ast_unlock_contexts();
08105    }
08106    return ret;
08107 }

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

08367 {
08368    struct ast_include *new_include;
08369    char *c;
08370    struct ast_include *i, *il = NULL; /* include, include_last */
08371    int length;
08372    char *p;
08373 
08374    length = sizeof(struct ast_include);
08375    length += 2 * (strlen(value) + 1);
08376 
08377    /* allocate new include structure ... */
08378    if (!(new_include = ast_calloc(1, length)))
08379       return -1;
08380    /* Fill in this structure. Use 'p' for assignments, as the fields
08381     * in the structure are 'const char *'
08382     */
08383    p = new_include->stuff;
08384    new_include->name = p;
08385    strcpy(p, value);
08386    p += strlen(value) + 1;
08387    new_include->rname = p;
08388    strcpy(p, value);
08389    /* Strip off timing info, and process if it is there */
08390    if ( (c = strchr(p, ',')) ) {
08391       *c++ = '\0';
08392       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08393    }
08394    new_include->next      = NULL;
08395    new_include->registrar = registrar;
08396 
08397    ast_wrlock_context(con);
08398 
08399    /* ... go to last include and check if context is already included too... */
08400    for (i = con->includes; i; i = i->next) {
08401       if (!strcasecmp(i->name, new_include->name)) {
08402          ast_destroy_timing(&(new_include->timing));
08403          ast_free(new_include);
08404          ast_unlock_context(con);
08405          errno = EEXIST;
08406          return -1;
08407       }
08408       il = i;
08409    }
08410 
08411    /* ... include new context into context list, unlock, return */
08412    if (il)
08413       il->next = new_include;
08414    else
08415       con->includes = new_include;
08416    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08417 
08418    ast_unlock_context(con);
08419 
08420    return 0;
08421 }

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

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

08429 {
08430    int ret = -1;
08431    struct ast_context *c;
08432 
08433    c = find_context_locked(context);
08434    if (c) { /* found, add switch to this context */
08435       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08436       ast_unlock_contexts();
08437    }
08438    return ret;
08439 }

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

08450 {
08451    struct ast_sw *new_sw;
08452    struct ast_sw *i;
08453    int length;
08454    char *p;
08455 
08456    length = sizeof(struct ast_sw);
08457    length += strlen(value) + 1;
08458    if (data)
08459       length += strlen(data);
08460    length++;
08461 
08462    /* allocate new sw structure ... */
08463    if (!(new_sw = ast_calloc(1, length)))
08464       return -1;
08465    /* ... fill in this structure ... */
08466    p = new_sw->stuff;
08467    new_sw->name = p;
08468    strcpy(new_sw->name, value);
08469    p += strlen(value) + 1;
08470    new_sw->data = p;
08471    if (data) {
08472       strcpy(new_sw->data, data);
08473       p += strlen(data) + 1;
08474    } else {
08475       strcpy(new_sw->data, "");
08476       p++;
08477    }
08478    new_sw->eval     = eval;
08479    new_sw->registrar = registrar;
08480 
08481    /* ... try to lock this context ... */
08482    ast_wrlock_context(con);
08483 
08484    /* ... go to last sw and check if context is already swd too... */
08485    AST_LIST_TRAVERSE(&con->alts, i, list) {
08486       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08487          ast_free(new_sw);
08488          ast_unlock_context(con);
08489          errno = EEXIST;
08490          return -1;
08491       }
08492    }
08493 
08494    /* ... sw new context into context list, unlock, return */
08495    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08496 
08497    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08498 
08499    ast_unlock_context(con);
08500 
08501    return 0;
08502 }

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 9829 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 2925 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().

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

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

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

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

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

Referenced by _macro_exec().

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

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

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

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

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

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

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

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

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

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

Definition at line 8508 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

08509 {
08510    int ret = -1;
08511    struct ast_context *c;
08512 
08513    c = find_context_locked(context);
08514    if (c) {
08515       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08516       ast_unlock_contexts();
08517    }
08518    return ret;
08519 }

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

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

08522 {
08523    struct ast_ignorepat *ip, *ipl = NULL;
08524 
08525    ast_wrlock_context(con);
08526 
08527    for (ip = con->ignorepats; ip; ip = ip->next) {
08528       if (!strcmp(ip->pattern, ignorepat) &&
08529          (!registrar || (registrar == ip->registrar))) {
08530          if (ipl) {
08531             ipl->next = ip->next;
08532             ast_free(ip);
08533          } else {
08534             con->ignorepats = ip->next;
08535             ast_free(ip);
08536          }
08537          ast_unlock_context(con);
08538          return 0;
08539       }
08540       ipl = ip;
08541    }
08542 
08543    ast_unlock_context(con);
08544    errno = EINVAL;
08545    return -1;
08546 }

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

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

Referenced by handle_cli_dialplan_remove_include().

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

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

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

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

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

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

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

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

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

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

Referenced by _macro_exec().

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

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

11081 {
11082    struct ast_include *inc = NULL;
11083    int res = 0;
11084 
11085    while ( (inc = ast_walk_context_includes(con, inc)) ) {
11086       if (ast_context_find(inc->rname))
11087          continue;
11088 
11089       res = -1;
11090       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
11091          ast_get_context_name(con), inc->rname);
11092       break;
11093    }
11094 
11095    return res;
11096 }

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

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

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

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

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

08351 {
08352    if (i->timezone) {
08353       ast_free(i->timezone);
08354       i->timezone = NULL;
08355    }
08356    return 0;
08357 }

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

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

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

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

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

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

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

08663 {
08664    if (!chan)
08665       return -1;
08666 
08667    ast_channel_lock(chan);
08668 
08669    if (!ast_strlen_zero(context))
08670       ast_copy_string(chan->context, context, sizeof(chan->context));
08671    if (!ast_strlen_zero(exten))
08672       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08673    if (priority > -1) {
08674       chan->priority = priority;
08675       /* see flag description in channel.h for explanation */
08676       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08677          chan->priority--;
08678    }
08679 
08680    ast_channel_unlock(chan);
08681 
08682    return 0;
08683 }

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

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

02903 {
02904    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02905       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02906    return extension_match_core(pattern, data, needmore);
02907 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02668 {
02669    int cmp;
02670 
02671    cmp = ext_cmp(a, b);
02672    if (cmp < 0) {
02673       return -1;
02674    }
02675    if (cmp > 0) {
02676       return 1;
02677    }
02678    return 0;
02679 }

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

02898 {
02899    return extension_match_core(pattern, data, E_MATCH);
02900 }

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

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

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

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

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

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

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

static int ast_extension_state3 ( struct ast_str hint_app  )  [static]

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

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

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

References ast_extension_state_add_destroy().

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

05091 {
05092    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
05093 }

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

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

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

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

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

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

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

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

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

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

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

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

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

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

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

Definition at line 10970 of file pbx.c.

References ast_context::registrar.

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

10971 {
10972    return c ? c->registrar : NULL;
10973 }

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

References ast_exten::cidmatch.

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

10996 {
10997    return e ? e->cidmatch : NULL;
10998 }

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

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

10938 {
10939    return exten ? exten->parent : NULL;
10940 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 10947 of file pbx.c.

References ast_exten::label.

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

10948 {
10949    return exten ? exten->label : NULL;
10950 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10990 of file pbx.c.

References ast_exten::matchcid.

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

10991 {
10992    return e ? e->matchcid : 0;
10993 }

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

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

10963 {
10964    return exten ? exten->priority : -1;
10965 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10975 of file pbx.c.

References ast_exten::registrar.

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

10976 {
10977    return e ? e->registrar : NULL;
10978 }

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

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

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

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

10986 {
10987    return ip ? ip->registrar : NULL;
10988 }

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

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

10981 {
10982    return i ? i->registrar : NULL;
10983 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

11016 {
11017    return sw ? sw->data : NULL;
11018 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 11020 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

11021 {
11022    return sw->eval;
11023 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

11011 {
11012    return sw ? sw->name : NULL;
11013 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

11026 {
11027    return sw ? sw->registrar : NULL;
11028 }

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

11121 {
11122    return __ast_goto_if_exists(chan, context, exten, priority, 0);
11123 }

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

04790 {
04791    struct ast_exten *e;
04792    ast_rdlock_contexts();
04793    e = ast_hint_extension_nolock(c, context, exten);
04794    ast_unlock_contexts();
04795    return e;
04796 }

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

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

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

08605 {
08606    struct ast_context *con = ast_context_find(context);
08607 
08608    if (con) {
08609       struct ast_ignorepat *pat;
08610 
08611       for (pat = con->ignorepats; pat; pat = pat->next) {
08612          if (ast_extension_match(pat->pattern, pattern))
08613             return 1;
08614       }
08615    }
08616 
08617    return 0;
08618 }

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

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

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

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

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

11186 {
11187    return pbx_parseable_goto(chan, goto_string, 0);
11188 }

int ast_pbx_init ( void   ) 

Provided by pbx.c

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

11267 {
11268    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
11269    statecbs = ao2_container_alloc(1, NULL, statecbs_cmp);
11270 
11271    ast_register_atexit(pbx_shutdown);
11272 
11273    return (hints && statecbs) ? 0 : -1;
11274 }

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

09499 {
09500    struct ast_channel *chan;
09501    struct app_tmp *tmp;
09502    int res = -1, cdr_res = -1;
09503    struct outgoing_helper oh;
09504 
09505    memset(&oh, 0, sizeof(oh));
09506    oh.vars = vars;
09507    oh.account = account;
09508 
09509    if (locked_channel)
09510       *locked_channel = NULL;
09511    if (ast_strlen_zero(app)) {
09512       res = -1;
09513       goto outgoing_app_cleanup;
09514    }
09515    if (synchronous) {
09516       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09517       if (chan) {
09518          ast_set_variables(chan, vars);
09519          if (account)
09520             ast_cdr_setaccount(chan, account);
09521          if (chan->_state == AST_STATE_UP) {
09522             res = 0;
09523             ast_verb(4, "Channel %s was answered.\n", chan->name);
09524             tmp = ast_calloc(1, sizeof(*tmp));
09525             if (!tmp || ast_string_field_init(tmp, 252)) {
09526                if (tmp) {
09527                   ast_free(tmp);
09528                }
09529                res = -1;
09530             } else {
09531                ast_string_field_set(tmp, app, app);
09532                ast_string_field_set(tmp, data, appdata);
09533                tmp->chan = chan;
09534                if (synchronous > 1) {
09535                   if (locked_channel)
09536                      ast_channel_unlock(chan);
09537                   ast_pbx_run_app(tmp);
09538                } else {
09539                   if (locked_channel)
09540                      ast_channel_lock(chan);
09541                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09542                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
09543                      ast_string_field_free_memory(tmp);
09544                      ast_free(tmp);
09545                      if (locked_channel)
09546                         ast_channel_unlock(chan);
09547                      ast_hangup(chan);
09548                      res = -1;
09549                   } else {
09550                      if (locked_channel)
09551                         *locked_channel = chan;
09552                   }
09553                }
09554             }
09555          } else {
09556             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09557             if (chan->cdr) { /* update the cdr */
09558                /* here we update the status of the call, which sould be busy.
09559                 * if that fails then we set the status to failed */
09560                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09561                   ast_cdr_failed(chan->cdr);
09562             }
09563             ast_hangup(chan);
09564          }
09565       }
09566 
09567       if (res < 0) { /* the call failed for some reason */
09568          if (*reason == 0) { /* if the call failed (not busy or no answer)
09569                         * update the cdr with the failed message */
09570             cdr_res = ast_pbx_outgoing_cdr_failed();
09571             if (cdr_res != 0) {
09572                res = cdr_res;
09573                goto outgoing_app_cleanup;
09574             }
09575          }
09576       }
09577 
09578    } else {
09579       struct async_stat *as;
09580       if (!(as = ast_calloc(1, sizeof(*as)))) {
09581          res = -1;
09582          goto outgoing_app_cleanup;
09583       }
09584       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09585       if (!chan) {
09586          ast_free(as);
09587          res = -1;
09588          goto outgoing_app_cleanup;
09589       }
09590       as->chan = chan;
09591       ast_copy_string(as->app, app, sizeof(as->app));
09592       if (appdata)
09593          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09594       as->timeout = timeout;
09595       ast_set_variables(chan, vars);
09596       if (account)
09597          ast_cdr_setaccount(chan, account);
09598       /* Start a new thread, and get something handling this channel. */
09599       if (locked_channel)
09600          ast_channel_lock(chan);
09601       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09602          ast_log(LOG_WARNING, "Failed to start async wait\n");
09603          ast_free(as);
09604          if (locked_channel)
09605             ast_channel_unlock(chan);
09606          ast_hangup(chan);
09607          res = -1;
09608          goto outgoing_app_cleanup;
09609       } else {
09610          if (locked_channel)
09611             *locked_channel = chan;
09612       }
09613       res = 0;
09614    }
09615 outgoing_app_cleanup:
09616    ast_variables_destroy(vars);
09617    return res;
09618 }

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

09303 {
09304    /* allocate a channel */
09305    struct ast_channel *chan = ast_dummy_channel_alloc();
09306 
09307    if (!chan)
09308       return -1;  /* failure */
09309 
09310    chan->cdr = ast_cdr_alloc();
09311    if (!chan->cdr) {
09312       /* allocation of the cdr failed */
09313       chan = ast_channel_unref(chan);   /* free the channel */
09314       return -1;                /* return failure */
09315    }
09316 
09317    /* allocation of the cdr was successful */
09318    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
09319    ast_cdr_start(chan->cdr);       /* record the start and stop time */
09320    ast_cdr_end(chan->cdr);
09321    ast_cdr_failed(chan->cdr);      /* set the status to failed */
09322    ast_cdr_detach(chan->cdr);      /* post and free the record */
09323    chan->cdr = NULL;
09324    chan = ast_channel_unref(chan);         /* free the channel */
09325 
09326    return 0;  /* success */
09327 }

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

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

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

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

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

run the application and free the descriptor once done

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

09483 {
09484    struct app_tmp *tmp = data;
09485    struct ast_app *app;
09486    app = pbx_findapp(tmp->app);
09487    if (app) {
09488       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
09489       pbx_exec(tmp->chan, app, tmp->data);
09490    } else
09491       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
09492    ast_hangup(tmp->chan);
09493    ast_string_field_free_memory(tmp);
09494    ast_free(tmp);
09495    return NULL;
09496 }

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

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

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

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

int ast_processed_calls ( void   ) 

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

Definition at line 5890 of file pbx.c.

References totalcalls.

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

05891 {
05892    return totalcalls;
05893 }

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

10920 {
10921    return ast_rwlock_rdlock(&con->lock);
10922 }

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

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

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

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

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

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

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

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

References E_SPAWN, and pbx_extension_helper().

Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), gosub_run(), and loopback_exec().

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

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

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

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

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

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

04423 {
04424    size_t used;
04425    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04426 }

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

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

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

04429 {
04430    size_t used;
04431    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04432 }

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

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

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

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

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

Referenced by handle_tcptls_connection().

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

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

07660 {
07661    struct ast_app *tmp;
07662 
07663    AST_RWLIST_WRLOCK(&apps);
07664    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
07665       if (!strcasecmp(app, tmp->name)) {
07666          unreference_cached_app(tmp);
07667          AST_RWLIST_REMOVE_CURRENT(list);
07668          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
07669          ast_string_field_free_memory(tmp);
07670          ast_free(tmp);
07671          break;
07672       }
07673    }
07674    AST_RWLIST_TRAVERSE_SAFE_END;
07675    AST_RWLIST_UNLOCK(&apps);
07676 
07677    return tmp ? 0 : -1;
07678 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

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

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

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

11040 {
11041    if (!exten)
11042       return con ? con->root : NULL;
11043    else
11044       return exten->next;
11045 }

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

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

11073 {
11074    if (!ip)
11075       return con ? con->ignorepats : NULL;
11076    else
11077       return ip->next;
11078 }

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

11049 {
11050    if (!sw)
11051       return con ? AST_LIST_FIRST(&con->alts) : NULL;
11052    else
11053       return AST_LIST_NEXT(sw, list);
11054 }

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

11058 {
11059    return priority ? priority->peer : exten;
11060 }

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

10915 {
10916    return ast_rwlock_wrlock(&con->lock);
10917 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

10897 {
10898    return ast_mutex_lock(&conlock);
10899 }

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

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

09240 {
09241    struct async_stat *as = data;
09242    struct ast_channel *chan = as->chan;
09243    int timeout = as->timeout;
09244    int res;
09245    struct ast_frame *f;
09246    struct ast_app *app;
09247    struct timeval start = ast_tvnow();
09248    int ms;
09249 
09250    while ((ms = ast_remaining_ms(start, timeout)) &&
09251          chan->_state != AST_STATE_UP) {
09252       res = ast_waitfor(chan, ms);
09253       if (res < 1)
09254          break;
09255 
09256       f = ast_read(chan);
09257       if (!f)
09258          break;
09259       if (f->frametype == AST_FRAME_CONTROL) {
09260          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
09261              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
09262             ast_frfree(f);
09263             break;
09264          }
09265       }
09266       ast_frfree(f);
09267    }
09268    if (chan->_state == AST_STATE_UP) {
09269       if (!ast_strlen_zero(as->app)) {
09270          app = pbx_findapp(as->app);
09271          if (app) {
09272             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
09273             pbx_exec(chan, app, as->appdata);
09274          } else
09275             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
09276       } else {
09277          if (!ast_strlen_zero(as->context))
09278             ast_copy_string(chan->context, as->context, sizeof(chan->context));
09279          if (!ast_strlen_zero(as->exten))
09280             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
09281          if (as->priority > 0)
09282             chan->priority = as->priority;
09283          /* Run the PBX */
09284          if (ast_pbx_run(chan)) {
09285             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
09286          } else {
09287             /* PBX will have taken care of this */
09288             chan = NULL;
09289          }
09290       }
09291    }
09292    ast_free(as);
09293    if (chan)
09294       ast_hangup(chan);
09295    return NULL;
09296 }

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

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

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

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

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

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

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

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

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

06821 {
06822    struct ast_context *c = NULL;
06823    char *ret = NULL;
06824    int which = 0;
06825    int wordlen;
06826 
06827    /* we are do completion of [exten@]context on second position only */
06828    if (pos != 2)
06829       return NULL;
06830 
06831    ast_rdlock_contexts();
06832 
06833    wordlen = strlen(word);
06834 
06835    /* walk through all contexts and return the n-th match */
06836    while ( (c = ast_walk_contexts(c)) ) {
06837       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
06838          ret = ast_strdup(ast_get_context_name(c));
06839          break;
06840       }
06841    }
06842 
06843    ast_unlock_contexts();
06844 
06845    return ret;
06846 }

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

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

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

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

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

07768 {
07769    struct ast_include *i;
07770    struct ast_ignorepat *ip;
07771    struct ast_sw *sw;
07772 
07773    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);
07774    /* copy in the includes, switches, and ignorepats */
07775    /* walk through includes */
07776    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
07777       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
07778          continue; /* not mine */
07779       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
07780    }
07781 
07782    /* walk through switches */
07783    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
07784       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
07785          continue; /* not mine */
07786       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));
07787    }
07788 
07789    /* walk thru ignorepats ... */
07790    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
07791       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
07792          continue; /* not mine */
07793       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
07794    }
07795 }

static void create_match_char_tree ( struct ast_context con  )  [static]

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

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

static void decrease_call_count ( void   )  [static]

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

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

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

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

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

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

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

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

static void destroy_state_cb ( void *  doomed  )  [static]

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

04993 {
04994    struct ast_state_cb *state_cb = doomed;
04995 
04996    if (state_cb->destroy_cb) {
04997       state_cb->destroy_cb(state_cb->id, state_cb->data);
04998    }
04999 }

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

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

10765 {
10766    const char *device;
10767    struct statechange *sc;
10768 
10769    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
10770    if (ast_strlen_zero(device)) {
10771       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
10772       return;
10773    }
10774 
10775    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
10776       return;
10777    strcpy(sc->dev, device);
10778    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
10779       ast_free(sc);
10780    }
10781 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 3525 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

03526 {
03527    struct pbx_exception *exception = data;
03528    ast_string_field_free_memory(exception);
03529    ast_free(exception);
03530 }

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

Definition at line 2645 of file pbx.c.

References ext_cmp_exten(), and ext_cmp_pattern().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

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

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

Definition at line 2395 of file pbx.c.

Referenced by _extension_match_core(), and ext_cmp().

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

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

Definition at line 2352 of file pbx.c.

Referenced by _extension_match_core().

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

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

Definition at line 2322 of file pbx.c.

References len().

Referenced by _extension_match_core().

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

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

Definition at line 2597 of file pbx.c.

References ARRAY_LEN, and ext_cmp_pattern_pos().

Referenced by _extension_match_core(), and ext_cmp().

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

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

References ast_log(), BITS_PER, and LOG_WARNING.

Referenced by ext_cmp_pattern().

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

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

copy a string skipping whitespace

Definition at line 8781 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

08782 {
08783    int count = 0;
08784    int insquares = 0;
08785 
08786    while (*src && (count < len - 1)) {
08787       if (*src == '[') {
08788          insquares = 1;
08789       } else if (*src == ']') {
08790          insquares = 0;
08791       } else if (*src == ' ' && !insquares) {
08792          src++;
08793          continue;
08794       }
08795       *dst = *src;
08796       dst++;
08797       src++;
08798       count++;
08799    }
08800    *dst = '\0';
08801 
08802    return count;
08803 }

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

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

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

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

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

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

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

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

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

Remove a watcher from the callback list.

Definition at line 5096 of file pbx.c.

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

Referenced by ast_extension_state_del().

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

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

References args, ast_log(), and LOG_WARNING.

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

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

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

Definition at line 1683 of file pbx.c.

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

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

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

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

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

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

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

Referenced by ast_build_timing().

08137 {
08138    int start, end; /* start and ending position */
08139    unsigned int mask = 0;
08140    char *part;
08141 
08142    /* Check for whole range */
08143    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
08144       return (1 << max) - 1;
08145    }
08146 
08147    while ((part = strsep(&src, "&"))) {
08148       /* Get start and ending position */
08149       char *endpart = strchr(part, '-');
08150       if (endpart) {
08151          *endpart++ = '\0';
08152       }
08153       /* Find the start */
08154       if ((start = lookup_name(part, names, max)) < 0) {
08155          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
08156          continue;
08157       }
08158       if (endpart) { /* find end of range */
08159          if ((end = lookup_name(endpart, names, max)) < 0) {
08160             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
08161             continue;
08162          }
08163       } else {
08164          end = start;
08165       }
08166       /* Fill the mask. Remember that ranges are cyclic */
08167       mask |= (1 << end);   /* initialize with last element */
08168       while (start != end) {
08169          mask |= (1 << start);
08170          if (++start >= max) {
08171             start = 0;
08172          }
08173       }
08174    }
08175    return mask;
08176 }

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

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

Referenced by ast_build_timing().

08180 {
08181    char *endpart, *part;
08182    int x;
08183    int st_h, st_m;
08184    int endh, endm;
08185    int minute_start, minute_end;
08186 
08187    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
08188    memset(i->minmask, 0, sizeof(i->minmask));
08189 
08190    /* 1-minute per bit */
08191    /* Star is all times */
08192    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
08193       /* 48, because each hour takes 2 integers; 30 bits each */
08194       for (x = 0; x < 48; x++) {
08195          i->minmask[x] = 0x3fffffff; /* 30 bits */
08196       }
08197       return;
08198    }
08199    /* Otherwise expect a range */
08200    while ((part = strsep(&times, "&"))) {
08201       if (!(endpart = strchr(part, '-'))) {
08202          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
08203             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
08204             continue;
08205          }
08206          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
08207          continue;
08208       }
08209       *endpart++ = '\0';
08210       /* why skip non digits? Mostly to skip spaces */
08211       while (*endpart && !isdigit(*endpart)) {
08212          endpart++;
08213       }
08214       if (!*endpart) {
08215          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
08216          continue;
08217       }
08218       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
08219          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
08220          continue;
08221       }
08222       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
08223          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
08224          continue;
08225       }
08226       minute_start = st_h * 60 + st_m;
08227       minute_end = endh * 60 + endm;
08228       /* Go through the time and enable each appropriate bit */
08229       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
08230          i->minmask[x / 30] |= (1 << (x % 30));
08231       }
08232       /* Do the last one */
08233       i->minmask[x / 30] |= (1 << (x % 30));
08234    }
08235    /* All done */
08236    return;
08237 }

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

Send ack once.

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

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

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

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

07524 {
07525    struct ast_channel *chan;
07526    const char *chan_name, *var_name, *var_value;
07527 
07528    switch (cmd) {
07529    case CLI_INIT:
07530       e->command = "dialplan set chanvar";
07531       e->usage =
07532          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
07533          "       Set channel variable <varname> to <value>\n";
07534       return NULL;
07535    case CLI_GENERATE:
07536       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07537    }
07538 
07539    if (a->argc != e->args + 3)
07540       return CLI_SHOWUSAGE;
07541 
07542    chan_name = a->argv[e->args];
07543    var_name = a->argv[e->args + 1];
07544    var_value = a->argv[e->args + 2];
07545 
07546    if (!(chan = ast_channel_get_by_name(chan_name))) {
07547       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
07548       return CLI_FAILURE;
07549    }
07550 
07551    pbx_builtin_setvar_helper(chan, var_name, var_value);
07552 
07553    chan = ast_channel_unref(chan);
07554 
07555    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
07556 
07557    return CLI_SUCCESS;
07558 }

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

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

07561 {
07562    int oldval = 0;
07563 
07564    switch (cmd) {
07565    case CLI_INIT:
07566       e->command = "dialplan set extenpatternmatchnew true";
07567       e->usage =
07568          "Usage: dialplan set extenpatternmatchnew true|false\n"
07569          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07570       return NULL;
07571    case CLI_GENERATE:
07572       return NULL;
07573    }
07574 
07575    if (a->argc != 4)
07576       return CLI_SHOWUSAGE;
07577 
07578    oldval =  pbx_set_extenpatternmatchnew(1);
07579 
07580    if (oldval)
07581       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
07582    else
07583       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
07584 
07585    return CLI_SUCCESS;
07586 }

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

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

07502 {
07503    switch (cmd) {
07504    case CLI_INIT:
07505       e->command = "dialplan set global";
07506       e->usage =
07507          "Usage: dialplan set global <name> <value>\n"
07508          "       Set global dialplan variable <name> to <value>\n";
07509       return NULL;
07510    case CLI_GENERATE:
07511       return NULL;
07512    }
07513 
07514    if (a->argc != e->args + 2)
07515       return CLI_SHOWUSAGE;
07516 
07517    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
07518    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
07519 
07520    return CLI_SUCCESS;
07521 }

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

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

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

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

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

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

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

07467 {
07468    struct ast_channel *chan = NULL;
07469    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
07470 
07471    switch (cmd) {
07472    case CLI_INIT:
07473       e->command = "dialplan show chanvar";
07474       e->usage =
07475          "Usage: dialplan show chanvar <channel>\n"
07476          "       List current channel variables and their values\n";
07477       return NULL;
07478    case CLI_GENERATE:
07479       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07480    }
07481 
07482    if (a->argc != e->args + 1)
07483       return CLI_SHOWUSAGE;
07484 
07485    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
07486       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
07487       return CLI_FAILURE;
07488    }
07489 
07490    pbx_builtin_serialize_variables(chan, &vars);
07491 
07492    if (ast_str_strlen(vars)) {
07493       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
07494    }
07495 
07496    chan = ast_channel_unref(chan);
07497 
07498    return CLI_SUCCESS;
07499 }

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

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

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

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

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

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

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

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

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

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

07409 {
07410    int i = 0;
07411    struct ast_var_t *newvariable;
07412 
07413    switch (cmd) {
07414    case CLI_INIT:
07415       e->command = "dialplan show globals";
07416       e->usage =
07417          "Usage: dialplan show globals\n"
07418          "       List current global dialplan variables and their values\n";
07419       return NULL;
07420    case CLI_GENERATE:
07421       return NULL;
07422    }
07423 
07424    ast_rwlock_rdlock(&globalslock);
07425    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
07426       i++;
07427       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
07428    }
07429    ast_rwlock_unlock(&globalslock);
07430    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
07431 
07432    return CLI_SUCCESS;
07433 }

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

06640 {
06641    struct ast_hint *hint;
06642    int watchers;
06643    int num = 0, extenlen;
06644    struct ao2_iterator i;
06645 
06646    switch (cmd) {
06647    case CLI_INIT:
06648       e->command = "core show hint";
06649       e->usage =
06650          "Usage: core show hint <exten>\n"
06651          "       List registered hint.\n"
06652          "       Hint details are shown in four columns. In order from left to right, they are:\n"
06653          "       1. Hint extension URI.\n"
06654          "       2. Mapped device state identifiers.\n"
06655          "       3. Current extension state. The aggregate of mapped device states.\n"
06656          "       4. Watchers - number of subscriptions and other entities watching this hint.\n";
06657 
06658       return NULL;
06659    case CLI_GENERATE:
06660       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
06661    }
06662 
06663    if (a->argc < 4)
06664       return CLI_SHOWUSAGE;
06665 
06666    if (ao2_container_count(hints) == 0) {
06667       ast_cli(a->fd, "There are no registered dialplan hints\n");
06668       return CLI_SUCCESS;
06669    }
06670    
06671    extenlen = strlen(a->argv[3]);
06672    i = ao2_iterator_init(hints, 0);
06673    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06674       ao2_lock(hint);
06675       if (!hint->exten) {
06676          /* The extension has already been destroyed */
06677          ao2_unlock(hint);
06678          continue;
06679       }
06680       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
06681          watchers = ao2_container_count(hint->callbacks);
06682          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06683             ast_get_extension_name(hint->exten),
06684             ast_get_context_name(ast_get_extension_context(hint->exten)),
06685             ast_get_extension_app(hint->exten),
06686             ast_extension_state2str(hint->laststate), watchers);
06687          num++;
06688       }
06689       ao2_unlock(hint);
06690    }
06691    ao2_iterator_destroy(&i);
06692    if (!num)
06693       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
06694    else
06695       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
06696    return CLI_SUCCESS;
06697 }

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

06549 {
06550    struct ast_hint *hint;
06551    int num = 0;
06552    int watchers;
06553    struct ao2_iterator i;
06554 
06555    switch (cmd) {
06556    case CLI_INIT:
06557       e->command = "core show hints";
06558       e->usage =
06559          "Usage: core show hints\n"
06560          "       List registered hints.\n"
06561          "       Hint details are shown in four columns. In order from left to right, they are:\n"
06562          "       1. Hint extension URI.\n"
06563          "       2. Mapped device state identifiers.\n"
06564          "       3. Current extension state. The aggregate of mapped device states.\n"
06565          "       4. Watchers - number of subscriptions and other entities watching this hint.\n";
06566       return NULL;
06567    case CLI_GENERATE:
06568       return NULL;
06569    }
06570 
06571    if (ao2_container_count(hints) == 0) {
06572       ast_cli(a->fd, "There are no registered dialplan hints\n");
06573       return CLI_SUCCESS;
06574    }
06575    /* ... we have hints ... */
06576    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
06577 
06578    i = ao2_iterator_init(hints, 0);
06579    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06580       ao2_lock(hint);
06581       if (!hint->exten) {
06582          /* The extension has already been destroyed */
06583          ao2_unlock(hint);
06584          continue;
06585       }
06586       watchers = ao2_container_count(hint->callbacks);
06587       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06588          ast_get_extension_name(hint->exten),
06589          ast_get_context_name(ast_get_extension_context(hint->exten)),
06590          ast_get_extension_app(hint->exten),
06591          ast_extension_state2str(hint->laststate), watchers);
06592       ao2_unlock(hint);
06593       num++;
06594    }
06595    ao2_iterator_destroy(&i);
06596 
06597    ast_cli(a->fd, "----------------\n");
06598    ast_cli(a->fd, "- %d hints registered\n", num);
06599    return CLI_SUCCESS;
06600 }

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

06702 {
06703    struct ast_switch *sw;
06704 
06705    switch (cmd) {
06706    case CLI_INIT:
06707       e->command = "core show switches";
06708       e->usage =
06709          "Usage: core show switches\n"
06710          "       List registered switches\n";
06711       return NULL;
06712    case CLI_GENERATE:
06713       return NULL;
06714    }
06715 
06716    AST_RWLIST_RDLOCK(&switches);
06717 
06718    if (AST_RWLIST_EMPTY(&switches)) {
06719       AST_RWLIST_UNLOCK(&switches);
06720       ast_cli(a->fd, "There are no registered alternative switches\n");
06721       return CLI_SUCCESS;
06722    }
06723 
06724    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
06725    AST_RWLIST_TRAVERSE(&switches, sw, list)
06726       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
06727 
06728    AST_RWLIST_UNLOCK(&switches);
06729 
06730    return CLI_SUCCESS;
06731 }

static int handle_statechange ( void *  datap  )  [static]

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

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

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

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

07589 {
07590    int oldval = 0;
07591 
07592    switch (cmd) {
07593    case CLI_INIT:
07594       e->command = "dialplan set extenpatternmatchnew false";
07595       e->usage =
07596          "Usage: dialplan set extenpatternmatchnew true|false\n"
07597          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07598       return NULL;
07599    case CLI_GENERATE:
07600       return NULL;
07601    }
07602 
07603    if (a->argc != 4)
07604       return CLI_SHOWUSAGE;
07605 
07606    oldval =  pbx_set_extenpatternmatchnew(0);
07607 
07608    if (!oldval)
07609       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
07610    else
07611       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
07612 
07613    return CLI_SUCCESS;
07614 }

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

References CMP_MATCH, CMP_STOP, and ast_hint::exten.

Referenced by ast_pbx_init().

11235 {
11236    const struct ast_hint *hint = obj;
11237    const struct ast_exten *exten = arg;
11238 
11239    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
11240 }

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

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

11215 {
11216    const struct ast_hint *hint = obj;
11217    const char *exten_name;
11218    int res;
11219 
11220    exten_name = ast_get_extension_name(hint->exten);
11221    if (ast_strlen_zero(exten_name)) {
11222       /*
11223        * If the exten or extension name isn't set, return 0 so that
11224        * the ao2_find() search will start in the first bucket.
11225        */
11226       res = 0;
11227    } else {
11228       res = ast_str_case_hash(exten_name);
11229    }
11230 
11231    return res;
11232 }

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

Definition at line 5145 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

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

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

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

10789 {
10790    struct ast_data *data_hint;
10791    struct ast_hint *hint;
10792    int watchers;
10793    struct ao2_iterator i;
10794 
10795    if (ao2_container_count(hints) == 0) {
10796       return 0;
10797    }
10798 
10799    i = ao2_iterator_init(hints, 0);
10800    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
10801       watchers = ao2_container_count(hint->callbacks);
10802       data_hint = ast_data_add_node(data_root, "hint");
10803       if (!data_hint) {
10804          continue;
10805       }
10806       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
10807       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
10808       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
10809       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
10810       ast_data_add_int(data_hint, "watchers", watchers);
10811 
10812       if (!ast_data_search_match(search, data_hint)) {
10813          ast_data_remove_node(data_root, data_hint);
10814       }
10815    }
10816    ao2_iterator_destroy(&i);
10817 
10818    return 0;
10819 }

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

Definition at line 1519 of file pbx.c.

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

Referenced by pbx_find_extension().

01520 {
01521    if (!i->hastime)
01522       return 1;
01523 
01524    return ast_check_timing(&(i->timing));
01525 }

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

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

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

Definition at line 1937 of file pbx.c.

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

Referenced by add_pattern_node().

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

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

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

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

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

Referenced by ast_func_write().

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

int load_pbx ( void   ) 

Provided by pbx.c

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

10856 {
10857    int x;
10858 
10859    ast_register_atexit(unload_pbx);
10860 
10861    /* Initialize the PBX */
10862    ast_verb(1, "Asterisk PBX Core Initializing\n");
10863    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
10864       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
10865    }
10866 
10867    ast_verb(1, "Registering builtin applications:\n");
10868    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
10869    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
10870    __ast_custom_function_register(&exception_function, NULL);
10871    __ast_custom_function_register(&testtime_function, NULL);
10872 
10873    /* Register builtin applications */
10874    for (x = 0; x < ARRAY_LEN(builtins); x++) {
10875       ast_verb(1, "[%s]\n", builtins[x].name);
10876       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
10877          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
10878          return -1;
10879       }
10880    }
10881 
10882    /* Register manager application */
10883    ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
10884 
10885    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
10886          AST_EVENT_IE_END))) {
10887       return -1;
10888    }
10889 
10890    return 0;
10891 }

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

Referenced by get_range().

08114 {
08115    int i;
08116 
08117    if (names && *s > '9') {
08118       for (i = 0; names[i]; i++) {
08119          if (!strcasecmp(s, names[i])) {
08120             return i;
08121          }
08122       }
08123    }
08124 
08125    /* Allow months and weekdays to be specified as numbers, as well */
08126    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
08127       /* What the array offset would have been: "1" would be at offset 0 */
08128       return i - 1;
08129    }
08130    return -1; /* error return */
08131 }

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

Send ack once.

Definition at line 7206 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

07207 {
07208    astman_send_listack(s, m, "DialPlan list will follow", "start");
07209 }

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

Manager listing of dial plan.

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

07352 {
07353    const char *exten, *context;
07354    const char *id = astman_get_header(m, "ActionID");
07355    char idtext[256];
07356 
07357    /* Variables used for different counters */
07358    struct dialplan_counters counters;
07359 
07360    if (!ast_strlen_zero(id))
07361       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
07362    else
07363       idtext[0] = '\0';
07364 
07365    memset(&counters, 0, sizeof(counters));
07366 
07367    exten = astman_get_header(m, "Extension");
07368    context = astman_get_header(m, "Context");
07369 
07370    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
07371 
07372    if (!ast_strlen_zero(context) && !counters.context_existence) {
07373       char errorbuf[BUFSIZ];
07374 
07375       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
07376       astman_send_error(s, m, errorbuf);
07377       return 0;
07378    }
07379    if (!ast_strlen_zero(exten) && !counters.extension_existence) {
07380       char errorbuf[BUFSIZ];
07381 
07382       if (!ast_strlen_zero(context))
07383          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
07384       else
07385          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
07386       astman_send_error(s, m, errorbuf);
07387       return 0;
07388    }
07389 
07390    if (!counters.total_items) {
07391       manager_dpsendack(s, m);
07392    }
07393 
07394    astman_append(s, "Event: ShowDialPlanComplete\r\n"
07395       "EventList: Complete\r\n"
07396       "ListItems: %d\r\n"
07397       "ListExtensions: %d\r\n"
07398       "ListPriorities: %d\r\n"
07399       "ListContexts: %d\r\n"
07400       "%s"
07401       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
07402 
07403    /* everything ok */
07404    return 0;
07405 }

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

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

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

Definition at line 2955 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

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

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

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

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

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

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

void pbx_builtin_clear_globals ( void   ) 

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

10664 {
10665    struct ast_var_t *vardata;
10666 
10667    ast_rwlock_wrlock(&globalslock);
10668    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10669       ast_var_delete(vardata);
10670    ast_rwlock_unlock(&globalslock);
10671 }

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

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

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

10430 {
10431    struct ast_var_t *variables;
10432    const char *ret = NULL;
10433    int i;
10434    struct varshead *places[2] = { NULL, &globals };
10435 
10436    if (!name)
10437       return NULL;
10438 
10439    if (chan) {
10440       ast_channel_lock(chan);
10441       places[0] = &chan->varshead;
10442    }
10443 
10444    for (i = 0; i < 2; i++) {
10445       if (!places[i])
10446          continue;
10447       if (places[i] == &globals)
10448          ast_rwlock_rdlock(&globalslock);
10449       AST_LIST_TRAVERSE(places[i], variables, entries) {
10450          if (!strcmp(name, ast_var_name(variables))) {
10451             ret = ast_var_value(variables);
10452             break;
10453          }
10454       }
10455       if (places[i] == &globals)
10456          ast_rwlock_unlock(&globalslock);
10457       if (ret)
10458          break;
10459    }
10460 
10461    if (chan)
10462       ast_channel_unlock(chan);
10463 
10464    return ret;
10465 }

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

Definition at line 10685 of file pbx.c.

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

10686 {
10687    char *condition, *branch1, *branch2, *branch;
10688    char *stringp;
10689 
10690    if (ast_strlen_zero(data)) {
10691       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
10692       return 0;
10693    }
10694 
10695    stringp = ast_strdupa(data);
10696    condition = strsep(&stringp,"?");
10697    branch1 = strsep(&stringp,":");
10698    branch2 = strsep(&stringp,"");
10699    branch = pbx_checkcondition(condition) ? branch1 : branch2;
10700 
10701    if (ast_strlen_zero(branch)) {
10702       ast_debug(1, "Not taking any branch\n");
10703       return 0;
10704    }
10705 
10706    return pbx_builtin_goto(chan, branch);
10707 }

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

10624 {
10625    char *name;
10626    char *value;
10627    char *channel;
10628    char tmp[VAR_BUF_SIZE];
10629    static int deprecation_warning = 0;
10630 
10631    if (ast_strlen_zero(data)) {
10632       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
10633       return 0;
10634    }
10635    tmp[0] = 0;
10636    if (!deprecation_warning) {
10637       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
10638       deprecation_warning = 1;
10639    }
10640 
10641    value = ast_strdupa(data);
10642    name = strsep(&value,"=");
10643    channel = strsep(&value,",");
10644    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
10645       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
10646       if (chan2) {
10647          char *s = ast_alloca(strlen(value) + 4);
10648          sprintf(s, "${%s}", value);
10649          pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
10650          chan2 = ast_channel_unref(chan2);
10651       }
10652       pbx_builtin_setvar_helper(chan, name, tmp);
10653    }
10654 
10655    return(0);
10656 }

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

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

09951 {
09952    const char *options = data;
09953    int answer = 1;
09954 
09955    /* Some channels can receive DTMF in unanswered state; some cannot */
09956    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
09957       answer = 0;
09958    }
09959 
09960    /* If the channel is hungup, stop waiting */
09961    if (ast_check_hangup(chan)) {
09962       return -1;
09963    } else if (chan->_state != AST_STATE_UP && answer) {
09964       __ast_answer(chan, 0, 1);
09965    }
09966 
09967    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
09968 
09969    return AST_PBX_INCOMPLETE;
09970 }

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

Definition at line 10658 of file pbx.c.

10659 {
10660    return 0;
10661 }

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

10468 {
10469    struct ast_var_t *newvariable;
10470    struct varshead *headp;
10471 
10472    if (name[strlen(name)-1] == ')') {
10473       char *function = ast_strdupa(name);
10474 
10475       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10476       ast_func_write(chan, function, value);
10477       return;
10478    }
10479 
10480    if (chan) {
10481       ast_channel_lock(chan);
10482       headp = &chan->varshead;
10483    } else {
10484       ast_rwlock_wrlock(&globalslock);
10485       headp = &globals;
10486    }
10487 
10488    if (value && (newvariable = ast_var_assign(name, value))) {
10489       if (headp == &globals)
10490          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10491       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10492    }
10493 
10494    if (chan)
10495       ast_channel_unlock(chan);
10496    else
10497       ast_rwlock_unlock(&globalslock);
10498 }

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

Definition at line 3574 of file pbx.c.

References raise_exception().

03575 {
03576    /* Priority will become 1, next time through the AUTOLOOP */
03577    return raise_exception(chan, reason, 0);
03578 }

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

Definition at line 10746 of file pbx.c.

References ast_say_character_str().

10747 {
10748    int res = 0;
10749 
10750    if (data)
10751       res = ast_say_character_str(chan, data, "", chan->language);
10752    return res;
10753 }

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

Definition at line 10737 of file pbx.c.

References ast_say_digit_str().

10738 {
10739    int res = 0;
10740 
10741    if (data)
10742       res = ast_say_digit_str(chan, data, "", chan->language);
10743    return res;
10744 }

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

Definition at line 10709 of file pbx.c.

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

10710 {
10711    char tmp[256];
10712    char *number = tmp;
10713    char *options;
10714 
10715    if (ast_strlen_zero(data)) {
10716       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
10717       return -1;
10718    }
10719    ast_copy_string(tmp, data, sizeof(tmp));
10720    strsep(&number, ",");
10721    options = strsep(&number, ",");
10722    if (options) {
10723       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
10724          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
10725          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
10726          return -1;
10727       }
10728    }
10729 
10730    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
10731       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
10732    }
10733 
10734    return 0;
10735 }

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

Definition at line 10755 of file pbx.c.

References ast_say_phonetic_str().

10756 {
10757    int res = 0;
10758 
10759    if (data)
10760       res = ast_say_phonetic_str(chan, data, "", chan->language);
10761    return res;
10762 }

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

10399 {
10400    struct ast_var_t *variables;
10401    const char *var, *val;
10402    int total = 0;
10403 
10404    if (!chan)
10405       return 0;
10406 
10407    ast_str_reset(*buf);
10408 
10409    ast_channel_lock(chan);
10410 
10411    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10412       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10413          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10414          ) {
10415          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10416             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10417             break;
10418          } else
10419             total++;
10420       } else
10421          break;
10422    }
10423 
10424    ast_channel_unlock(chan);
10425 
10426    return total;
10427 }

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

10558 {
10559    char *name, *value, *mydata;
10560 
10561    if (ast_compat_app_set) {
10562       return pbx_builtin_setvar_multiple(chan, data);
10563    }
10564 
10565    if (ast_strlen_zero(data)) {
10566       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10567       return 0;
10568    }
10569 
10570    mydata = ast_strdupa(data);
10571    name = strsep(&mydata, "=");
10572    value = mydata;
10573    if (!value) {
10574       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10575       return 0;
10576    }
10577 
10578    if (strchr(name, ' ')) {
10579       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10580    }
10581 
10582    pbx_builtin_setvar_helper(chan, name, value);
10583 
10584    return 0;
10585 }

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 10500 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(), gosub_run(), handle_gosub(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_call_full(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), ring_entry(), rollback_exec(), rotate_file(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().

10501 {
10502    struct ast_var_t *newvariable;
10503    struct varshead *headp;
10504    const char *nametail = name;
10505 
10506    if (name[strlen(name) - 1] == ')') {
10507       char *function = ast_strdupa(name);
10508 
10509       return ast_func_write(chan, function, value);
10510    }
10511 
10512    if (chan) {
10513       ast_channel_lock(chan);
10514       headp = &chan->varshead;
10515    } else {
10516       ast_rwlock_wrlock(&globalslock);
10517       headp = &globals;
10518    }
10519 
10520    /* For comparison purposes, we have to strip leading underscores */
10521    if (*nametail == '_') {
10522       nametail++;
10523       if (*nametail == '_')
10524          nametail++;
10525    }
10526 
10527    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10528       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10529          /* there is already such a variable, delete it */
10530          AST_LIST_REMOVE_CURRENT(entries);
10531          ast_var_delete(newvariable);
10532          break;
10533       }
10534    }
10535    AST_LIST_TRAVERSE_SAFE_END;
10536 
10537    if (value && (newvariable = ast_var_assign(name, value))) {
10538       if (headp == &globals)
10539          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10540       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10541       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10542          "Channel: %s\r\n"
10543          "Variable: %s\r\n"
10544          "Value: %s\r\n"
10545          "Uniqueid: %s\r\n",
10546          chan ? chan->name : "none", name, value,
10547          chan ? chan->uniqueid : "none");
10548    }
10549 
10550    if (chan)
10551       ast_channel_unlock(chan);
10552    else
10553       ast_rwlock_unlock(&globalslock);
10554    return 0;
10555 }

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

10588 {
10589    char *data;
10590    int x;
10591    AST_DECLARE_APP_ARGS(args,
10592       AST_APP_ARG(pair)[24];
10593    );
10594    AST_DECLARE_APP_ARGS(pair,
10595       AST_APP_ARG(name);
10596       AST_APP_ARG(value);
10597    );
10598 
10599    if (ast_strlen_zero(vdata)) {
10600       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10601       return 0;
10602    }
10603 
10604    data = ast_strdupa(vdata);
10605    AST_STANDARD_APP_ARGS(args, data);
10606 
10607    for (x = 0; x < args.argc; x++) {
10608       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10609       if (pair.argc == 2) {
10610          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10611          if (strchr(pair.name, ' '))
10612             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);
10613       } else if (!chan) {
10614          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10615       } else {
10616          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10617       }
10618    }
10619 
10620    return 0;
10621 }

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

10674 {
10675    int res;
10676    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10677       return 0;
10678    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10679       return res;
10680    } else {                                         /* Strings are true */
10681       return 1;
10682    }
10683 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1527 of file pbx.c.

References ast_free.

Referenced by __ast_pbx_run().

01528 {
01529    ast_free(p);
01530 }

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_exec_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().

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

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

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

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

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

Definition at line 1505 of file pbx.c.

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

Referenced by pbx_find_extension().

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

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

References ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by ast_readconfig().

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

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

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

11131 {
11132    char *exten, *pri, *context;
11133    char *stringp;
11134    int ipri;
11135    int mode = 0;
11136 
11137    if (ast_strlen_zero(goto_string)) {
11138       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
11139       return -1;
11140    }
11141    stringp = ast_strdupa(goto_string);
11142    context = strsep(&stringp, ","); /* guaranteed non-null */
11143    exten = strsep(&stringp, ",");
11144    pri = strsep(&stringp, ",");
11145    if (!exten) {  /* Only a priority in this one */
11146       pri = context;
11147       exten = NULL;
11148       context = NULL;
11149    } else if (!pri) {   /* Only an extension and priority in this one */
11150       pri = exten;
11151       exten = context;
11152       context = NULL;
11153    }
11154    if (*pri == '+') {
11155       mode = 1;
11156       pri++;
11157    } else if (*pri == '-') {
11158       mode = -1;
11159       pri++;
11160    }
11161    if (sscanf(pri, "%30d", &ipri) != 1) {
11162       ipri = ast_findlabel_extension(chan, context ? context : chan->context,
11163          exten ? exten : chan->exten, pri,
11164          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
11165       if (ipri < 1) {
11166          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
11167          return -1;
11168       } else
11169          mode = 0;
11170    }
11171    /* At this point we have a priority and maybe an extension and a context */
11172 
11173    if (mode)
11174       ipri = chan->priority + (ipri * mode);
11175 
11176    if (async)
11177       ast_async_goto(chan, context, exten, ipri);
11178    else
11179       ast_explicit_goto(chan, context, exten, ipri);
11180 
11181    return 0;
11182 
11183 }

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

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

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

References autofallthrough.

Referenced by pbx_load_module().

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

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

References extenpatternmatchnew.

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

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

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

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

Referenced by pbx_load_module().

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

static void pbx_shutdown ( void   )  [static]

Definition at line 11250 of file pbx.c.

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

Referenced by ast_pbx_init().

11251 {
11252    if (hints) {
11253       ao2_ref(hints, -1);
11254       hints = NULL;
11255    }
11256    if (statecbs) {
11257       ao2_ref(statecbs, -1);
11258       statecbs = NULL;
11259    }
11260    if (contexts_table) {
11261       ast_hashtab_destroy(contexts_table, NULL);
11262    }
11263    pbx_builtin_clear_globals();
11264 }

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

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

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

Definition at line 4636 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

04637 {
04638    size_t used;
04639    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04640 }

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

Definition at line 5813 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

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

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

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

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

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

helper function to print an extension

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

06860 {
06861    int prio = ast_get_extension_priority(e);
06862    if (prio == PRIORITY_HINT) {
06863       snprintf(buf, buflen, "hint: %s",
06864          ast_get_extension_app(e));
06865    } else {
06866       snprintf(buf, buflen, "%d. %s(%s)",
06867          prio, ast_get_extension_app(e),
06868          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06869    }
06870 }

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 11242 of file pbx.c.

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

11243 {
11244    const struct ast_state_cb *state_cb = obj;
11245    ast_state_cb_type change_cb = arg;
11246 
11247    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
11248 }

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

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

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

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

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

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

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

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

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

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

07641 {
07642    struct ast_context *context = NULL;
07643    struct ast_exten *eroot = NULL, *e = NULL;
07644 
07645    ast_rdlock_contexts();
07646    while ((context = ast_walk_contexts(context))) {
07647       while ((eroot = ast_walk_context_extensions(context, eroot))) {
07648          while ((e = ast_walk_extension_priorities(eroot, e))) {
07649             if (e->cached_app == app)
07650                e->cached_app = NULL;
07651          }
07652       }
07653    }
07654    ast_unlock_contexts();
07655 
07656    return;
07657 }

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

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

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

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

09837 {
09838    int res;
09839    struct ast_frame *f;
09840    double waitsec;
09841    int waittime;
09842 
09843    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
09844       waitsec = -1;
09845    if (waitsec > -1) {
09846       waittime = waitsec * 1000.0;
09847       ast_safe_sleep(chan, waittime);
09848    } else do {
09849       res = ast_waitfor(chan, -1);
09850       if (res < 0)
09851          return;
09852       f = ast_read(chan);
09853       if (f)
09854          ast_frfree(f);
09855    } while(f);
09856 }

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

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


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

Referenced by load_pbx(), and unload_pbx().

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

Definition at line 3532 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 10821 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 8251 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 7619 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 10826 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 9977 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 10068 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 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1