Wed Aug 7 17:16:07 2019

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_saydate (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 *)
static int pbx_builtin_saytime (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 841 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 840 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 842 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 839 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 828 of file pbx.c.

Referenced by pbx_extension_helper(), and realtime_exec().

#define HASH_EXTENHINT_SIZE   563

Definition at line 1028 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 2995 of file pbx.c.

#define STATUS_NO_EXTENSION   2

Definition at line 2996 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2998 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2997 of file pbx.c.

#define STATUS_SUCCESS   5

Definition at line 2999 of file pbx.c.

#define SWITCH_DATA_LENGTH   256

Definition at line 831 of file pbx.c.

#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3

Definition at line 837 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 835 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 836 of file pbx.c.

#define WAITEXTEN_DIALTONE   (1 << 1)

Definition at line 852 of file pbx.c.

Referenced by pbx_builtin_waitexten().

#define WAITEXTEN_MOH   (1 << 0)

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

09719 {
09720    struct ast_context *tmp, *tmpl=NULL;
09721    struct ast_exten *exten_item, *prio_item;
09722 
09723    for (tmp = list; tmp; ) {
09724       struct ast_context *next = NULL; /* next starting point */
09725          /* The following code used to skip forward to the next
09726             context with matching registrar, but this didn't
09727             make sense; individual priorities registrar'd to
09728             the matching registrar could occur in any context! */
09729       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
09730       if (con) {
09731          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
09732             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
09733             if ( !strcasecmp(tmp->name, con->name) ) {
09734                break;   /* found it */
09735             }
09736          }
09737       }
09738 
09739       if (!tmp)   /* not found, we are done */
09740          break;
09741       ast_wrlock_context(tmp);
09742 
09743       if (registrar) {
09744          /* then search thru and remove any extens that match registrar. */
09745          struct ast_hashtab_iter *exten_iter;
09746          struct ast_hashtab_iter *prio_iter;
09747          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
09748          struct ast_include *i, *pi = NULL, *ni = NULL;
09749          struct ast_sw *sw = NULL;
09750 
09751          /* remove any ignorepats whose registrar matches */
09752          for (ip = tmp->ignorepats; ip; ip = ipn) {
09753             ipn = ip->next;
09754             if (!strcmp(ip->registrar, registrar)) {
09755                if (ipl) {
09756                   ipl->next = ip->next;
09757                   ast_free(ip);
09758                   continue; /* don't change ipl */
09759                } else {
09760                   tmp->ignorepats = ip->next;
09761                   ast_free(ip);
09762                   continue; /* don't change ipl */
09763                }
09764             }
09765             ipl = ip;
09766          }
09767          /* remove any includes whose registrar matches */
09768          for (i = tmp->includes; i; i = ni) {
09769             ni = i->next;
09770             if (strcmp(i->registrar, registrar) == 0) {
09771                /* remove from list */
09772                if (pi) {
09773                   pi->next = i->next;
09774                   /* free include */
09775                   ast_free(i);
09776                   continue; /* don't change pi */
09777                } else {
09778                   tmp->includes = i->next;
09779                   /* free include */
09780                   ast_free(i);
09781                   continue; /* don't change pi */
09782                }
09783             }
09784             pi = i;
09785          }
09786          /* remove any switches whose registrar matches */
09787          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
09788             if (strcmp(sw->registrar,registrar) == 0) {
09789                AST_LIST_REMOVE_CURRENT(list);
09790                ast_free(sw);
09791             }
09792          }
09793          AST_LIST_TRAVERSE_SAFE_END;
09794 
09795          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
09796             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
09797             while ((exten_item=ast_hashtab_next(exten_iter))) {
09798                int end_traversal = 1;
09799                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
09800                while ((prio_item=ast_hashtab_next(prio_iter))) {
09801                   char extension[AST_MAX_EXTENSION];
09802                   char cidmatch[AST_MAX_EXTENSION];
09803                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
09804                      continue;
09805                   }
09806                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
09807                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
09808                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
09809                   if (prio_item->cidmatch) {
09810                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
09811                   }
09812                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
09813                }
09814                /* Explanation:
09815                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
09816                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
09817                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
09818                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
09819                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
09820                 * free the iterator
09821                 */
09822                if (end_traversal) {
09823                   ast_hashtab_end_traversal(prio_iter);
09824                } else {
09825                   ast_free(prio_iter);
09826                }
09827             }
09828             ast_hashtab_end_traversal(exten_iter);
09829          }
09830 
09831          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
09832          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
09833             another registrar. It's not empty if there are any extensions */
09834          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
09835             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09836             ast_hashtab_remove_this_object(contexttab, tmp);
09837 
09838             next = tmp->next;
09839             if (tmpl)
09840                tmpl->next = next;
09841             else
09842                contexts = next;
09843             /* Okay, now we're safe to let it go -- in a sense, we were
09844                ready to let it go as soon as we locked it. */
09845             ast_unlock_context(tmp);
09846             __ast_internal_context_destroy(tmp);
09847          } else {
09848             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
09849                     tmp->refcount, tmp->root);
09850             ast_unlock_context(tmp);
09851             next = tmp->next;
09852             tmpl = tmp;
09853          }
09854       } else if (con) {
09855          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
09856          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09857          ast_hashtab_remove_this_object(contexttab, tmp);
09858 
09859          next = tmp->next;
09860          if (tmpl)
09861             tmpl->next = next;
09862          else
09863             contexts = next;
09864          /* Okay, now we're safe to let it go -- in a sense, we were
09865             ready to let it go as soon as we locked it. */
09866          ast_unlock_context(tmp);
09867          __ast_internal_context_destroy(tmp);
09868       }
09869 
09870       /* if we have a specific match, we are done, otherwise continue */
09871       tmp = con ? NULL : next;
09872    }
09873 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

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

03947 {
03948    struct ast_custom_function *cur;
03949    char tmps[80];
03950 
03951    if (!acf) {
03952       return -1;
03953    }
03954 
03955    acf->mod = mod;
03956 #ifdef AST_XML_DOCS
03957    acf->docsrc = AST_STATIC_DOC;
03958 #endif
03959 
03960    if (acf_retrieve_docs(acf)) {
03961       return -1;
03962    }
03963 
03964    AST_RWLIST_WRLOCK(&acf_root);
03965 
03966    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03967       if (!strcmp(acf->name, cur->name)) {
03968          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03969          AST_RWLIST_UNLOCK(&acf_root);
03970          return -1;
03971       }
03972    }
03973 
03974    /* Store in alphabetical order */
03975    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03976       if (strcasecmp(acf->name, cur->name) < 0) {
03977          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03978          break;
03979       }
03980    }
03981    AST_RWLIST_TRAVERSE_SAFE_END;
03982 
03983    if (!cur) {
03984       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03985    }
03986 
03987    AST_RWLIST_UNLOCK(&acf_root);
03988 
03989    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03990 
03991    return 0;
03992 }

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

03995 {
03996    struct ast_custom_escalating_function *acf_escalation = NULL;
03997    int res;
03998 
03999    res = __ast_custom_function_register(acf, mod);
04000    if (res != 0) {
04001       return -1;
04002    }
04003 
04004    if (escalation == AST_CFE_NONE) {
04005       /* No escalations; no need to do anything else */
04006       return 0;
04007    }
04008 
04009    acf_escalation = ast_calloc(1, sizeof(*acf_escalation));
04010    if (!acf_escalation) {
04011       ast_custom_function_unregister(acf);
04012       return -1;
04013    }
04014 
04015    acf_escalation->acf = acf;
04016    switch (escalation) {
04017    case AST_CFE_NONE:
04018       break;
04019    case AST_CFE_READ:
04020       acf_escalation->read_escalates = 1;
04021       break;
04022    case AST_CFE_WRITE:
04023       acf_escalation->write_escalates = 1;
04024       break;
04025    case AST_CFE_BOTH:
04026       acf_escalation->read_escalates = 1;
04027       acf_escalation->write_escalates = 1;
04028       break;
04029    }
04030 
04031    AST_RWLIST_WRLOCK(&escalation_root);
04032    AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list);
04033    AST_RWLIST_UNLOCK(&escalation_root);
04034 
04035    return 0;
04036 }

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

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

11241 {
11242    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
11243 
11244    if (!chan)
11245       return -2;
11246 
11247    if (context == NULL)
11248       context = chan->context;
11249    if (exten == NULL)
11250       exten = chan->exten;
11251 
11252    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
11253    if (ast_exists_extension(chan, context, exten, priority,
11254       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
11255       return goto_func(chan, context, exten, priority);
11256    else {
11257       return AST_PBX_GOTO_FAILED;
11258    }
11259 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

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

09671 {
09672    struct ast_include *tmpi;
09673    struct ast_sw *sw;
09674    struct ast_exten *e, *el, *en;
09675    struct ast_ignorepat *ipi;
09676    struct ast_context *tmp = con;
09677 
09678    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
09679       struct ast_include *tmpil = tmpi;
09680       tmpi = tmpi->next;
09681       ast_free(tmpil);
09682    }
09683    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
09684       struct ast_ignorepat *ipl = ipi;
09685       ipi = ipi->next;
09686       ast_free(ipl);
09687    }
09688    if (tmp->registrar)
09689       ast_free(tmp->registrar);
09690 
09691    /* destroy the hash tabs */
09692    if (tmp->root_table) {
09693       ast_hashtab_destroy(tmp->root_table, 0);
09694    }
09695    /* and destroy the pattern tree */
09696    if (tmp->pattern_tree)
09697       destroy_pattern_tree(tmp->pattern_tree);
09698 
09699    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
09700       ast_free(sw);
09701    for (e = tmp->root; e;) {
09702       for (en = e->peer; en;) {
09703          el = en;
09704          en = en->peer;
09705          destroy_exten(el);
09706       }
09707       el = e;
09708       e = e->next;
09709       destroy_exten(el);
09710    }
09711    tmp->root = NULL;
09712    ast_rwlock_destroy(&tmp->lock);
09713    ast_mutex_destroy(&tmp->macrolock);
09714    ast_free(tmp);
09715 }

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

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

static void __init_extensionstate_buf ( void   )  [static]

Definition at line 865 of file pbx.c.

00879 : An extension

static void __init_switch_data ( void   )  [static]

Definition at line 864 of file pbx.c.

00879 : 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 870 of file pbx.c.

00879 : An extension

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

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

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

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

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

03627 {
03628    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03629    struct pbx_exception *exception = NULL;
03630    if (!ds || !ds->data)
03631       return -1;
03632    exception = ds->data;
03633    if (!strcasecmp(data, "REASON"))
03634       ast_copy_string(buf, exception->reason, buflen);
03635    else if (!strcasecmp(data, "CONTEXT"))
03636       ast_copy_string(buf, exception->context, buflen);
03637    else if (!strncasecmp(data, "EXTEN", 5))
03638       ast_copy_string(buf, exception->exten, buflen);
03639    else if (!strcasecmp(data, "PRIORITY"))
03640       snprintf(buf, buflen, "%d", exception->priority);
03641    else
03642       return -1;
03643    return 0;
03644 }

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

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

03902 {
03903 #ifdef AST_XML_DOCS
03904    char *tmpxml;
03905 
03906    /* Let's try to find it in the Documentation XML */
03907    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
03908       return 0;
03909    }
03910 
03911    if (ast_string_field_init(acf, 128)) {
03912       return -1;
03913    }
03914 
03915    /* load synopsis */
03916    tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
03917    ast_string_field_set(acf, synopsis, tmpxml);
03918    ast_free(tmpxml);
03919 
03920    /* load description */
03921    tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
03922    ast_string_field_set(acf, desc, tmpxml);
03923    ast_free(tmpxml);
03924 
03925    /* load syntax */
03926    tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
03927    ast_string_field_set(acf, syntax, tmpxml);
03928    ast_free(tmpxml);
03929 
03930    /* load arguments */
03931    tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
03932    ast_string_field_set(acf, arguments, tmpxml);
03933    ast_free(tmpxml);
03934 
03935    /* load seealso */
03936    tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
03937    ast_string_field_set(acf, seealso, tmpxml);
03938    ast_free(tmpxml);
03939 
03940    acf->docsrc = AST_XML_DOC;
03941 #endif
03942 
03943    return 0;
03944 }

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

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

02223 {
02224    struct match_char *m1 = NULL;
02225    struct match_char *m2 = NULL;
02226    struct match_char **m0;
02227    const char *pos;
02228    int already;
02229    int pattern = 0;
02230    int idx_cur;
02231    int idx_next;
02232    char extenbuf[512];
02233    struct pattern_node pat_node[2];
02234 
02235    if (e1->matchcid) {
02236       if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
02237          ast_log(LOG_ERROR,
02238             "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
02239             e1->exten, e1->cidmatch);
02240          return NULL;
02241       }
02242       sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe.  We just checked. */
02243    } else {
02244       ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
02245    }
02246 
02247 #ifdef NEED_DEBUG
02248    ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf);
02249 #endif
02250    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
02251    m0 = &con->pattern_tree;
02252    already = 1;
02253 
02254    pos = extenbuf;
02255    if (*pos == '_') {
02256       pattern = 1;
02257       ++pos;
02258    }
02259    idx_cur = 0;
02260    pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
02261    for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
02262       idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
02263       pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
02264 
02265       /* See about adding node to tree. */
02266       m2 = NULL;
02267       if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
02268          && m2->next_char) {
02269          if (!pat_node[idx_next].buf[0]) {
02270             /*
02271              * This is the end of the pattern, but not the end of the tree.
02272              * Mark this node with the exten... a shorter pattern might win
02273              * if the longer one doesn't match.
02274              */
02275             if (findonly) {
02276                return m2;
02277             }
02278             if (m2->exten) {
02279                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02280                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02281             }
02282             m2->exten = e1;
02283             m2->deleted = 0;
02284          }
02285          m1 = m2->next_char; /* m1 points to the node to compare against */
02286          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
02287       } else { /* not already OR not m2 OR nor m2->next_char */
02288          if (m2) {
02289             if (findonly) {
02290                return m2;
02291             }
02292             m1 = m2; /* while m0 stays the same */
02293          } else {
02294             if (findonly) {
02295                return m1;
02296             }
02297             m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
02298             if (!m1) { /* m1 is the node just added */
02299                return NULL;
02300             }
02301             m0 = &m1->next_char;
02302          }
02303          if (!pat_node[idx_next].buf[0]) {
02304             if (m2 && m2->exten) {
02305                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02306                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02307             }
02308             m1->deleted = 0;
02309             m1->exten = e1;
02310          }
02311 
02312          /* The 'already' variable is a mini-optimization designed to make it so that we
02313           * don't have to call already_in_tree when we know it will return false.
02314           */
02315          already = 0;
02316       }
02317    }
02318    return m1;
02319 }

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

02025 {
02026    struct match_char *m;
02027 
02028    if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
02029       return NULL;
02030    }
02031 
02032    /* strcpy is safe here since we know its size and have allocated
02033     * just enough space for when we allocated m
02034     */
02035    strcpy(m->x, pattern->buf);
02036 
02037    /* the specificity scores are the same as used in the old
02038       pattern matcher. */
02039    m->is_pattern = is_pattern;
02040    if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
02041       m->specificity = 0x0832;
02042    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
02043       m->specificity = 0x0931;
02044    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
02045       m->specificity = 0x0a30;
02046    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
02047       m->specificity = 0x18000;
02048    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
02049       m->specificity = 0x28000;
02050    } else {
02051       m->specificity = pattern->specif;
02052    }
02053 
02054    if (!con->pattern_tree) {
02055       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
02056    } else {
02057       if (already) { /* switch to the new regime (traversing vs appending)*/
02058          insert_in_next_chars_alt_char_list(nextcharptr, m);
02059       } else {
02060          insert_in_next_chars_alt_char_list(&current->next_char, m);
02061       }
02062    }
02063 
02064    return m;
02065 }

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

08858 {
08859    struct ast_exten *ep;
08860    struct ast_exten *eh=e;
08861    int repeated_label = 0; /* Track if this label is a repeat, assume no. */
08862 
08863    for (ep = NULL; e ; ep = e, e = e->peer) {
08864       if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
08865          if (strcmp(e->exten, tmp->exten)) {
08866             ast_log(LOG_WARNING,
08867                "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
08868                tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority);
08869          } else {
08870             ast_log(LOG_WARNING,
08871                "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
08872                tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
08873          }
08874          repeated_label = 1;
08875       }
08876       if (e->priority >= tmp->priority) {
08877          break;
08878       }
08879    }
08880 
08881    if (repeated_label) {   /* Discard the label since it's a repeat. */
08882       tmp->label = NULL;
08883    }
08884 
08885    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
08886       ast_hashtab_insert_safe(eh->peer_table, tmp);
08887 
08888       if (tmp->label) {
08889          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08890       }
08891       ep->peer = tmp;
08892       return 0;   /* success */
08893    }
08894    if (e->priority == tmp->priority) {
08895       /* Can't have something exactly the same.  Is this a
08896          replacement?  If so, replace, otherwise, bonk. */
08897       if (!replace) {
08898          if (strcmp(e->exten, tmp->exten)) {
08899             ast_log(LOG_WARNING,
08900                "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
08901                tmp->exten, tmp->priority, con->name, e->exten);
08902          } else {
08903             ast_log(LOG_WARNING,
08904                "Unable to register extension '%s' priority %d in '%s', already in use\n",
08905                tmp->exten, tmp->priority, con->name);
08906          }
08907          if (tmp->datad) {
08908             tmp->datad(tmp->data);
08909             /* if you free this, null it out */
08910             tmp->data = NULL;
08911          }
08912 
08913          ast_free(tmp);
08914          return -1;
08915       }
08916       /* we are replacing e, so copy the link fields and then update
08917        * whoever pointed to e to point to us
08918        */
08919       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
08920       tmp->peer = e->peer; /* always meaningful */
08921       if (ep)  {     /* We're in the peer list, just insert ourselves */
08922          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
08923 
08924          if (e->label) {
08925             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
08926          }
08927 
08928          ast_hashtab_insert_safe(eh->peer_table,tmp);
08929          if (tmp->label) {
08930             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
08931          }
08932 
08933          ep->peer = tmp;
08934       } else if (el) {     /* We're the first extension. Take over e's functions */
08935          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08936          tmp->peer_table = e->peer_table;
08937          tmp->peer_label_table = e->peer_label_table;
08938          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
08939          ast_hashtab_insert_safe(tmp->peer_table,tmp);
08940          if (e->label) {
08941             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08942          }
08943          if (tmp->label) {
08944             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08945          }
08946 
08947          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08948          ast_hashtab_insert_safe(con->root_table, tmp);
08949          el->next = tmp;
08950          /* The pattern trie points to this exten; replace the pointer,
08951             and all will be well */
08952          if (x) { /* if the trie isn't formed yet, don't sweat this */
08953             if (x->exten) { /* this test for safety purposes */
08954                x->exten = tmp; /* replace what would become a bad pointer */
08955             } else {
08956                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08957             }
08958          }
08959       } else {       /* We're the very first extension.  */
08960          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08961          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08962          ast_hashtab_insert_safe(con->root_table, tmp);
08963          tmp->peer_table = e->peer_table;
08964          tmp->peer_label_table = e->peer_label_table;
08965          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
08966          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08967          if (e->label) {
08968             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08969          }
08970          if (tmp->label) {
08971             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08972          }
08973 
08974          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08975          ast_hashtab_insert_safe(con->root_table, tmp);
08976          con->root = tmp;
08977          /* The pattern trie points to this exten; replace the pointer,
08978             and all will be well */
08979          if (x) { /* if the trie isn't formed yet; no problem */
08980             if (x->exten) { /* this test for safety purposes */
08981                x->exten = tmp; /* replace what would become a bad pointer */
08982             } else {
08983                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08984             }
08985          }
08986       }
08987       if (tmp->priority == PRIORITY_HINT)
08988          ast_change_hint(e,tmp);
08989       /* Destroy the old one */
08990       if (e->datad)
08991          e->datad(e->data);
08992       ast_free(e);
08993    } else { /* Slip ourselves in just before e */
08994       tmp->peer = e;
08995       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
08996       if (ep) {         /* Easy enough, we're just in the peer list */
08997          if (tmp->label) {
08998             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08999          }
09000          ast_hashtab_insert_safe(eh->peer_table, tmp);
09001          ep->peer = tmp;
09002       } else {       /* we are the first in some peer list, so link in the ext list */
09003          tmp->peer_table = e->peer_table;
09004          tmp->peer_label_table = e->peer_label_table;
09005          e->peer_table = 0;
09006          e->peer_label_table = 0;
09007          ast_hashtab_insert_safe(tmp->peer_table, tmp);
09008          if (tmp->label) {
09009             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
09010          }
09011          ast_hashtab_remove_object_via_lookup(con->root_table, e);
09012          ast_hashtab_insert_safe(con->root_table, tmp);
09013          if (el)
09014             el->next = tmp;   /* in the middle... */
09015          else
09016             con->root = tmp; /* ... or at the head */
09017          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
09018       }
09019       /* And immediately return success. */
09020       if (tmp->priority == PRIORITY_HINT) {
09021          ast_add_hint(tmp);
09022       }
09023    }
09024    return 0;
09025 }

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

Definition at line 1962 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

01963 {
01964    struct match_char *t;
01965 
01966    if (!current) {
01967       return 0;
01968    }
01969 
01970    for (t = current; t; t = t->alt_char) {
01971       if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
01972          return t;
01973       }
01974    }
01975 
01976    return 0;
01977 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5931 of file pbx.c.

References countcalls.

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

05932 {
05933    return countcalls;
05934 }

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

08694 {
08695    int ret = -1;
08696    struct ast_context *c;
08697 
08698    c = find_context_locked(context);
08699    if (c) {
08700       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08701          application, data, datad, registrar);
08702       ast_unlock_contexts();
08703    }
08704 
08705    return ret;
08706 }

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

09056 {
09057    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
09058       application, data, datad, registrar, 1);
09059 }

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

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

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

08674 {
08675    int ret = -1;
08676    struct ast_context *c;
08677 
08678    c = find_context(context);
08679    if (c) {
08680       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
08681          application, data, datad, registrar, 1);
08682    }
08683 
08684    return ret;
08685 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

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

05271 {
05272    struct ast_hint *hint_new;
05273    struct ast_hint *hint_found;
05274 
05275    if (!e) {
05276       return -1;
05277    }
05278 
05279    /*
05280     * We must create the hint we wish to add before determining if
05281     * it is already in the hints container to avoid possible
05282     * deadlock when getting the current extension state.
05283     */
05284    hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
05285    if (!hint_new) {
05286       return -1;
05287    }
05288 
05289    /* Initialize new hint. */
05290    hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
05291    if (!hint_new->callbacks) {
05292       ao2_ref(hint_new, -1);
05293       return -1;
05294    }
05295    hint_new->exten = e;
05296    if (strstr(e->app, "${") && e->exten[0] == '_') {
05297       hint_new->laststate = AST_DEVICE_INVALID;
05298    } else {
05299       hint_new->laststate = ast_extension_state2(e);
05300    }
05301 
05302    /* Prevent multiple add hints from adding the same hint at the same time. */
05303    ao2_lock(hints);
05304 
05305    /* Search if hint exists, do nothing */
05306    hint_found = ao2_find(hints, e, 0);
05307    if (hint_found) {
05308       ao2_ref(hint_found, -1);
05309       ao2_unlock(hints);
05310       ao2_ref(hint_new, -1);
05311       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
05312          ast_get_extension_name(e), ast_get_extension_app(e));
05313       return -1;
05314    }
05315 
05316    /* Add new hint to the hints container */
05317    ast_debug(2, "HINTS: Adding hint %s: %s\n",
05318       ast_get_extension_name(e), ast_get_extension_app(e));
05319    ao2_link(hints, hint_new);
05320 
05321    ao2_unlock(hints);
05322    ao2_ref(hint_new, -1);
05323 
05324    return 0;
05325 }

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

08732 {
08733    int res = 0;
08734    struct ast_channel *tmpchan;
08735    struct {
08736       char *accountcode;
08737       char *exten;
08738       char *context;
08739       char *linkedid;
08740       char *name;
08741       struct ast_cdr *cdr;
08742       int amaflags;
08743       int state;
08744       format_t readformat;
08745       format_t writeformat;
08746    } tmpvars = { 0, };
08747 
08748    ast_channel_lock(chan);
08749    if (chan->pbx) { /* This channel is currently in the PBX */
08750       ast_explicit_goto(chan, context, exten, priority + 1);
08751       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08752       ast_channel_unlock(chan);
08753       return res;
08754    }
08755 
08756    /* In order to do it when the channel doesn't really exist within
08757     * the PBX, we have to make a new channel, masquerade, and start the PBX
08758     * at the new location */
08759    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08760    tmpvars.exten = ast_strdupa(chan->exten);
08761    tmpvars.context = ast_strdupa(chan->context);
08762    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08763    tmpvars.name = ast_strdupa(chan->name);
08764    tmpvars.amaflags = chan->amaflags;
08765    tmpvars.state = chan->_state;
08766    tmpvars.writeformat = chan->writeformat;
08767    tmpvars.readformat = chan->readformat;
08768    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08769 
08770    ast_channel_unlock(chan);
08771 
08772    /* Do not hold any channel locks while calling channel_alloc() since the function
08773     * locks the channel container when linking the new channel in. */
08774    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08775       ast_cdr_discard(tmpvars.cdr);
08776       return -1;
08777    }
08778 
08779    /* copy the cdr info over */
08780    if (tmpvars.cdr) {
08781       ast_cdr_discard(tmpchan->cdr);
08782       tmpchan->cdr = tmpvars.cdr;
08783       tmpvars.cdr = NULL;
08784    }
08785 
08786    /* Make formats okay */
08787    tmpchan->readformat = tmpvars.readformat;
08788    tmpchan->writeformat = tmpvars.writeformat;
08789 
08790    /* Setup proper location. Never hold another channel lock while calling this function. */
08791    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08792 
08793    /* Masquerade into tmp channel */
08794    if (ast_channel_masquerade(tmpchan, chan)) {
08795       /* Failed to set up the masquerade.  It's probably chan_local
08796        * in the middle of optimizing itself out.  Sad. :( */
08797       ast_hangup(tmpchan);
08798       tmpchan = NULL;
08799       res = -1;
08800    } else {
08801       ast_do_masquerade(tmpchan);
08802       /* Start the PBX going on our stolen channel */
08803       if (ast_pbx_start(tmpchan)) {
08804          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08805          ast_hangup(tmpchan);
08806          res = -1;
08807       }
08808    }
08809 
08810    return res;
08811 }

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

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

08814 {
08815    struct ast_channel *chan;
08816    int res = -1;
08817 
08818    if ((chan = ast_channel_get_by_name(channame))) {
08819       res = ast_async_goto(chan, context, exten, priority);
08820       chan = ast_channel_unref(chan);
08821    }
08822 
08823    return res;
08824 }

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

References __ast_goto_if_exists().

11267 {
11268    return __ast_goto_if_exists(chan, context, exten, priority, 1);
11269 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

11332 {
11333    return pbx_parseable_goto(chan, goto_string, 1);
11334 }

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

08315 {
08316    char *info;
08317    int j, num_fields, last_sep = -1;
08318 
08319    i->timezone = NULL;
08320 
08321    /* Check for empty just in case */
08322    if (ast_strlen_zero(info_in)) {
08323       return 0;
08324    }
08325 
08326    /* make a copy just in case we were passed a static string */
08327    info = ast_strdupa(info_in);
08328 
08329    /* count the number of fields in the timespec */
08330    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
08331       if (info[j] == ',') {
08332          last_sep = j;
08333          num_fields++;
08334       }
08335    }
08336 
08337    /* save the timezone, if it is specified */
08338    if (num_fields == 5) {
08339       i->timezone = ast_strdup(info + last_sep + 1);
08340    }
08341 
08342    /* Assume everything except time */
08343    i->monthmask = 0xfff;   /* 12 bits */
08344    i->daymask = 0x7fffffffU; /* 31 bits */
08345    i->dowmask = 0x7f; /* 7 bits */
08346    /* on each call, use strsep() to move info to the next argument */
08347    get_timerange(i, strsep(&info, "|,"));
08348    if (info)
08349       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
08350    if (info)
08351       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
08352    if (info)
08353       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
08354    return 1;
08355 }

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

05416 {
05417    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05418 }

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

Change hint for an extension.

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

05329 {
05330    struct ast_hint *hint;
05331 
05332    if (!oe || !ne) {
05333       return -1;
05334    }
05335 
05336    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
05337 
05338    /*
05339     * Unlink the hint from the hints container as the extension
05340     * name (which is the hash value) could change.
05341     */
05342    hint = ao2_find(hints, oe, OBJ_UNLINK);
05343    if (!hint) {
05344       ao2_unlock(hints);
05345       return -1;
05346    }
05347 
05348    /* Update the hint and put it back in the hints container. */
05349    ao2_lock(hint);
05350    hint->exten = ne;
05351    ao2_unlock(hint);
05352    ao2_link(hints, hint);
05353 
05354    ao2_unlock(hints);
05355    ao2_ref(hint, -1);
05356 
05357    return 0;
05358 }

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

References ast_check_timing2(), and ast_tvnow().

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

08358 {
08359    return ast_check_timing2(i, ast_tvnow());
08360 }

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

08363 {
08364    struct ast_tm tm;
08365 
08366    ast_localtime(&tv, &tm, i->timezone);
08367 
08368    /* If it's not the right month, return */
08369    if (!(i->monthmask & (1 << tm.tm_mon)))
08370       return 0;
08371 
08372    /* If it's not that time of the month.... */
08373    /* Warning, tm_mday has range 1..31! */
08374    if (!(i->daymask & (1 << (tm.tm_mday-1))))
08375       return 0;
08376 
08377    /* If it's not the right day of the week */
08378    if (!(i->dowmask & (1 << tm.tm_wday)))
08379       return 0;
08380 
08381    /* Sanity check the hour just to be safe */
08382    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
08383       ast_log(LOG_WARNING, "Insane time...\n");
08384       return 0;
08385    }
08386 
08387    /* Now the tough part, we calculate if it fits
08388       in the right time based on min/hour */
08389    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))))
08390       return 0;
08391 
08392    /* If we got this far, then we're good */
08393    return 1;
08394 }

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

11337 {
11338    struct ast_app *app = NULL;
11339    int which = 0;
11340    char *ret = NULL;
11341    size_t wordlen = strlen(word);
11342 
11343    AST_RWLIST_RDLOCK(&apps);
11344    AST_RWLIST_TRAVERSE(&apps, app, list) {
11345       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
11346          ret = ast_strdup(app->name);
11347          break;
11348       }
11349    }
11350    AST_RWLIST_UNLOCK(&apps);
11351 
11352    return ret;
11353 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08599 {
08600    int ret = -1;
08601    struct ast_context *c;
08602 
08603    c = find_context_locked(context);
08604    if (c) {
08605       ret = ast_context_add_ignorepat2(c, value, registrar);
08606       ast_unlock_contexts();
08607    }
08608    return ret;
08609 }

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

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

08612 {
08613    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08614    int length;
08615    char *pattern;
08616    length = sizeof(struct ast_ignorepat);
08617    length += strlen(value) + 1;
08618    if (!(ignorepat = ast_calloc(1, length)))
08619       return -1;
08620    /* The cast to char * is because we need to write the initial value.
08621     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08622     * sees the cast as dereferencing a type-punned pointer and warns about
08623     * it.  This is the workaround (we're telling gcc, yes, that's really
08624     * what we wanted to do).
08625     */
08626    pattern = (char *) ignorepat->pattern;
08627    strcpy(pattern, value);
08628    ignorepat->next = NULL;
08629    ignorepat->registrar = registrar;
08630    ast_wrlock_context(con);
08631    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08632       ignorepatl = ignorepatc;
08633       if (!strcasecmp(ignorepatc->pattern, value)) {
08634          /* Already there */
08635          ast_unlock_context(con);
08636          ast_free(ignorepat);
08637          errno = EEXIST;
08638          return -1;
08639       }
08640    }
08641    if (ignorepatl)
08642       ignorepatl->next = ignorepat;
08643    else
08644       con->ignorepats = ignorepat;
08645    ast_unlock_context(con);
08646    return 0;
08647 
08648 }

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

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

Referenced by handle_cli_dialplan_add_include().

08143 {
08144    int ret = -1;
08145    struct ast_context *c;
08146 
08147    c = find_context_locked(context);
08148    if (c) {
08149       ret = ast_context_add_include2(c, include, registrar);
08150       ast_unlock_contexts();
08151    }
08152    return ret;
08153 }

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

08413 {
08414    struct ast_include *new_include;
08415    char *c;
08416    struct ast_include *i, *il = NULL; /* include, include_last */
08417    int length;
08418    char *p;
08419 
08420    length = sizeof(struct ast_include);
08421    length += 2 * (strlen(value) + 1);
08422 
08423    /* allocate new include structure ... */
08424    if (!(new_include = ast_calloc(1, length)))
08425       return -1;
08426    /* Fill in this structure. Use 'p' for assignments, as the fields
08427     * in the structure are 'const char *'
08428     */
08429    p = new_include->stuff;
08430    new_include->name = p;
08431    strcpy(p, value);
08432    p += strlen(value) + 1;
08433    new_include->rname = p;
08434    strcpy(p, value);
08435    /* Strip off timing info, and process if it is there */
08436    if ( (c = strchr(p, ',')) ) {
08437       *c++ = '\0';
08438       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08439    }
08440    new_include->next      = NULL;
08441    new_include->registrar = registrar;
08442 
08443    ast_wrlock_context(con);
08444 
08445    /* ... go to last include and check if context is already included too... */
08446    for (i = con->includes; i; i = i->next) {
08447       if (!strcasecmp(i->name, new_include->name)) {
08448          ast_destroy_timing(&(new_include->timing));
08449          ast_free(new_include);
08450          ast_unlock_context(con);
08451          errno = EEXIST;
08452          return -1;
08453       }
08454       il = i;
08455    }
08456 
08457    /* ... include new context into context list, unlock, return */
08458    if (il)
08459       il->next = new_include;
08460    else
08461       con->includes = new_include;
08462    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08463 
08464    ast_unlock_context(con);
08465 
08466    return 0;
08467 }

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

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

08475 {
08476    int ret = -1;
08477    struct ast_context *c;
08478 
08479    c = find_context_locked(context);
08480    if (c) { /* found, add switch to this context */
08481       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08482       ast_unlock_contexts();
08483    }
08484    return ret;
08485 }

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

08496 {
08497    struct ast_sw *new_sw;
08498    struct ast_sw *i;
08499    int length;
08500    char *p;
08501 
08502    length = sizeof(struct ast_sw);
08503    length += strlen(value) + 1;
08504    if (data)
08505       length += strlen(data);
08506    length++;
08507 
08508    /* allocate new sw structure ... */
08509    if (!(new_sw = ast_calloc(1, length)))
08510       return -1;
08511    /* ... fill in this structure ... */
08512    p = new_sw->stuff;
08513    new_sw->name = p;
08514    strcpy(new_sw->name, value);
08515    p += strlen(value) + 1;
08516    new_sw->data = p;
08517    if (data) {
08518       strcpy(new_sw->data, data);
08519       p += strlen(data) + 1;
08520    } else {
08521       strcpy(new_sw->data, "");
08522       p++;
08523    }
08524    new_sw->eval     = eval;
08525    new_sw->registrar = registrar;
08526 
08527    /* ... try to lock this context ... */
08528    ast_wrlock_context(con);
08529 
08530    /* ... go to last sw and check if context is already swd too... */
08531    AST_LIST_TRAVERSE(&con->alts, i, list) {
08532       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08533          ast_free(new_sw);
08534          ast_unlock_context(con);
08535          errno = EEXIST;
08536          return -1;
08537       }
08538    }
08539 
08540    /* ... sw new context into context list, unlock, return */
08541    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08542 
08543    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08544 
08545    ast_unlock_context(con);
08546 
08547    return 0;
08548 }

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 9875 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 2971 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().

02972 {
02973    struct ast_context *tmp;
02974    struct fake_context item;
02975 
02976    if (!name) {
02977       return NULL;
02978    }
02979    ast_rdlock_contexts();
02980    if (contexts_table) {
02981       ast_copy_string(item.name, name, sizeof(item.name));
02982       tmp = ast_hashtab_lookup(contexts_table, &item);
02983    } else {
02984       tmp = NULL;
02985       while ((tmp = ast_walk_contexts(tmp))) {
02986          if (!strcasecmp(name, tmp->name)) {
02987             break;
02988          }
02989       }
02990    }
02991    ast_unlock_contexts();
02992    return tmp;
02993 }

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

07727 {
07728    struct ast_context *tmp, **local_contexts;
07729    struct fake_context search;
07730    int length = sizeof(struct ast_context) + strlen(name) + 1;
07731 
07732    if (!contexts_table) {
07733       /* Protect creation of contexts_table from reentrancy. */
07734       ast_wrlock_contexts();
07735       if (!contexts_table) {
07736          contexts_table = ast_hashtab_create(17,
07737             ast_hashtab_compare_contexts,
07738             ast_hashtab_resize_java,
07739             ast_hashtab_newsize_java,
07740             ast_hashtab_hash_contexts,
07741             0);
07742       }
07743       ast_unlock_contexts();
07744    }
07745 
07746    ast_copy_string(search.name, name, sizeof(search.name));
07747    if (!extcontexts) {
07748       ast_rdlock_contexts();
07749       local_contexts = &contexts;
07750       tmp = ast_hashtab_lookup(contexts_table, &search);
07751       ast_unlock_contexts();
07752       if (tmp) {
07753          tmp->refcount++;
07754          return tmp;
07755       }
07756    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07757       local_contexts = extcontexts;
07758       tmp = ast_hashtab_lookup(exttable, &search);
07759       if (tmp) {
07760          tmp->refcount++;
07761          return tmp;
07762       }
07763    }
07764 
07765    if ((tmp = ast_calloc(1, length))) {
07766       ast_rwlock_init(&tmp->lock);
07767       ast_mutex_init(&tmp->macrolock);
07768       strcpy(tmp->name, name);
07769       tmp->root = NULL;
07770       tmp->root_table = NULL;
07771       tmp->registrar = ast_strdup(registrar);
07772       tmp->includes = NULL;
07773       tmp->ignorepats = NULL;
07774       tmp->refcount = 1;
07775    } else {
07776       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07777       return NULL;
07778    }
07779 
07780    if (!extcontexts) {
07781       ast_wrlock_contexts();
07782       tmp->next = *local_contexts;
07783       *local_contexts = tmp;
07784       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07785       ast_unlock_contexts();
07786       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07787       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07788    } else {
07789       tmp->next = *local_contexts;
07790       if (exttable)
07791          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07792 
07793       *local_contexts = tmp;
07794       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07795       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07796    }
07797    return tmp;
07798 }

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

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

Referenced by _macro_exec().

06307 {
06308    struct ast_context *c;
06309    int ret = -1;
06310 
06311    c = find_context_locked(context);
06312    if (c) {
06313       ast_unlock_contexts();
06314 
06315       /* if we found context, lock macrolock */
06316       ret = ast_mutex_lock(&c->macrolock);
06317    }
06318 
06319    return ret;
06320 }

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

06115 {
06116    return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
06117 }

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

06145 {
06146    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
06147 }

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

06120 {
06121    int ret = -1; /* default error return */
06122    struct ast_context *c;
06123 
06124    c = find_context_locked(context);
06125    if (c) { /* ... remove extension ... */
06126       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
06127          matchcallerid, registrar, 0);
06128       ast_unlock_contexts();
06129    }
06130 
06131    return ret;
06132 }

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

06150 {
06151    struct ast_exten *exten, *prev_exten = NULL;
06152    struct ast_exten *peer;
06153    struct ast_exten ex, *exten2, *exten3;
06154    char dummy_name[1024];
06155    struct ast_exten *previous_peer = NULL;
06156    struct ast_exten *next_peer = NULL;
06157    int found = 0;
06158 
06159    if (!already_locked)
06160       ast_wrlock_context(con);
06161 
06162 #ifdef NEED_DEBUG
06163    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
06164 #endif
06165 #ifdef CONTEXT_DEBUG
06166    check_contexts(__FILE__, __LINE__);
06167 #endif
06168    /* find this particular extension */
06169    ex.exten = dummy_name;
06170    ex.matchcid = matchcallerid;
06171    ex.cidmatch = callerid;
06172    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
06173    exten = ast_hashtab_lookup(con->root_table, &ex);
06174    if (exten) {
06175       if (priority == 0) {
06176          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
06177          if (!exten2)
06178             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);
06179          if (con->pattern_tree) {
06180             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
06181 
06182             if (x->exten) { /* this test for safety purposes */
06183                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
06184                x->exten = 0; /* get rid of what will become a bad pointer */
06185             } else {
06186                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
06187             }
06188          }
06189       } else {
06190          ex.priority = priority;
06191          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
06192          if (exten2) {
06193             if (exten2->label) { /* if this exten has a label, remove that, too */
06194                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
06195                if (!exten3)
06196                   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);
06197             }
06198 
06199             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
06200             if (!exten3)
06201                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);
06202             if (exten2 == exten && exten2->peer) {
06203                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
06204                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
06205             }
06206             if (ast_hashtab_size(exten->peer_table) == 0) {
06207                /* well, if the last priority of an exten is to be removed,
06208                   then, the extension is removed, too! */
06209                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
06210                if (!exten3)
06211                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
06212                if (con->pattern_tree) {
06213                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
06214                   if (x->exten) { /* this test for safety purposes */
06215                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
06216                      x->exten = 0; /* get rid of what will become a bad pointer */
06217                   }
06218                }
06219             }
06220          } else {
06221             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
06222                   priority, exten->exten, con->name);
06223          }
06224       }
06225    } else {
06226       /* hmmm? this exten is not in this pattern tree? */
06227       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
06228             extension, con->name);
06229    }
06230 #ifdef NEED_DEBUG
06231    if (con->pattern_tree) {
06232       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
06233       log_match_char_tree(con->pattern_tree, " ");
06234    }
06235 #endif
06236 
06237    /* scan the extension list to find first matching extension-registrar */
06238    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
06239       if (!strcmp(exten->exten, extension) &&
06240          (!registrar || !strcmp(exten->registrar, registrar)) &&
06241          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
06242          break;
06243    }
06244    if (!exten) {
06245       /* we can't find right extension */
06246       if (!already_locked)
06247          ast_unlock_context(con);
06248       return -1;
06249    }
06250 
06251    /* scan the priority list to remove extension with exten->priority == priority */
06252    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
06253        peer && !strcmp(peer->exten, extension) &&
06254          (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ;
06255          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
06256 
06257       if ((priority == 0 || peer->priority == priority) &&
06258             (!registrar || !strcmp(peer->registrar, registrar) )) {
06259          found = 1;
06260 
06261          /* we are first priority extension? */
06262          if (!previous_peer) {
06263             /*
06264              * We are first in the priority chain, so must update the extension chain.
06265              * The next node is either the next priority or the next extension
06266              */
06267             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
06268             if (peer->peer) {
06269                /* move the peer_table and peer_label_table down to the next peer, if
06270                   it is there */
06271                peer->peer->peer_table = peer->peer_table;
06272                peer->peer->peer_label_table = peer->peer_label_table;
06273                peer->peer_table = NULL;
06274                peer->peer_label_table = NULL;
06275             }
06276             if (!prev_exten) {   /* change the root... */
06277                con->root = next_node;
06278             } else {
06279                prev_exten->next = next_node; /* unlink */
06280             }
06281             if (peer->peer)   { /* update the new head of the pri list */
06282                peer->peer->next = peer->next;
06283             }
06284          } else { /* easy, we are not first priority in extension */
06285             previous_peer->peer = peer->peer;
06286          }
06287 
06288 
06289          /* now, free whole priority extension */
06290          destroy_exten(peer);
06291       } else {
06292          previous_peer = peer;
06293       }
06294    }
06295    if (!already_locked)
06296       ast_unlock_context(con);
06297    return found ? 0 : -1;
06298 }

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

Definition at line 8554 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

08555 {
08556    int ret = -1;
08557    struct ast_context *c;
08558 
08559    c = find_context_locked(context);
08560    if (c) {
08561       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08562       ast_unlock_contexts();
08563    }
08564    return ret;
08565 }

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

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

08568 {
08569    struct ast_ignorepat *ip, *ipl = NULL;
08570 
08571    ast_wrlock_context(con);
08572 
08573    for (ip = con->ignorepats; ip; ip = ip->next) {
08574       if (!strcmp(ip->pattern, ignorepat) &&
08575          (!registrar || (registrar == ip->registrar))) {
08576          if (ipl) {
08577             ipl->next = ip->next;
08578             ast_free(ip);
08579          } else {
08580             con->ignorepats = ip->next;
08581             ast_free(ip);
08582          }
08583          ast_unlock_context(con);
08584          return 0;
08585       }
08586       ipl = ip;
08587    }
08588 
08589    ast_unlock_context(con);
08590    errno = EINVAL;
08591    return -1;
08592 }

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

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

Referenced by handle_cli_dialplan_remove_include().

06008 {
06009    int ret = -1;
06010    struct ast_context *c;
06011 
06012    c = find_context_locked(context);
06013    if (c) {
06014       /* found, remove include from this context ... */
06015       ret = ast_context_remove_include2(c, include, registrar);
06016       ast_unlock_contexts();
06017    }
06018    return ret;
06019 }

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

06031 {
06032    struct ast_include *i, *pi = NULL;
06033    int ret = -1;
06034 
06035    ast_wrlock_context(con);
06036 
06037    /* find our include */
06038    for (i = con->includes; i; pi = i, i = i->next) {
06039       if (!strcmp(i->name, include) &&
06040             (!registrar || !strcmp(i->registrar, registrar))) {
06041          /* remove from list */
06042          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
06043          if (pi)
06044             pi->next = i->next;
06045          else
06046             con->includes = i->next;
06047          /* free include and return */
06048          ast_destroy_timing(&(i->timing));
06049          ast_free(i);
06050          ret = 0;
06051          break;
06052       }
06053    }
06054 
06055    ast_unlock_context(con);
06056 
06057    return ret;
06058 }

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

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

06066 {
06067    int ret = -1; /* default error return */
06068    struct ast_context *c;
06069 
06070    c = find_context_locked(context);
06071    if (c) {
06072       /* remove switch from this context ... */
06073       ret = ast_context_remove_switch2(c, sw, data, registrar);
06074       ast_unlock_contexts();
06075    }
06076    return ret;
06077 }

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

06088 {
06089    struct ast_sw *i;
06090    int ret = -1;
06091 
06092    ast_wrlock_context(con);
06093 
06094    /* walk switches */
06095    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
06096       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
06097          (!registrar || !strcmp(i->registrar, registrar))) {
06098          /* found, remove from list */
06099          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
06100          AST_LIST_REMOVE_CURRENT(list);
06101          ast_free(i); /* free switch and return */
06102          ret = 0;
06103          break;
06104       }
06105    }
06106    AST_LIST_TRAVERSE_SAFE_END;
06107 
06108    ast_unlock_context(con);
06109 
06110    return ret;
06111 }

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

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

Referenced by _macro_exec().

06328 {
06329    struct ast_context *c;
06330    int ret = -1;
06331 
06332    c = find_context_locked(context);
06333    if (c) {
06334       ast_unlock_contexts();
06335 
06336       /* if we found context, unlock macrolock */
06337       ret = ast_mutex_unlock(&c->macrolock);
06338    }
06339 
06340    return ret;
06341 }

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

11222 {
11223    struct ast_include *inc = NULL;
11224    int res = 0;
11225 
11226    while ( (inc = ast_walk_context_includes(con, inc)) ) {
11227       if (ast_context_find(inc->rname))
11228          continue;
11229 
11230       res = -1;
11231       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
11232          ast_get_context_name(con), inc->rname);
11233       break;
11234    }
11235 
11236    return res;
11237 }

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

03815 {
03816    struct ast_custom_function *cur;
03817    struct ast_custom_escalating_function *cur_escalation;
03818 
03819    if (!acf) {
03820       return -1;
03821    }
03822 
03823    AST_RWLIST_WRLOCK(&acf_root);
03824    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03825 #ifdef AST_XML_DOCS
03826       if (cur->docsrc == AST_XML_DOC) {
03827          ast_string_field_free_memory(acf);
03828       }
03829 #endif
03830       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03831    }
03832    AST_RWLIST_UNLOCK(&acf_root);
03833 
03834    /* Remove from the escalation list */
03835    AST_RWLIST_WRLOCK(&escalation_root);
03836    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) {
03837       if (cur_escalation->acf == acf) {
03838          AST_RWLIST_REMOVE_CURRENT(list);
03839          ast_free(cur_escalation);
03840          break;
03841       }
03842    }
03843    AST_RWLIST_TRAVERSE_SAFE_END;
03844    AST_RWLIST_UNLOCK(&escalation_root);
03845 
03846    return cur ? 0 : -1;
03847 }

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

08397 {
08398    if (i->timezone) {
08399       ast_free(i->timezone);
08400       i->timezone = NULL;
08401    }
08402    return 0;
08403 }

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

04845 {
04846    switch (devstate) {
04847    case AST_DEVICE_ONHOLD:
04848       return AST_EXTENSION_ONHOLD;
04849    case AST_DEVICE_BUSY:
04850       return AST_EXTENSION_BUSY;
04851    case AST_DEVICE_UNKNOWN:
04852       return AST_EXTENSION_NOT_INUSE;
04853    case AST_DEVICE_UNAVAILABLE:
04854    case AST_DEVICE_INVALID:
04855       return AST_EXTENSION_UNAVAILABLE;
04856    case AST_DEVICE_RINGINUSE:
04857       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04858    case AST_DEVICE_RINGING:
04859       return AST_EXTENSION_RINGING;
04860    case AST_DEVICE_INUSE:
04861       return AST_EXTENSION_INUSE;
04862    case AST_DEVICE_NOT_INUSE:
04863       return AST_EXTENSION_NOT_INUSE;
04864    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04865       break;
04866    }
04867 
04868    return AST_EXTENSION_NOT_INUSE;
04869 }

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

05401 {
05402    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05403 }

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

08709 {
08710    if (!chan)
08711       return -1;
08712 
08713    ast_channel_lock(chan);
08714 
08715    if (!ast_strlen_zero(context))
08716       ast_copy_string(chan->context, context, sizeof(chan->context));
08717    if (!ast_strlen_zero(exten))
08718       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08719    if (priority > -1) {
08720       chan->priority = priority;
08721       /* see flag description in channel.h for explanation */
08722       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08723          chan->priority--;
08724    }
08725 
08726    ast_channel_unlock(chan);
08727 
08728    return 0;
08729 }

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

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

02949 {
02950    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02951       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02952    return extension_match_core(pattern, data, needmore);
02953 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02714 {
02715    int cmp;
02716 
02717    cmp = ext_cmp(a, b);
02718    if (cmp < 0) {
02719       return -1;
02720    }
02721    if (cmp > 0) {
02722       return 1;
02723    }
02724    return 0;
02725 }

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

02944 {
02945    return extension_match_core(pattern, data, E_MATCH);
02946 }

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

04915 {
04916    struct ast_exten *e;
04917 
04918    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04919       return -1;                   /* No hint, return -1 */
04920    }
04921 
04922    if (e->exten[0] == '_') {
04923       /* Create this hint on-the-fly */
04924       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04925          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04926          e->registrar);
04927       if (!(e = ast_hint_extension(c, context, exten))) {
04928          /* Improbable, but not impossible */
04929          return -1;
04930       }
04931    }
04932 
04933    return ast_extension_state2(e);  /* Check all devices in the hint */
04934 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

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

04890 {
04891    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
04892 
04893    if (!e || !hint_app) {
04894       return -1;
04895    }
04896 
04897    ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
04898    return ast_extension_state3(hint_app);
04899 }

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

04903 {
04904    int i;
04905 
04906    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04907       if (extension_states[i].extension_state == extension_state)
04908          return extension_states[i].text;
04909    }
04910    return "Unknown";
04911 }

static int ast_extension_state3 ( struct ast_str hint_app  )  [static]

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

04872 {
04873    char *cur;
04874    char *rest;
04875    struct ast_devstate_aggregate agg;
04876 
04877    /* One or more devices separated with a & character */
04878    rest = ast_str_buffer(hint_app);
04879 
04880    ast_devstate_aggregate_init(&agg);
04881    while ((cur = strsep(&rest, "&"))) {
04882       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
04883    }
04884 
04885    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
04886 }

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

References ast_extension_state_add_destroy().

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

05137 {
05138    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
05139 }

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

05050 {
05051    struct ast_hint *hint;
05052    struct ast_state_cb *state_cb;
05053    struct ast_exten *e;
05054    int id;
05055 
05056    /* If there's no context and extension:  add callback to statecbs list */
05057    if (!context && !exten) {
05058       /* Prevent multiple adds from adding the same change_cb at the same time. */
05059       ao2_lock(statecbs);
05060 
05061       /* Remove any existing change_cb. */
05062       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
05063 
05064       /* Now insert the change_cb */
05065       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05066          ao2_unlock(statecbs);
05067          return -1;
05068       }
05069       state_cb->id = 0;
05070       state_cb->change_cb = change_cb;
05071       state_cb->destroy_cb = destroy_cb;
05072       state_cb->data = data;
05073       ao2_link(statecbs, state_cb);
05074 
05075       ao2_ref(state_cb, -1);
05076       ao2_unlock(statecbs);
05077       return 0;
05078    }
05079 
05080    if (!context || !exten)
05081       return -1;
05082 
05083    /* This callback type is for only one hint, so get the hint */
05084    e = ast_hint_extension(NULL, context, exten);
05085    if (!e) {
05086       return -1;
05087    }
05088 
05089    /* If this is a pattern, dynamically create a new extension for this
05090     * particular match.  Note that this will only happen once for each
05091     * individual extension, because the pattern will no longer match first.
05092     */
05093    if (e->exten[0] == '_') {
05094       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05095          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05096          e->registrar);
05097       e = ast_hint_extension(NULL, context, exten);
05098       if (!e || e->exten[0] == '_') {
05099          return -1;
05100       }
05101    }
05102 
05103    /* Find the hint in the hints container */
05104    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05105    hint = ao2_find(hints, e, 0);
05106    if (!hint) {
05107       ao2_unlock(hints);
05108       return -1;
05109    }
05110 
05111    /* Now insert the callback in the callback list  */
05112    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05113       ao2_ref(hint, -1);
05114       ao2_unlock(hints);
05115       return -1;
05116    }
05117    do {
05118       id = stateid++;      /* Unique ID for this callback */
05119       /* Do not allow id to ever be -1 or 0. */
05120    } while (id == -1 || id == 0);
05121    state_cb->id = id;
05122    state_cb->change_cb = change_cb; /* Pointer to callback routine */
05123    state_cb->destroy_cb = destroy_cb;
05124    state_cb->data = data;     /* Data for the callback */
05125    ao2_link(hint->callbacks, state_cb);
05126 
05127    ao2_ref(state_cb, -1);
05128    ao2_ref(hint, -1);
05129    ao2_unlock(hints);
05130 
05131    return id;
05132 }

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

05158 {
05159    struct ast_state_cb *p_cur;
05160    int ret = -1;
05161 
05162    if (!id) {  /* id == 0 is a callback without extension */
05163       if (!change_cb) {
05164          return ret;
05165       }
05166       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
05167       if (p_cur) {
05168          ret = 0;
05169          ao2_ref(p_cur, -1);
05170       }
05171    } else { /* callback with extension, find the callback based on ID */
05172       struct ast_hint *hint;
05173 
05174       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05175       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
05176       if (hint) {
05177          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
05178          if (p_cur) {
05179             ret = 0;
05180             ao2_ref(p_cur, -1);
05181          }
05182          ao2_ref(hint, -1);
05183       }
05184       ao2_unlock(hints);
05185    }
05186 
05187    return ret;
05188 }

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

05406 {
05407    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05408 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

05411 {
05412    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05413 }

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

04178 {
04179    char *copy = ast_strdupa(function);
04180    char *args = func_args(copy);
04181    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04182    int res;
04183    struct ast_module_user *u = NULL;
04184 
04185    if (acfptr == NULL) {
04186       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04187    } else if (!acfptr->read && !acfptr->read2) {
04188       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04189    } else if (!is_read_allowed(acfptr)) {
04190       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04191    } else if (acfptr->read) {
04192       if (acfptr->mod) {
04193          u = __ast_module_user_add(acfptr->mod, chan);
04194       }
04195       res = acfptr->read(chan, copy, args, workspace, len);
04196       if (acfptr->mod && u) {
04197          __ast_module_user_remove(acfptr->mod, u);
04198       }
04199       return res;
04200    } else {
04201       struct ast_str *str = ast_str_create(16);
04202       if (acfptr->mod) {
04203          u = __ast_module_user_add(acfptr->mod, chan);
04204       }
04205       res = acfptr->read2(chan, copy, args, &str, 0);
04206       if (acfptr->mod && u) {
04207          __ast_module_user_remove(acfptr->mod, u);
04208       }
04209       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
04210       ast_free(str);
04211       return res;
04212    }
04213    return -1;
04214 }

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

04217 {
04218    char *copy = ast_strdupa(function);
04219    char *args = func_args(copy);
04220    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04221    int res;
04222    struct ast_module_user *u = NULL;
04223 
04224    if (acfptr == NULL) {
04225       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04226    } else if (!acfptr->read && !acfptr->read2) {
04227       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04228    } else if (!is_read_allowed(acfptr)) {
04229       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04230    } else {
04231       if (acfptr->mod) {
04232          u = __ast_module_user_add(acfptr->mod, chan);
04233       }
04234       ast_str_reset(*str);
04235       if (acfptr->read2) {
04236          /* ast_str enabled */
04237          res = acfptr->read2(chan, copy, args, str, maxlen);
04238       } else {
04239          /* Legacy function pointer, allocate buffer for result */
04240          int maxsize = ast_str_size(*str);
04241          if (maxlen > -1) {
04242             if (maxlen == 0) {
04243                if (acfptr->read_max) {
04244                   maxsize = acfptr->read_max;
04245                } else {
04246                   maxsize = VAR_BUF_SIZE;
04247                }
04248             } else {
04249                maxsize = maxlen;
04250             }
04251             ast_str_make_space(str, maxsize);
04252          }
04253          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
04254       }
04255       if (acfptr->mod && u) {
04256          __ast_module_user_remove(acfptr->mod, u);
04257       }
04258       return res;
04259    }
04260    return -1;
04261 }

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

04264 {
04265    char *copy = ast_strdupa(function);
04266    char *args = func_args(copy);
04267    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04268 
04269    if (acfptr == NULL) {
04270       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04271    } else if (!acfptr->write) {
04272       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
04273    } else if (!is_write_allowed(acfptr)) {
04274       ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
04275    } else {
04276       int res;
04277       struct ast_module_user *u = NULL;
04278       if (acfptr->mod)
04279          u = __ast_module_user_add(acfptr->mod, chan);
04280       res = acfptr->write(chan, copy, args, value);
04281       if (acfptr->mod && u)
04282          __ast_module_user_remove(acfptr->mod, u);
04283       return res;
04284    }
04285 
04286    return -1;
04287 }

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

Definition at line 11111 of file pbx.c.

References ast_context::registrar.

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

11112 {
11113    return c ? c->registrar : NULL;
11114 }

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

References ast_exten::cidmatch.

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

11137 {
11138    return e ? e->cidmatch : NULL;
11139 }

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

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

11079 {
11080    return exten ? exten->parent : NULL;
11081 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 11088 of file pbx.c.

References ast_exten::label.

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

11089 {
11090    return exten ? exten->label : NULL;
11091 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 11131 of file pbx.c.

References ast_exten::matchcid.

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

11132 {
11133    return e ? e->matchcid : 0;
11134 }

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

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

11104 {
11105    return exten ? exten->priority : -1;
11106 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 11116 of file pbx.c.

References ast_exten::registrar.

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

11117 {
11118    return e ? e->registrar : NULL;
11119 }

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

05363 {
05364    struct ast_exten *e = ast_hint_extension(c, context, exten);
05365 
05366    if (e) {
05367       if (hint)
05368          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05369       if (name) {
05370          const char *tmp = ast_get_extension_app_data(e);
05371          if (tmp)
05372             ast_copy_string(name, tmp, namesize);
05373       }
05374       return -1;
05375    }
05376    return 0;
05377 }

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

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

11127 {
11128    return ip ? ip->registrar : NULL;
11129 }

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

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

11122 {
11123    return i ? i->registrar : NULL;
11124 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

11157 {
11158    return sw ? sw->data : NULL;
11159 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 11161 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

11162 {
11163    return sw->eval;
11164 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

11152 {
11153    return sw ? sw->name : NULL;
11154 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

11167 {
11168    return sw ? sw->registrar : NULL;
11169 }

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

11262 {
11263    return __ast_goto_if_exists(chan, context, exten, priority, 0);
11264 }

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

hashtable functions for contexts

Definition at line 1136 of file pbx.c.

References ast_context::name.

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

01137 {
01138    const struct ast_context *ac = ah_a;
01139    const struct ast_context *bc = ah_b;
01140    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01141       return 1;
01142    /* assume context names are registered in a string table! */
01143    return strcmp(ac->name, bc->name);
01144 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

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

01189 {
01190    const struct ast_context *ac = obj;
01191    return ast_hashtab_hash_string(ac->name);
01192 }

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

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

04836 {
04837    struct ast_exten *e;
04838    ast_rdlock_contexts();
04839    e = ast_hint_extension_nolock(c, context, exten);
04840    ast_unlock_contexts();
04841    return e;
04842 }

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

04830 {
04831    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04832    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04833 }

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

08651 {
08652    struct ast_context *con = ast_context_find(context);
08653 
08654    if (con) {
08655       struct ast_ignorepat *pat;
08656 
08657       for (pat = con->ignorepats; pat; pat = pat->next) {
08658          if (ast_extension_match(pat->pattern, pattern))
08659             return 1;
08660       }
08661    }
08662 
08663    return 0;
08664 }

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

05421 {
05422    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05423 }

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

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

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

11327 {
11328    return pbx_parseable_goto(chan, goto_string, 0);
11329 }

int ast_pbx_init ( void   ) 

Provided by pbx.c

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

11408 {
11409    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
11410    statecbs = ao2_container_alloc(1, NULL, statecbs_cmp);
11411 
11412    ast_register_atexit(pbx_shutdown);
11413 
11414    return (hints && statecbs) ? 0 : -1;
11415 }

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

09545 {
09546    struct ast_channel *chan;
09547    struct app_tmp *tmp;
09548    int res = -1, cdr_res = -1;
09549    struct outgoing_helper oh;
09550 
09551    memset(&oh, 0, sizeof(oh));
09552    oh.vars = vars;
09553    oh.account = account;
09554 
09555    if (locked_channel)
09556       *locked_channel = NULL;
09557    if (ast_strlen_zero(app)) {
09558       res = -1;
09559       goto outgoing_app_cleanup;
09560    }
09561    if (synchronous) {
09562       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09563       if (chan) {
09564          ast_set_variables(chan, vars);
09565          if (account)
09566             ast_cdr_setaccount(chan, account);
09567          if (chan->_state == AST_STATE_UP) {
09568             res = 0;
09569             ast_verb(4, "Channel %s was answered.\n", chan->name);
09570             tmp = ast_calloc(1, sizeof(*tmp));
09571             if (!tmp || ast_string_field_init(tmp, 252)) {
09572                if (tmp) {
09573                   ast_free(tmp);
09574                }
09575                res = -1;
09576             } else {
09577                ast_string_field_set(tmp, app, app);
09578                ast_string_field_set(tmp, data, appdata);
09579                tmp->chan = chan;
09580                if (synchronous > 1) {
09581                   if (locked_channel)
09582                      ast_channel_unlock(chan);
09583                   ast_pbx_run_app(tmp);
09584                } else {
09585                   if (locked_channel)
09586                      ast_channel_lock(chan);
09587                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09588                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
09589                      ast_string_field_free_memory(tmp);
09590                      ast_free(tmp);
09591                      if (locked_channel)
09592                         ast_channel_unlock(chan);
09593                      ast_hangup(chan);
09594                      res = -1;
09595                   } else {
09596                      if (locked_channel)
09597                         *locked_channel = chan;
09598                   }
09599                }
09600             }
09601          } else {
09602             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09603             if (chan->cdr) { /* update the cdr */
09604                /* here we update the status of the call, which sould be busy.
09605                 * if that fails then we set the status to failed */
09606                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09607                   ast_cdr_failed(chan->cdr);
09608             }
09609             ast_hangup(chan);
09610          }
09611       }
09612 
09613       if (res < 0) { /* the call failed for some reason */
09614          if (*reason == 0) { /* if the call failed (not busy or no answer)
09615                         * update the cdr with the failed message */
09616             cdr_res = ast_pbx_outgoing_cdr_failed();
09617             if (cdr_res != 0) {
09618                res = cdr_res;
09619                goto outgoing_app_cleanup;
09620             }
09621          }
09622       }
09623 
09624    } else {
09625       struct async_stat *as;
09626       if (!(as = ast_calloc(1, sizeof(*as)))) {
09627          res = -1;
09628          goto outgoing_app_cleanup;
09629       }
09630       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09631       if (!chan) {
09632          ast_free(as);
09633          res = -1;
09634          goto outgoing_app_cleanup;
09635       }
09636       as->chan = chan;
09637       ast_copy_string(as->app, app, sizeof(as->app));
09638       if (appdata)
09639          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09640       as->timeout = timeout;
09641       ast_set_variables(chan, vars);
09642       if (account)
09643          ast_cdr_setaccount(chan, account);
09644       /* Start a new thread, and get something handling this channel. */
09645       if (locked_channel)
09646          ast_channel_lock(chan);
09647       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09648          ast_log(LOG_WARNING, "Failed to start async wait\n");
09649          ast_free(as);
09650          if (locked_channel)
09651             ast_channel_unlock(chan);
09652          ast_hangup(chan);
09653          res = -1;
09654          goto outgoing_app_cleanup;
09655       } else {
09656          if (locked_channel)
09657             *locked_channel = chan;
09658       }
09659       res = 0;
09660    }
09661 outgoing_app_cleanup:
09662    ast_variables_destroy(vars);
09663    return res;
09664 }

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

09349 {
09350    /* allocate a channel */
09351    struct ast_channel *chan = ast_dummy_channel_alloc();
09352 
09353    if (!chan)
09354       return -1;  /* failure */
09355 
09356    chan->cdr = ast_cdr_alloc();
09357    if (!chan->cdr) {
09358       /* allocation of the cdr failed */
09359       chan = ast_channel_unref(chan);   /* free the channel */
09360       return -1;                /* return failure */
09361    }
09362 
09363    /* allocation of the cdr was successful */
09364    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
09365    ast_cdr_start(chan->cdr);       /* record the start and stop time */
09366    ast_cdr_end(chan->cdr);
09367    ast_cdr_failed(chan->cdr);      /* set the status to failed */
09368    ast_cdr_detach(chan->cdr);      /* post and free the record */
09369    chan->cdr = NULL;
09370    chan = ast_channel_unref(chan);         /* free the channel */
09371 
09372    return 0;  /* success */
09373 }

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

09376 {
09377    struct ast_channel *chan;
09378    struct async_stat *as;
09379    int res = -1, cdr_res = -1;
09380    struct outgoing_helper oh;
09381 
09382    if (synchronous) {
09383       oh.context = context;
09384       oh.exten = exten;
09385       oh.priority = priority;
09386       oh.cid_num = cid_num;
09387       oh.cid_name = cid_name;
09388       oh.account = account;
09389       oh.vars = vars;
09390       oh.parent_channel = NULL;
09391 
09392       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09393       if (channel) {
09394          *channel = chan;
09395          if (chan)
09396             ast_channel_lock(chan);
09397       }
09398       if (chan) {
09399          if (chan->_state == AST_STATE_UP) {
09400                res = 0;
09401             ast_verb(4, "Channel %s was answered.\n", chan->name);
09402 
09403             if (synchronous > 1) {
09404                if (channel)
09405                   ast_channel_unlock(chan);
09406                if (ast_pbx_run(chan)) {
09407                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09408                   if (channel)
09409                      *channel = NULL;
09410                   ast_hangup(chan);
09411                   chan = NULL;
09412                   res = -1;
09413                }
09414             } else {
09415                if (ast_pbx_start(chan)) {
09416                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
09417                   if (channel) {
09418                      *channel = NULL;
09419                      ast_channel_unlock(chan);
09420                   }
09421                   ast_hangup(chan);
09422                   res = -1;
09423                }
09424                chan = NULL;
09425             }
09426          } else {
09427             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09428 
09429             if (chan->cdr) { /* update the cdr */
09430                /* here we update the status of the call, which sould be busy.
09431                 * if that fails then we set the status to failed */
09432                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09433                   ast_cdr_failed(chan->cdr);
09434             }
09435 
09436             if (channel) {
09437                *channel = NULL;
09438                ast_channel_unlock(chan);
09439             }
09440             ast_hangup(chan);
09441             chan = NULL;
09442          }
09443       }
09444 
09445       if (res < 0) { /* the call failed for some reason */
09446          if (*reason == 0) { /* if the call failed (not busy or no answer)
09447                         * update the cdr with the failed message */
09448             cdr_res = ast_pbx_outgoing_cdr_failed();
09449             if (cdr_res != 0) {
09450                res = cdr_res;
09451                goto outgoing_exten_cleanup;
09452             }
09453          }
09454 
09455          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
09456          /* check if "failed" exists */
09457          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
09458             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
09459             if (chan) {
09460                char failed_reason[4] = "";
09461                if (!ast_strlen_zero(context))
09462                   ast_copy_string(chan->context, context, sizeof(chan->context));
09463                set_ext_pri(chan, "failed", 1);
09464                ast_set_variables(chan, vars);
09465                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
09466                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
09467                if (account)
09468                   ast_cdr_setaccount(chan, account);
09469                if (ast_pbx_run(chan)) {
09470                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
09471                   ast_hangup(chan);
09472                }
09473                chan = NULL;
09474             }
09475          }
09476       }
09477    } else {
09478       if (!(as = ast_calloc(1, sizeof(*as)))) {
09479          res = -1;
09480          goto outgoing_exten_cleanup;
09481       }
09482       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
09483       if (channel) {
09484          *channel = chan;
09485          if (chan)
09486             ast_channel_lock(chan);
09487       }
09488       if (!chan) {
09489          ast_free(as);
09490          res = -1;
09491          goto outgoing_exten_cleanup;
09492       }
09493       as->chan = chan;
09494       ast_copy_string(as->context, context, sizeof(as->context));
09495       set_ext_pri(as->chan,  exten, priority);
09496       as->timeout = timeout;
09497       ast_set_variables(chan, vars);
09498       if (account)
09499          ast_cdr_setaccount(chan, account);
09500       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09501          ast_log(LOG_WARNING, "Failed to start async wait\n");
09502          ast_free(as);
09503          if (channel) {
09504             *channel = NULL;
09505             ast_channel_unlock(chan);
09506          }
09507          ast_hangup(chan);
09508          res = -1;
09509          goto outgoing_exten_cleanup;
09510       }
09511       res = 0;
09512    }
09513 outgoing_exten_cleanup:
09514    ast_variables_destroy(vars);
09515    return res;
09516 }

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

05927 {
05928    return ast_pbx_run_args(c, NULL);
05929 }

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

run the application and free the descriptor once done

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

09529 {
09530    struct app_tmp *tmp = data;
09531    struct ast_app *app;
09532    app = pbx_findapp(tmp->app);
09533    if (app) {
09534       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
09535       pbx_exec(tmp->chan, app, tmp->data);
09536    } else
09537       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
09538    ast_hangup(tmp->chan);
09539    ast_string_field_free_memory(tmp);
09540    ast_free(tmp);
09541    return NULL;
09542 }

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

05907 {
05908    enum ast_pbx_result res = AST_PBX_SUCCESS;
05909 
05910    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05911       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05912       return AST_PBX_FAILED;
05913    }
05914 
05915    if (increase_call_count(c)) {
05916       return AST_PBX_CALL_LIMIT;
05917    }
05918 
05919    res = __ast_pbx_run(c, args);
05920 
05921    decrease_call_count();
05922 
05923    return res;
05924 }

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

05880 {
05881    pthread_t t;
05882 
05883    if (!c) {
05884       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05885       return AST_PBX_FAILED;
05886    }
05887 
05888    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05889       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05890       return AST_PBX_FAILED;
05891    }
05892 
05893    if (increase_call_count(c))
05894       return AST_PBX_CALL_LIMIT;
05895 
05896    /* Start a new thread, and get something handling this channel. */
05897    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05898       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05899       decrease_call_count();
05900       return AST_PBX_FAILED;
05901    }
05902 
05903    return AST_PBX_SUCCESS;
05904 }

int ast_processed_calls ( void   ) 

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

Definition at line 5936 of file pbx.c.

References totalcalls.

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

05937 {
05938    return totalcalls;
05939 }

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

11061 {
11062    return ast_rwlock_rdlock(&con->lock);
11063 }

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

06345 {
06346    struct ast_app *tmp, *cur = NULL;
06347    char tmps[80];
06348    int length, res;
06349 #ifdef AST_XML_DOCS
06350    char *tmpxml;
06351 #endif
06352 
06353    AST_RWLIST_WRLOCK(&apps);
06354    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
06355       if (!(res = strcasecmp(app, tmp->name))) {
06356          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
06357          AST_RWLIST_UNLOCK(&apps);
06358          return -1;
06359       } else if (res < 0)
06360          break;
06361    }
06362 
06363    length = sizeof(*tmp) + strlen(app) + 1;
06364 
06365    if (!(tmp = ast_calloc(1, length))) {
06366       AST_RWLIST_UNLOCK(&apps);
06367       return -1;
06368    }
06369 
06370    if (ast_string_field_init(tmp, 128)) {
06371       AST_RWLIST_UNLOCK(&apps);
06372       ast_free(tmp);
06373       return -1;
06374    }
06375 
06376    strcpy(tmp->name, app);
06377    tmp->execute = execute;
06378    tmp->module = mod;
06379 
06380 #ifdef AST_XML_DOCS
06381    /* Try to lookup the docs in our XML documentation database */
06382    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
06383       /* load synopsis */
06384       tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
06385       ast_string_field_set(tmp, synopsis, tmpxml);
06386       ast_free(tmpxml);
06387 
06388       /* load description */
06389       tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
06390       ast_string_field_set(tmp, description, tmpxml);
06391       ast_free(tmpxml);
06392 
06393       /* load syntax */
06394       tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
06395       ast_string_field_set(tmp, syntax, tmpxml);
06396       ast_free(tmpxml);
06397 
06398       /* load arguments */
06399       tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
06400       ast_string_field_set(tmp, arguments, tmpxml);
06401       ast_free(tmpxml);
06402 
06403       /* load seealso */
06404       tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
06405       ast_string_field_set(tmp, seealso, tmpxml);
06406       ast_free(tmpxml);
06407       tmp->docsrc = AST_XML_DOC;
06408    } else {
06409 #endif
06410       ast_string_field_set(tmp, synopsis, synopsis);
06411       ast_string_field_set(tmp, description, description);
06412 #ifdef AST_XML_DOCS
06413       tmp->docsrc = AST_STATIC_DOC;
06414    }
06415 #endif
06416 
06417    /* Store in alphabetical order */
06418    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
06419       if (strcasecmp(tmp->name, cur->name) < 0) {
06420          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
06421          break;
06422       }
06423    }
06424    AST_RWLIST_TRAVERSE_SAFE_END;
06425    if (!cur)
06426       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
06427 
06428    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
06429 
06430    AST_RWLIST_UNLOCK(&apps);
06431 
06432    return 0;
06433 }

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

06440 {
06441    struct ast_switch *tmp;
06442 
06443    AST_RWLIST_WRLOCK(&switches);
06444    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
06445       if (!strcasecmp(tmp->name, sw->name)) {
06446          AST_RWLIST_UNLOCK(&switches);
06447          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
06448          return -1;
06449       }
06450    }
06451    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
06452    AST_RWLIST_UNLOCK(&switches);
06453 
06454    return 0;
06455 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

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

05238 {
05239    /* Cleanup the Notifys if hint is removed */
05240    struct ast_hint *hint;
05241 
05242    if (!e) {
05243       return -1;
05244    }
05245 
05246    hint = ao2_find(hints, e, OBJ_UNLINK);
05247    if (!hint) {
05248       return -1;
05249    }
05250 
05251    /*
05252     * The extension is being destroyed so we must save some
05253     * information to notify that the extension is deactivated.
05254     */
05255    ao2_lock(hint);
05256    ast_copy_string(hint->context_name,
05257       ast_get_context_name(ast_get_extension_context(hint->exten)),
05258       sizeof(hint->context_name));
05259    ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten),
05260       sizeof(hint->exten_name));
05261    hint->exten = NULL;
05262    ao2_unlock(hint);
05263 
05264    ao2_ref(hint, -1);
05265 
05266    return 0;
05267 }

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

05426 {
05427    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05428 }

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

05381 {
05382    struct ast_exten *e = ast_hint_extension(c, context, exten);
05383 
05384    if (!e) {
05385       return 0;
05386    }
05387 
05388    if (hint) {
05389       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05390    }
05391    if (name) {
05392       const char *tmp = ast_get_extension_app_data(e);
05393       if (tmp) {
05394          ast_str_set(name, namesize, "%s", tmp);
05395       }
05396    }
05397    return -1;
05398 }

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

03446 {
03447    const char not_found = '\0';
03448    char *tmpvar;
03449    const char *ret;
03450    const char *s; /* the result */
03451    int offset, length;
03452    int i, need_substring;
03453    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03454    char workspace[20];
03455 
03456    if (c) {
03457       ast_channel_lock(c);
03458       places[0] = &c->varshead;
03459    }
03460    /*
03461     * Make a copy of var because parse_variable_name() modifies the string.
03462     * Then if called directly, we might need to run substring() on the result;
03463     * remember this for later in 'need_substring', 'offset' and 'length'
03464     */
03465    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03466    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03467 
03468    /*
03469     * Look first into predefined variables, then into variable lists.
03470     * Variable 's' points to the result, according to the following rules:
03471     * s == &not_found (set at the beginning) means that we did not find a
03472     * matching variable and need to look into more places.
03473     * If s != &not_found, s is a valid result string as follows:
03474     * s = NULL if the variable does not have a value;
03475     * you typically do this when looking for an unset predefined variable.
03476     * s = workspace if the result has been assembled there;
03477     * typically done when the result is built e.g. with an snprintf(),
03478     * so we don't need to do an additional copy.
03479     * s != workspace in case we have a string, that needs to be copied
03480     * (the ast_copy_string is done once for all at the end).
03481     * Typically done when the result is already available in some string.
03482     */
03483    s = &not_found;   /* default value */
03484    if (c) { /* This group requires a valid channel */
03485       /* Names with common parts are looked up a piece at a time using strncmp. */
03486       if (!strncmp(var, "CALL", 4)) {
03487          if (!strncmp(var + 4, "ING", 3)) {
03488             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03489                ast_str_set(str, maxlen, "%d",
03490                   ast_party_id_presentation(&c->caller.id));
03491                s = ast_str_buffer(*str);
03492             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03493                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03494                s = ast_str_buffer(*str);
03495             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03496                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03497                s = ast_str_buffer(*str);
03498             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03499                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03500                s = ast_str_buffer(*str);
03501             }
03502          }
03503       } else if (!strcmp(var, "HINT")) {
03504          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03505       } else if (!strcmp(var, "HINTNAME")) {
03506          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03507       } else if (!strcmp(var, "EXTEN")) {
03508          s = c->exten;
03509       } else if (!strcmp(var, "CONTEXT")) {
03510          s = c->context;
03511       } else if (!strcmp(var, "PRIORITY")) {
03512          ast_str_set(str, maxlen, "%d", c->priority);
03513          s = ast_str_buffer(*str);
03514       } else if (!strcmp(var, "CHANNEL")) {
03515          s = c->name;
03516       } else if (!strcmp(var, "UNIQUEID")) {
03517          s = c->uniqueid;
03518       } else if (!strcmp(var, "HANGUPCAUSE")) {
03519          ast_str_set(str, maxlen, "%d", c->hangupcause);
03520          s = ast_str_buffer(*str);
03521       }
03522    }
03523    if (s == &not_found) { /* look for more */
03524       if (!strcmp(var, "EPOCH")) {
03525          ast_str_set(str, maxlen, "%d", (int) time(NULL));
03526          s = ast_str_buffer(*str);
03527       } else if (!strcmp(var, "SYSTEMNAME")) {
03528          s = ast_config_AST_SYSTEM_NAME;
03529       } else if (!strcmp(var, "ENTITYID")) {
03530          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03531          s = workspace;
03532       }
03533    }
03534    /* if not found, look into chanvars or global vars */
03535    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03536       struct ast_var_t *variables;
03537       if (!places[i])
03538          continue;
03539       if (places[i] == &globals)
03540          ast_rwlock_rdlock(&globalslock);
03541       AST_LIST_TRAVERSE(places[i], variables, entries) {
03542          if (!strcasecmp(ast_var_name(variables), var)) {
03543             s = ast_var_value(variables);
03544             break;
03545          }
03546       }
03547       if (places[i] == &globals)
03548          ast_rwlock_unlock(&globalslock);
03549    }
03550    if (s == &not_found || s == NULL) {
03551       ast_debug(5, "Result of '%s' is NULL\n", var);
03552       ret = NULL;
03553    } else {
03554       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03555       if (s != ast_str_buffer(*str)) {
03556          ast_str_set(str, maxlen, "%s", s);
03557       }
03558       ret = ast_str_buffer(*str);
03559       if (need_substring) {
03560          ret = ast_str_substring(*str, offset, length);
03561          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03562       }
03563    }
03564 
03565    if (c) {
03566       ast_channel_unlock(c);
03567    }
03568    return ret;
03569 }

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

04469 {
04470    size_t used;
04471    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04472 }

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

04290 {
04291    /* Substitutes variables into buf, based on string templ */
04292    char *cp4 = NULL;
04293    const char *tmp, *whereweare;
04294    int orig_size = 0;
04295    int offset, offset2, isfunction;
04296    const char *nextvar, *nextexp, *nextthing;
04297    const char *vars, *vare;
04298    char *finalvars;
04299    int pos, brackets, needsub, len;
04300    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
04301 
04302    ast_str_reset(*buf);
04303    whereweare = tmp = templ;
04304    while (!ast_strlen_zero(whereweare)) {
04305       /* reset our buffer */
04306       ast_str_reset(substr3);
04307 
04308       /* Assume we're copying the whole remaining string */
04309       pos = strlen(whereweare);
04310       nextvar = NULL;
04311       nextexp = NULL;
04312       nextthing = strchr(whereweare, '$');
04313       if (nextthing) {
04314          switch (nextthing[1]) {
04315          case '{':
04316             nextvar = nextthing;
04317             pos = nextvar - whereweare;
04318             break;
04319          case '[':
04320             nextexp = nextthing;
04321             pos = nextexp - whereweare;
04322             break;
04323          default:
04324             pos = 1;
04325          }
04326       }
04327 
04328       if (pos) {
04329          /* Copy that many bytes */
04330          ast_str_append_substr(buf, maxlen, whereweare, pos);
04331 
04332          templ += pos;
04333          whereweare += pos;
04334       }
04335 
04336       if (nextvar) {
04337          /* We have a variable.  Find the start and end, and determine
04338             if we are going to have to recursively call ourselves on the
04339             contents */
04340          vars = vare = nextvar + 2;
04341          brackets = 1;
04342          needsub = 0;
04343 
04344          /* Find the end of it */
04345          while (brackets && *vare) {
04346             if ((vare[0] == '$') && (vare[1] == '{')) {
04347                needsub++;
04348             } else if (vare[0] == '{') {
04349                brackets++;
04350             } else if (vare[0] == '}') {
04351                brackets--;
04352             } else if ((vare[0] == '$') && (vare[1] == '['))
04353                needsub++;
04354             vare++;
04355          }
04356          if (brackets)
04357             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04358          len = vare - vars - 1;
04359 
04360          /* Skip totally over variable string */
04361          whereweare += (len + 3);
04362 
04363          /* Store variable name (and truncate) */
04364          ast_str_set_substr(&substr1, 0, vars, len);
04365          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
04366 
04367          /* Substitute if necessary */
04368          if (needsub) {
04369             size_t used;
04370             if (!substr2) {
04371                substr2 = ast_str_create(16);
04372             }
04373 
04374             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04375             finalvars = ast_str_buffer(substr2);
04376          } else {
04377             finalvars = ast_str_buffer(substr1);
04378          }
04379 
04380          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
04381          if (isfunction) {
04382             /* Evaluate function */
04383             if (c || !headp) {
04384                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04385             } else {
04386                struct varshead old;
04387                struct ast_channel *bogus = ast_dummy_channel_alloc();
04388                if (bogus) {
04389                   memcpy(&old, &bogus->varshead, sizeof(old));
04390                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
04391                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04392                   /* Don't deallocate the varshead that was passed in */
04393                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
04394                   ast_channel_unref(bogus);
04395                } else {
04396                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04397                }
04398             }
04399             ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)");
04400          } else {
04401             /* Retrieve variable value */
04402             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04403             cp4 = ast_str_buffer(substr3);
04404          }
04405          if (cp4) {
04406             ast_str_substring(substr3, offset, offset2);
04407             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04408          }
04409       } else if (nextexp) {
04410          /* We have an expression.  Find the start and end, and determine
04411             if we are going to have to recursively call ourselves on the
04412             contents */
04413          vars = vare = nextexp + 2;
04414          brackets = 1;
04415          needsub = 0;
04416 
04417          /* Find the end of it */
04418          while (brackets && *vare) {
04419             if ((vare[0] == '$') && (vare[1] == '[')) {
04420                needsub++;
04421                brackets++;
04422                vare++;
04423             } else if (vare[0] == '[') {
04424                brackets++;
04425             } else if (vare[0] == ']') {
04426                brackets--;
04427             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04428                needsub++;
04429                vare++;
04430             }
04431             vare++;
04432          }
04433          if (brackets)
04434             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04435          len = vare - vars - 1;
04436 
04437          /* Skip totally over expression */
04438          whereweare += (len + 3);
04439 
04440          /* Store variable name (and truncate) */
04441          ast_str_set_substr(&substr1, 0, vars, len);
04442 
04443          /* Substitute if necessary */
04444          if (needsub) {
04445             size_t used;
04446             if (!substr2) {
04447                substr2 = ast_str_create(16);
04448             }
04449 
04450             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04451             finalvars = ast_str_buffer(substr2);
04452          } else {
04453             finalvars = ast_str_buffer(substr1);
04454          }
04455 
04456          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04457             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04458          }
04459          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04460       }
04461    }
04462    *used = ast_str_strlen(*buf) - orig_size;
04463    ast_free(substr1);
04464    ast_free(substr2);
04465    ast_free(substr3);
04466 }

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

04475 {
04476    size_t used;
04477    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04478 }

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

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

03381 {
03382    int lr;  /* length of the input string after the copy */
03383 
03384    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
03385 
03386    /* Quick check if no need to do anything */
03387    if (offset == 0 && length >= lr) /* take the whole string */
03388       return ast_str_buffer(value);
03389 
03390    if (offset < 0)   {  /* translate negative offset into positive ones */
03391       offset = lr + offset;
03392       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03393          offset = 0;
03394    }
03395 
03396    /* too large offset result in empty string so we know what to return */
03397    if (offset >= lr) {
03398       ast_str_reset(value);
03399       return ast_str_buffer(value);
03400    }
03401 
03402    if (offset > 0) {
03403       /* Go ahead and chop off the beginning */
03404       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
03405       lr -= offset;
03406    }
03407 
03408    if (length >= 0 && length < lr) {   /* truncate if necessary */
03409       char *tmp = ast_str_buffer(value);
03410       tmp[length] = '\0';
03411       ast_str_update(value);
03412    } else if (length < 0) {
03413       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
03414          char *tmp = ast_str_buffer(value);
03415          tmp[lr + length] = '\0';
03416          ast_str_update(value);
03417       } else {
03418          ast_str_reset(value);
03419       }
03420    } else {
03421       /* Nothing to do, but update the buffer length */
03422       ast_str_update(value);
03423    }
03424 
03425    return ast_str_buffer(value);
03426 }

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

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

Referenced by handle_tcptls_connection().

04073 {
04074    int *thread_inhibit_escalations;
04075 
04076    thread_inhibit_escalations = ast_threadstorage_get(
04077       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04078 
04079    if (thread_inhibit_escalations == NULL) {
04080       ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
04081       return -1;
04082    }
04083 
04084    *thread_inhibit_escalations = 1;
04085    return 0;
04086 }

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

07706 {
07707    struct ast_app *tmp;
07708 
07709    AST_RWLIST_WRLOCK(&apps);
07710    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
07711       if (!strcasecmp(app, tmp->name)) {
07712          unreference_cached_app(tmp);
07713          AST_RWLIST_REMOVE_CURRENT(list);
07714          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
07715          ast_string_field_free_memory(tmp);
07716          ast_free(tmp);
07717          break;
07718       }
07719    }
07720    AST_RWLIST_TRAVERSE_SAFE_END;
07721    AST_RWLIST_UNLOCK(&apps);
07722 
07723    return tmp ? 0 : -1;
07724 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

06458 {
06459    AST_RWLIST_WRLOCK(&switches);
06460    AST_RWLIST_REMOVE(&switches, sw, list);
06461    AST_RWLIST_UNLOCK(&switches);
06462 }

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

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

11181 {
11182    if (!exten)
11183       return con ? con->root : NULL;
11184    else
11185       return exten->next;
11186 }

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

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

11214 {
11215    if (!ip)
11216       return con ? con->ignorepats : NULL;
11217    else
11218       return ip->next;
11219 }

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

11190 {
11191    if (!sw)
11192       return con ? AST_LIST_FIRST(&con->alts) : NULL;
11193    else
11194       return AST_LIST_NEXT(sw, list);
11195 }

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

11199 {
11200    return priority ? priority->peer : exten;
11201 }

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

11056 {
11057    return ast_rwlock_wrlock(&con->lock);
11058 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

11038 {
11039    return ast_mutex_lock(&conlock);
11040 }

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

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

09286 {
09287    struct async_stat *as = data;
09288    struct ast_channel *chan = as->chan;
09289    int timeout = as->timeout;
09290    int res;
09291    struct ast_frame *f;
09292    struct ast_app *app;
09293    struct timeval start = ast_tvnow();
09294    int ms;
09295 
09296    while ((ms = ast_remaining_ms(start, timeout)) &&
09297          chan->_state != AST_STATE_UP) {
09298       res = ast_waitfor(chan, ms);
09299       if (res < 1)
09300          break;
09301 
09302       f = ast_read(chan);
09303       if (!f)
09304          break;
09305       if (f->frametype == AST_FRAME_CONTROL) {
09306          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
09307              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
09308             ast_frfree(f);
09309             break;
09310          }
09311       }
09312       ast_frfree(f);
09313    }
09314    if (chan->_state == AST_STATE_UP) {
09315       if (!ast_strlen_zero(as->app)) {
09316          app = pbx_findapp(as->app);
09317          if (app) {
09318             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
09319             pbx_exec(chan, app, as->appdata);
09320          } else
09321             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
09322       } else {
09323          if (!ast_strlen_zero(as->context))
09324             ast_copy_string(chan->context, as->context, sizeof(chan->context));
09325          if (!ast_strlen_zero(as->exten))
09326             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
09327          if (as->priority > 0)
09328             chan->priority = as->priority;
09329          /* Run the PBX */
09330          if (ast_pbx_run(chan)) {
09331             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
09332          } else {
09333             /* PBX will have taken care of this */
09334             chan = NULL;
09335          }
09336       }
09337    }
09338    ast_free(as);
09339    if (chan)
09340       ast_hangup(chan);
09341    return NULL;
09342 }

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

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

01700 {
01701    char extenstr[40];
01702    struct ast_str *my_prefix = ast_str_alloca(1024);
01703 
01704    extenstr[0] = '\0';
01705 
01706    if (node->exten) {
01707       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01708    }
01709 
01710    if (strlen(node->x) > 1) {
01711       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01712          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01713          node->exten ? node->exten->exten : "", extenstr);
01714    } else {
01715       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01716          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01717          node->exten ? node->exten->exten : "", extenstr);
01718    }
01719 
01720    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01721 
01722    if (node->next_char)
01723       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01724 
01725    if (node->alt_char)
01726       cli_match_char_tree(node->alt_char, prefix, fd);
01727 }

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

05447 {
05448    int digit;
05449 
05450    buf[pos] = '\0';  /* make sure it is properly terminated */
05451    while (ast_matchmore_extension(c, c->context, buf, 1,
05452       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05453       /* As long as we're willing to wait, and as long as it's not defined,
05454          keep reading digits until we can't possibly get a right answer anymore.  */
05455       digit = ast_waitfordigit(c, waittime);
05456       if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05457          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05458       } else {
05459          if (!digit) /* No entry */
05460             break;
05461          if (digit < 0) /* Error, maybe a  hangup */
05462             return -1;
05463          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
05464             buf[pos++] = digit;
05465             buf[pos] = '\0';
05466          }
05467          waittime = c->pbx->dtimeoutms;
05468       }
05469    }
05470    return 0;
05471 }

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

Definition at line 1127 of file pbx.c.

Referenced by get_pattern_node().

01128 {
01129    const unsigned char *ac = a;
01130    const unsigned char *bc = b;
01131 
01132    return *ac - *bc;
01133 }

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

06650 {
06651    struct ast_hint *hint;
06652    char *ret = NULL;
06653    int which = 0;
06654    int wordlen;
06655    struct ao2_iterator i;
06656 
06657    if (pos != 3)
06658       return NULL;
06659 
06660    wordlen = strlen(word);
06661 
06662    /* walk through all hints */
06663    i = ao2_iterator_init(hints, 0);
06664    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06665       ao2_lock(hint);
06666       if (!hint->exten) {
06667          /* The extension has already been destroyed */
06668          ao2_unlock(hint);
06669          continue;
06670       }
06671       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
06672          ret = ast_strdup(ast_get_extension_name(hint->exten));
06673          ao2_unlock(hint);
06674          ao2_ref(hint, -1);
06675          break;
06676       }
06677       ao2_unlock(hint);
06678    }
06679    ao2_iterator_destroy(&i);
06680 
06681    return ret;
06682 }

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

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

06867 {
06868    struct ast_context *c = NULL;
06869    char *ret = NULL;
06870    int which = 0;
06871    int wordlen;
06872 
06873    /* we are do completion of [exten@]context on second position only */
06874    if (pos != 2)
06875       return NULL;
06876 
06877    ast_rdlock_contexts();
06878 
06879    wordlen = strlen(word);
06880 
06881    /* walk through all contexts and return the n-th match */
06882    while ( (c = ast_walk_contexts(c)) ) {
06883       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
06884          ret = ast_strdup(ast_get_context_name(c));
06885          break;
06886       }
06887    }
06888 
06889    ast_unlock_contexts();
06890 
06891    return ret;
06892 }

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

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

07847 {
07848    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
07849    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
07850    struct ast_hashtab_iter *exten_iter;
07851    struct ast_hashtab_iter *prio_iter;
07852    int insert_count = 0;
07853    int first = 1;
07854 
07855    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
07856       the current registrar, and copy them to the new context. If the new context does not
07857       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
07858       only create the empty matching context if the old one meets the criteria */
07859 
07860    if (context->root_table) {
07861       exten_iter = ast_hashtab_start_traversal(context->root_table);
07862       while ((exten_item=ast_hashtab_next(exten_iter))) {
07863          if (new) {
07864             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
07865          } else {
07866             new_exten_item = NULL;
07867          }
07868          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
07869          while ((prio_item=ast_hashtab_next(prio_iter))) {
07870             int res1;
07871             char *dupdstr;
07872 
07873             if (new_exten_item) {
07874                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
07875             } else {
07876                new_prio_item = NULL;
07877             }
07878             if (strcmp(prio_item->registrar,registrar) == 0) {
07879                continue;
07880             }
07881             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
07882             if (!new) {
07883                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 */
07884             }
07885 
07886             /* copy in the includes, switches, and ignorepats */
07887             if (first) { /* but, only need to do this once */
07888                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07889                first = 0;
07890             }
07891 
07892             if (!new) {
07893                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
07894                ast_hashtab_end_traversal(prio_iter);
07895                ast_hashtab_end_traversal(exten_iter);
07896                return; /* no sense continuing. */
07897             }
07898             /* we will not replace existing entries in the new context with stuff from the old context.
07899                but, if this is because of some sort of registrar conflict, we ought to say something... */
07900 
07901             dupdstr = ast_strdup(prio_item->data);
07902 
07903             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
07904                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
07905             if (!res1 && new_exten_item && new_prio_item){
07906                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
07907                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
07908             } else {
07909                /* 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,
07910                 and no double frees take place, either! */
07911                insert_count++;
07912             }
07913          }
07914          ast_hashtab_end_traversal(prio_iter);
07915       }
07916       ast_hashtab_end_traversal(exten_iter);
07917    } else if (new) {
07918       /* If the context existed but had no extensions, we still want to merge
07919        * the includes, switches and ignore patterns.
07920        */
07921       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07922    }
07923 
07924    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
07925         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
07926       /* we could have given it the registrar of the other module who incremented the refcount,
07927          but that's not available, so we give it the registrar we know about */
07928       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
07929 
07930       /* copy in the includes, switches, and ignorepats */
07931       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07932    }
07933 }

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

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

07814 {
07815    struct ast_include *i;
07816    struct ast_ignorepat *ip;
07817    struct ast_sw *sw;
07818 
07819    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);
07820    /* copy in the includes, switches, and ignorepats */
07821    /* walk through includes */
07822    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
07823       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
07824          continue; /* not mine */
07825       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
07826    }
07827 
07828    /* walk through switches */
07829    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
07830       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
07831          continue; /* not mine */
07832       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));
07833    }
07834 
07835    /* walk thru ignorepats ... */
07836    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
07837       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
07838          continue; /* not mine */
07839       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
07840    }
07841 }

static void create_match_char_tree ( struct ast_context con  )  [static]

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

02322 {
02323    struct ast_hashtab_iter *t1;
02324    struct ast_exten *e1;
02325 #ifdef NEED_DEBUG
02326    int biggest_bucket, resizes, numobjs, numbucks;
02327 
02328    ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con);
02329    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02330    ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02331          numobjs, numbucks, biggest_bucket, resizes);
02332 #endif
02333    t1 = ast_hashtab_start_traversal(con->root_table);
02334    while ((e1 = ast_hashtab_next(t1))) {
02335       if (e1->exten) {
02336          add_exten_to_pattern_tree(con, e1, 0);
02337       } else {
02338          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02339       }
02340    }
02341    ast_hashtab_end_traversal(t1);
02342 }

static void decrease_call_count ( void   )  [static]

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

05838 {
05839    ast_mutex_lock(&maxcalllock);
05840    if (countcalls > 0)
05841       countcalls--;
05842    ast_mutex_unlock(&maxcalllock);
05843 }

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

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

05208 {
05209    struct ast_hint *hint = obj;
05210 
05211    if (hint->callbacks) {
05212       struct ast_state_cb *state_cb;
05213       const char *context_name;
05214       const char *exten_name;
05215 
05216       if (hint->exten) {
05217          context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
05218          exten_name = ast_get_extension_name(hint->exten);
05219          hint->exten = NULL;
05220       } else {
05221          /* The extension has already been destroyed */
05222          context_name = hint->context_name;
05223          exten_name = hint->exten_name;
05224       }
05225       while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
05226          /* Notify with -1 and remove all callbacks */
05227          /* NOTE: The casts will not be needed for v1.10 and later */
05228          state_cb->change_cb((char *) context_name, (char *) exten_name,
05229             AST_EXTENSION_DEACTIVATED, state_cb->data);
05230          ao2_ref(state_cb, -1);
05231       }
05232       ao2_ref(hint->callbacks, -1);
05233    }
05234 }

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

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

02345 {
02346    /* destroy all the alternates */
02347    if (pattern_tree->alt_char) {
02348       destroy_pattern_tree(pattern_tree->alt_char);
02349       pattern_tree->alt_char = 0;
02350    }
02351    /* destroy all the nexts */
02352    if (pattern_tree->next_char) {
02353       destroy_pattern_tree(pattern_tree->next_char);
02354       pattern_tree->next_char = 0;
02355    }
02356    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02357    ast_free(pattern_tree);
02358 }

static void destroy_state_cb ( void *  doomed  )  [static]

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

05039 {
05040    struct ast_state_cb *state_cb = doomed;
05041 
05042    if (state_cb->destroy_cb) {
05043       state_cb->destroy_cb(state_cb->id, state_cb->data);
05044    }
05045 }

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

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

10906 {
10907    const char *device;
10908    struct statechange *sc;
10909 
10910    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
10911    if (ast_strlen_zero(device)) {
10912       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
10913       return;
10914    }
10915 
10916    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
10917       return;
10918    strcpy(sc->dev, device);
10919    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
10920       ast_free(sc);
10921    }
10922 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 3571 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

03572 {
03573    struct pbx_exception *exception = data;
03574    ast_string_field_free_memory(exception);
03575    ast_free(exception);
03576 }

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

Definition at line 2691 of file pbx.c.

References ext_cmp_exten(), and ext_cmp_pattern().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

02692 {
02693    /* Make sure non-pattern extens come first. */
02694    if (left[0] != '_') {
02695       if (right[0] == '_') {
02696          return -1;
02697       }
02698       /* Compare two non-pattern extens. */
02699       return ext_cmp_exten(left, right);
02700    }
02701    if (right[0] != '_') {
02702       return 1;
02703    }
02704 
02705    /*
02706     * OK, we need full pattern sorting routine.
02707     *
02708     * Skip past the underscores
02709     */
02710    return ext_cmp_pattern(left + 1, right + 1);
02711 }

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

Definition at line 2441 of file pbx.c.

Referenced by _extension_match_core(), and ext_cmp().

02442 {
02443    int cmp;
02444 
02445    for (;;) {
02446       /* Ignore '-' chars as eye candy fluff. */
02447       while (*left == '-') {
02448          ++left;
02449       }
02450       while (*right == '-') {
02451          ++right;
02452       }
02453 
02454       cmp = *left - *right;
02455       if (cmp) {
02456          break;
02457       }
02458       if (!*left) {
02459          /*
02460           * Get here only if both strings ended at the same time.  cmp
02461           * would be non-zero if only one string ended.
02462           */
02463          break;
02464       }
02465       ++left;
02466       ++right;
02467    }
02468    return cmp;
02469 }

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

Definition at line 2398 of file pbx.c.

Referenced by _extension_match_core().

02399 {
02400    int cmp;
02401 
02402    for (;;) {
02403       /* Ignore '-' chars as eye candy fluff. */
02404       while (*left == '-') {
02405          ++left;
02406       }
02407       while (*right == '-') {
02408          ++right;
02409       }
02410 
02411       if (!*right) {
02412          /*
02413           * Right ended first for partial match or both ended at the same
02414           * time for a match.
02415           */
02416          cmp = 0;
02417          break;
02418       }
02419 
02420       cmp = *left - *right;
02421       if (cmp) {
02422          break;
02423       }
02424       ++left;
02425       ++right;
02426    }
02427    return cmp;
02428 }

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

Definition at line 2368 of file pbx.c.

References len().

Referenced by _extension_match_core().

02369 {
02370    int len;
02371 
02372    len = 0;
02373    for (;;) {
02374       /* Ignore '-' chars as eye candy fluff. */
02375       while (*str == '-') {
02376          ++str;
02377       }
02378       if (!*str) {
02379          break;
02380       }
02381       ++str;
02382       ++len;
02383    }
02384    return len;
02385 }

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

Definition at line 2643 of file pbx.c.

References ARRAY_LEN, and ext_cmp_pattern_pos().

Referenced by _extension_match_core(), and ext_cmp().

02644 {
02645    int cmp;
02646    int left_pos;
02647    int right_pos;
02648 
02649    for (;;) {
02650       unsigned char left_bitwise[32] = { 0, };
02651       unsigned char right_bitwise[32] = { 0, };
02652 
02653       left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
02654       right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
02655       cmp = left_pos - right_pos;
02656       if (!cmp) {
02657          /*
02658           * Are the character sets different, even though they score the same?
02659           *
02660           * Note: Must swap left and right to get the sense of the
02661           * comparison correct.  Otherwise, we would need to multiply by
02662           * -1 instead.
02663           */
02664          cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
02665       }
02666       if (cmp) {
02667          break;
02668       }
02669       if (!left) {
02670          /*
02671           * Get here only if both patterns ended at the same time.  cmp
02672           * would be non-zero if only one pattern ended.
02673           */
02674          break;
02675       }
02676    }
02677    return cmp;
02678 }

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

References ast_log(), BITS_PER, and LOG_WARNING.

Referenced by ext_cmp_pattern().

02529 {
02530 #define BITS_PER  8  /* Number of bits per unit (byte). */
02531    unsigned char c;
02532    unsigned char cmin;
02533    int count;
02534    const char *end;
02535 
02536    do {
02537       /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
02538       do {
02539          c = *(*p)++;
02540       } while (c == '-');
02541 
02542       /* always return unless we have a set of chars */
02543       switch (c) {
02544       default:
02545          /* ordinary character */
02546          bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
02547          return 0x0100 | c;
02548 
02549       case 'n':
02550       case 'N':
02551          /* 2..9 */
02552          bitwise[6] = 0x3f;
02553          bitwise[7] = 0xc0;
02554          return 0x0800 | '2';
02555 
02556       case 'x':
02557       case 'X':
02558          /* 0..9 */
02559          bitwise[6] = 0xff;
02560          bitwise[7] = 0xc0;
02561          return 0x0A00 | '0';
02562 
02563       case 'z':
02564       case 'Z':
02565          /* 1..9 */
02566          bitwise[6] = 0x7f;
02567          bitwise[7] = 0xc0;
02568          return 0x0900 | '1';
02569 
02570       case '.':
02571          /* wildcard */
02572          return 0x18000;
02573 
02574       case '!':
02575          /* earlymatch */
02576          return 0x28000;   /* less specific than '.' */
02577 
02578       case '\0':
02579          /* empty string */
02580          *p = NULL;
02581          return 0x30000;
02582 
02583       case '[':
02584          /* char set */
02585          break;
02586       }
02587       /* locate end of set */
02588       end = strchr(*p, ']');
02589 
02590       if (!end) {
02591          ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02592          return 0x40000;   /* XXX make this entry go last... */
02593       }
02594 
02595       count = 0;
02596       cmin = 0xFF;
02597       for (; *p < end; ++*p) {
02598          unsigned char c1; /* first char in range */
02599          unsigned char c2; /* last char in range */
02600 
02601          c1 = (*p)[0];
02602          if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02603             c2 = (*p)[2];
02604             *p += 2;    /* skip a total of 3 chars */
02605          } else {        /* individual character */
02606             c2 = c1;
02607          }
02608          if (c1 < cmin) {
02609             cmin = c1;
02610          }
02611          for (; c1 <= c2; ++c1) {
02612             unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
02613 
02614             /*
02615              * Note: If two character sets score the same, the one with the
02616              * lowest ASCII values will compare as coming first.  Must fill
02617              * in most significant bits for lower ASCII values to accomplish
02618              * the desired sort order.
02619              */
02620             if (!(bitwise[c1 / BITS_PER] & mask)) {
02621                /* Add the character to the set. */
02622                bitwise[c1 / BITS_PER] |= mask;
02623                count += 0x100;
02624             }
02625          }
02626       }
02627       ++*p;
02628    } while (!count);/* While the char set was empty. */
02629    return count | cmin;
02630 }

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

copy a string skipping whitespace

Definition at line 8827 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

08828 {
08829    int count = 0;
08830    int insquares = 0;
08831 
08832    while (*src && (count < len - 1)) {
08833       if (*src == '[') {
08834          insquares = 1;
08835       } else if (*src == ']') {
08836          insquares = 0;
08837       } else if (*src == ' ' && !insquares) {
08838          src++;
08839          continue;
08840       }
08841       *dst = *src;
08842       dst++;
08843       src++;
08844       count++;
08845    }
08846    *dst = '\0';
08847 
08848    return count;
08849 }

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

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

02931 {
02932    int i;
02933    static int prof_id = -2;   /* marker for 'unallocated' id */
02934    if (prof_id == -2) {
02935       prof_id = ast_add_profile("ext_match", 0);
02936    }
02937    ast_mark(prof_id, 1);
02938    i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
02939    ast_mark(prof_id, 0);
02940    return i;
02941 }

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

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

05972 {
05973    struct fake_context item;
05974 
05975    ast_copy_string(item.name, context, sizeof(item.name));
05976 
05977    return ast_hashtab_lookup(contexts_table, &item);
05978 }

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

05986 {
05987    struct ast_context *c;
05988    struct fake_context item;
05989 
05990    ast_copy_string(item.name, context, sizeof(item.name));
05991 
05992    ast_rdlock_contexts();
05993    c = ast_hashtab_lookup(contexts_table, &item);
05994    if (!c) {
05995       ast_unlock_contexts();
05996    }
05997 
05998    return c;
05999 }

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

Remove a watcher from the callback list.

Definition at line 5142 of file pbx.c.

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

Referenced by ast_extension_state_del().

05143 {
05144    struct ast_state_cb *state_cb;
05145    const struct ast_hint *hint = obj;
05146    int *id = arg;
05147 
05148    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
05149       ao2_ref(state_cb, -1);
05150       return CMP_MATCH | CMP_STOP;
05151    }
05152 
05153    return 0;
05154 }

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

References args, ast_log(), and LOG_WARNING.

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

04042 {
04043    char *args = strchr(function, '(');
04044 
04045    if (!args) {
04046       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
04047    } else {
04048       char *p;
04049       *args++ = '\0';
04050       if ((p = strrchr(args, ')'))) {
04051          *p = '\0';
04052       } else {
04053          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
04054       }
04055    }
04056    return args;
04057 }

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

Definition at line 1729 of file pbx.c.

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

01730 {
01731    /* find the exten at the end of the rope */
01732    struct match_char *node2 = node;
01733 
01734    for (node2 = node; node2; node2 = node2->next_char) {
01735       if (node2->exten) {
01736 #ifdef NEED_DEBUG_HERE
01737          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01738 #endif
01739          return node2->exten;
01740       }
01741    }
01742 #ifdef NEED_DEBUG_HERE
01743    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01744 #endif
01745    return 0;
01746 }

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

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

02079 {
02080 #define INC_DST_OVERFLOW_CHECK                     \
02081    do {                                   \
02082       if (dst - node->buf < sizeof(node->buf) - 1) {  \
02083          ++dst;                              \
02084       } else {                            \
02085          overflow = 1;                       \
02086       }                                   \
02087    } while (0)
02088 
02089    node->specif = 0;
02090    node->buf[0] = '\0';
02091    while (*src) {
02092       if (*src == '[' && pattern) {
02093          char *dst = node->buf;
02094          const char *src_next;
02095          int length;
02096          int overflow = 0;
02097 
02098          /* get past the '[' */
02099          ++src;
02100          for (;;) {
02101             if (*src == '\\') {
02102                /* Escaped character. */
02103                ++src;
02104                if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
02105                   *dst = *src++;
02106                   INC_DST_OVERFLOW_CHECK;
02107                }
02108             } else if (*src == '-') {
02109                unsigned char first;
02110                unsigned char last;
02111 
02112                src_next = src;
02113                first = *(src_next - 1);
02114                last = *++src_next;
02115 
02116                if (last == '\\') {
02117                   /* Escaped character. */
02118                   last = *++src_next;
02119                }
02120 
02121                /* Possible char range. */
02122                if (node->buf[0] && last) {
02123                   /* Expand the char range. */
02124                   while (++first <= last) {
02125                      *dst = first;
02126                      INC_DST_OVERFLOW_CHECK;
02127                   }
02128                   src = src_next + 1;
02129                } else {
02130                   /*
02131                    * There was no left or right char for the range.
02132                    * It is just a '-'.
02133                    */
02134                   *dst = *src++;
02135                   INC_DST_OVERFLOW_CHECK;
02136                }
02137             } else if (*src == '\0') {
02138                ast_log(LOG_WARNING,
02139                   "A matching ']' was not found for '[' in exten pattern '%s'\n",
02140                   extenbuf);
02141                break;
02142             } else if (*src == ']') {
02143                ++src;
02144                break;
02145             } else {
02146                *dst = *src++;
02147                INC_DST_OVERFLOW_CHECK;
02148             }
02149          }
02150          /* null terminate the exploded range */
02151          *dst = '\0';
02152 
02153          if (overflow) {
02154             ast_log(LOG_ERROR,
02155                "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
02156                extenbuf);
02157             node->buf[0] = '\0';
02158             continue;
02159          }
02160 
02161          /* Sort the characters in character set. */
02162          length = strlen(node->buf);
02163          if (!length) {
02164             ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
02165                extenbuf);
02166             node->buf[0] = '\0';
02167             continue;
02168          }
02169          qsort(node->buf, length, 1, compare_char);
02170 
02171          /* Remove duplicate characters from character set. */
02172          dst = node->buf;
02173          src_next = node->buf;
02174          while (*src_next++) {
02175             if (*dst != *src_next) {
02176                *++dst = *src_next;
02177             }
02178          }
02179 
02180          length = strlen(node->buf);
02181          length <<= 8;
02182          node->specif = length | (unsigned char) node->buf[0];
02183          break;
02184       } else if (*src == '-') {
02185          /* Skip dashes in all extensions. */
02186          ++src;
02187       } else {
02188          if (*src == '\\') {
02189             /*
02190              * XXX The escape character here does not remove any special
02191              * meaning to characters except the '[', '\\', and '-'
02192              * characters since they are special only in this function.
02193              */
02194             node->buf[0] = *++src;
02195             if (!node->buf[0]) {
02196                break;
02197             }
02198          } else {
02199             node->buf[0] = *src;
02200             if (pattern) {
02201                /* make sure n,x,z patterns are canonicalized to N,X,Z */
02202                if (node->buf[0] == 'n') {
02203                   node->buf[0] = 'N';
02204                } else if (node->buf[0] == 'x') {
02205                   node->buf[0] = 'X';
02206                } else if (node->buf[0] == 'z') {
02207                   node->buf[0] = 'Z';
02208                }
02209             }
02210          }
02211          node->buf[1] = '\0';
02212          node->specif = 1;
02213          ++src;
02214          break;
02215       }
02216    }
02217    return src;
02218 
02219 #undef INC_DST_OVERFLOW_CHECK
02220 }

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

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

Referenced by ast_build_timing().

08183 {
08184    int start, end; /* start and ending position */
08185    unsigned int mask = 0;
08186    char *part;
08187 
08188    /* Check for whole range */
08189    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
08190       return (1 << max) - 1;
08191    }
08192 
08193    while ((part = strsep(&src, "&"))) {
08194       /* Get start and ending position */
08195       char *endpart = strchr(part, '-');
08196       if (endpart) {
08197          *endpart++ = '\0';
08198       }
08199       /* Find the start */
08200       if ((start = lookup_name(part, names, max)) < 0) {
08201          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
08202          continue;
08203       }
08204       if (endpart) { /* find end of range */
08205          if ((end = lookup_name(endpart, names, max)) < 0) {
08206             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
08207             continue;
08208          }
08209       } else {
08210          end = start;
08211       }
08212       /* Fill the mask. Remember that ranges are cyclic */
08213       mask |= (1 << end);   /* initialize with last element */
08214       while (start != end) {
08215          mask |= (1 << start);
08216          if (++start >= max) {
08217             start = 0;
08218          }
08219       }
08220    }
08221    return mask;
08222 }

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

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

Referenced by ast_build_timing().

08226 {
08227    char *endpart, *part;
08228    int x;
08229    int st_h, st_m;
08230    int endh, endm;
08231    int minute_start, minute_end;
08232 
08233    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
08234    memset(i->minmask, 0, sizeof(i->minmask));
08235 
08236    /* 1-minute per bit */
08237    /* Star is all times */
08238    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
08239       /* 48, because each hour takes 2 integers; 30 bits each */
08240       for (x = 0; x < 48; x++) {
08241          i->minmask[x] = 0x3fffffff; /* 30 bits */
08242       }
08243       return;
08244    }
08245    /* Otherwise expect a range */
08246    while ((part = strsep(&times, "&"))) {
08247       if (!(endpart = strchr(part, '-'))) {
08248          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
08249             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
08250             continue;
08251          }
08252          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
08253          continue;
08254       }
08255       *endpart++ = '\0';
08256       /* why skip non digits? Mostly to skip spaces */
08257       while (*endpart && !isdigit(*endpart)) {
08258          endpart++;
08259       }
08260       if (!*endpart) {
08261          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
08262          continue;
08263       }
08264       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
08265          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
08266          continue;
08267       }
08268       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
08269          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
08270          continue;
08271       }
08272       minute_start = st_h * 60 + st_m;
08273       minute_end = endh * 60 + endm;
08274       /* Go through the time and enable each appropriate bit */
08275       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
08276          i->minmask[x / 30] |= (1 << (x % 30));
08277       }
08278       /* Do the last one */
08279       i->minmask[x / 30] |= (1 << (x % 30));
08280    }
08281    /* All done */
08282    return;
08283 }

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

Send ack once.

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

07197 {
07198    char *exten = NULL, *context = NULL;
07199    /* Variables used for different counters */
07200    struct dialplan_counters counters;
07201    const char *incstack[AST_PBX_MAX_STACK];
07202 
07203    switch (cmd) {
07204    case CLI_INIT:
07205       e->command = "dialplan debug";
07206       e->usage =
07207          "Usage: dialplan debug [context]\n"
07208          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
07209       return NULL;
07210    case CLI_GENERATE:
07211       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
07212    }
07213 
07214    memset(&counters, 0, sizeof(counters));
07215 
07216    if (a->argc != 2 && a->argc != 3)
07217       return CLI_SHOWUSAGE;
07218 
07219    /* we obtain [exten@]context? if yes, split them ... */
07220    /* note: we ignore the exten totally here .... */
07221    if (a->argc == 3) {
07222       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
07223          context = ast_strdupa(a->argv[2]);
07224          exten = strsep(&context, "@");
07225          /* change empty strings to NULL */
07226          if (ast_strlen_zero(exten))
07227             exten = NULL;
07228       } else { /* no '@' char, only context given */
07229          context = ast_strdupa(a->argv[2]);
07230       }
07231       if (ast_strlen_zero(context))
07232          context = NULL;
07233    }
07234    /* else Show complete dial plan, context and exten are NULL */
07235    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
07236 
07237    /* check for input failure and throw some error messages */
07238    if (context && !counters.context_existence) {
07239       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
07240       return CLI_FAILURE;
07241    }
07242 
07243 
07244    ast_cli(a->fd,"-= %d %s. =-\n",
07245          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
07246 
07247    /* everything ok */
07248    return CLI_SUCCESS;
07249 }

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

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

07570 {
07571    struct ast_channel *chan;
07572    const char *chan_name, *var_name, *var_value;
07573 
07574    switch (cmd) {
07575    case CLI_INIT:
07576       e->command = "dialplan set chanvar";
07577       e->usage =
07578          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
07579          "       Set channel variable <varname> to <value>\n";
07580       return NULL;
07581    case CLI_GENERATE:
07582       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07583    }
07584 
07585    if (a->argc != e->args + 3)
07586       return CLI_SHOWUSAGE;
07587 
07588    chan_name = a->argv[e->args];
07589    var_name = a->argv[e->args + 1];
07590    var_value = a->argv[e->args + 2];
07591 
07592    if (!(chan = ast_channel_get_by_name(chan_name))) {
07593       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
07594       return CLI_FAILURE;
07595    }
07596 
07597    pbx_builtin_setvar_helper(chan, var_name, var_value);
07598 
07599    chan = ast_channel_unref(chan);
07600 
07601    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
07602 
07603    return CLI_SUCCESS;
07604 }

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

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

07607 {
07608    int oldval = 0;
07609 
07610    switch (cmd) {
07611    case CLI_INIT:
07612       e->command = "dialplan set extenpatternmatchnew true";
07613       e->usage =
07614          "Usage: dialplan set extenpatternmatchnew true|false\n"
07615          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07616       return NULL;
07617    case CLI_GENERATE:
07618       return NULL;
07619    }
07620 
07621    if (a->argc != 4)
07622       return CLI_SHOWUSAGE;
07623 
07624    oldval =  pbx_set_extenpatternmatchnew(1);
07625 
07626    if (oldval)
07627       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
07628    else
07629       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
07630 
07631    return CLI_SUCCESS;
07632 }

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

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

07548 {
07549    switch (cmd) {
07550    case CLI_INIT:
07551       e->command = "dialplan set global";
07552       e->usage =
07553          "Usage: dialplan set global <name> <value>\n"
07554          "       Set global dialplan variable <name> to <value>\n";
07555       return NULL;
07556    case CLI_GENERATE:
07557       return NULL;
07558    }
07559 
07560    if (a->argc != e->args + 2)
07561       return CLI_SHOWUSAGE;
07562 
07563    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
07564    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
07565 
07566    return CLI_SUCCESS;
07567 }

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

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

06544 {
06545    struct ast_app *aa;
06546    int app, no_registered_app = 1;
06547 
06548    switch (cmd) {
06549    case CLI_INIT:
06550       e->command = "core show application";
06551       e->usage =
06552          "Usage: core show application <application> [<application> [<application> [...]]]\n"
06553          "       Describes a particular application.\n";
06554       return NULL;
06555    case CLI_GENERATE:
06556       /*
06557        * There is a possibility to show informations about more than one
06558        * application at one time. You can type 'show application Dial Echo' and
06559        * you will see informations about these two applications ...
06560        */
06561       return ast_complete_applications(a->line, a->word, a->n);
06562    }
06563 
06564    if (a->argc < 4) {
06565       return CLI_SHOWUSAGE;
06566    }
06567 
06568    AST_RWLIST_RDLOCK(&apps);
06569    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06570       /* Check for each app that was supplied as an argument */
06571       for (app = 3; app < a->argc; app++) {
06572          if (strcasecmp(aa->name, a->argv[app])) {
06573             continue;
06574          }
06575 
06576          /* We found it! */
06577          no_registered_app = 0;
06578 
06579          print_app_docs(aa, a->fd);
06580       }
06581    }
06582    AST_RWLIST_UNLOCK(&apps);
06583 
06584    /* we found at least one app? no? */
06585    if (no_registered_app) {
06586       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
06587       return CLI_FAILURE;
06588    }
06589 
06590    return CLI_SUCCESS;
06591 }

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

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

06780 {
06781    struct ast_app *aa;
06782    int like = 0, describing = 0;
06783    int total_match = 0;    /* Number of matches in like clause */
06784    int total_apps = 0;     /* Number of apps registered */
06785    static const char * const choices[] = { "like", "describing", NULL };
06786 
06787    switch (cmd) {
06788    case CLI_INIT:
06789       e->command = "core show applications [like|describing]";
06790       e->usage =
06791          "Usage: core show applications [{like|describing} <text>]\n"
06792          "       List applications which are currently available.\n"
06793          "       If 'like', <text> will be a substring of the app name\n"
06794          "       If 'describing', <text> will be a substring of the description\n";
06795       return NULL;
06796    case CLI_GENERATE:
06797       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
06798    }
06799 
06800    AST_RWLIST_RDLOCK(&apps);
06801 
06802    if (AST_RWLIST_EMPTY(&apps)) {
06803       ast_cli(a->fd, "There are no registered applications\n");
06804       AST_RWLIST_UNLOCK(&apps);
06805       return CLI_SUCCESS;
06806    }
06807 
06808    /* core list applications like <keyword> */
06809    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
06810       like = 1;
06811    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
06812       describing = 1;
06813    }
06814 
06815    /* core list applications describing <keyword1> [<keyword2>] [...] */
06816    if ((!like) && (!describing)) {
06817       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
06818    } else {
06819       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
06820    }
06821 
06822    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06823       int printapp = 0;
06824       total_apps++;
06825       if (like) {
06826          if (strcasestr(aa->name, a->argv[4])) {
06827             printapp = 1;
06828             total_match++;
06829          }
06830       } else if (describing) {
06831          if (aa->description) {
06832             /* Match all words on command line */
06833             int i;
06834             printapp = 1;
06835             for (i = 4; i < a->argc; i++) {
06836                if (!strcasestr(aa->description, a->argv[i])) {
06837                   printapp = 0;
06838                } else {
06839                   total_match++;
06840                }
06841             }
06842          }
06843       } else {
06844          printapp = 1;
06845       }
06846 
06847       if (printapp) {
06848          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
06849       }
06850    }
06851    if ((!like) && (!describing)) {
06852       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
06853    } else {
06854       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
06855    }
06856 
06857    AST_RWLIST_UNLOCK(&apps);
06858 
06859    return CLI_SUCCESS;
06860 }

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

07513 {
07514    struct ast_channel *chan = NULL;
07515    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
07516 
07517    switch (cmd) {
07518    case CLI_INIT:
07519       e->command = "dialplan show chanvar";
07520       e->usage =
07521          "Usage: dialplan show chanvar <channel>\n"
07522          "       List current channel variables and their values\n";
07523       return NULL;
07524    case CLI_GENERATE:
07525       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07526    }
07527 
07528    if (a->argc != e->args + 1)
07529       return CLI_SHOWUSAGE;
07530 
07531    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
07532       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
07533       return CLI_FAILURE;
07534    }
07535 
07536    pbx_builtin_serialize_variables(chan, &vars);
07537 
07538    if (ast_str_strlen(vars)) {
07539       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
07540    }
07541 
07542    chan = ast_channel_unref(chan);
07543 
07544    return CLI_SUCCESS;
07545 }

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

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

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

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

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

03694 {
03695    struct ast_custom_function *acf;
03696    /* Maximum number of characters added by terminal coloring is 22 */
03697    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03698    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03699    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03700    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03701    char *ret = NULL;
03702    int which = 0;
03703    int wordlen;
03704 
03705    switch (cmd) {
03706    case CLI_INIT:
03707       e->command = "core show function";
03708       e->usage =
03709          "Usage: core show function <function>\n"
03710          "       Describe a particular dialplan function.\n";
03711       return NULL;
03712    case CLI_GENERATE:
03713       wordlen = strlen(a->word);
03714       /* case-insensitive for convenience in this 'complete' function */
03715       AST_RWLIST_RDLOCK(&acf_root);
03716       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03717          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03718             ret = ast_strdup(acf->name);
03719             break;
03720          }
03721       }
03722       AST_RWLIST_UNLOCK(&acf_root);
03723 
03724       return ret;
03725    }
03726 
03727    if (a->argc < 4) {
03728       return CLI_SHOWUSAGE;
03729    }
03730 
03731    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03732       ast_cli(a->fd, "No function by that name registered.\n");
03733       return CLI_FAILURE;
03734    }
03735 
03736    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03737    if (!(syntax = ast_malloc(syntax_size))) {
03738       ast_cli(a->fd, "Memory allocation failure!\n");
03739       return CLI_FAILURE;
03740    }
03741 
03742    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03743    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03744    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03745    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03746    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03747    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03748    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03749    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03750 #ifdef AST_XML_DOCS
03751    if (acf->docsrc == AST_XML_DOC) {
03752       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03753       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03754       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03755       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03756    } else
03757 #endif
03758    {
03759       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03760       synopsis = ast_malloc(synopsis_size);
03761 
03762       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03763       description = ast_malloc(description_size);
03764 
03765       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03766       arguments = ast_malloc(arguments_size);
03767 
03768       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03769       seealso = ast_malloc(seealso_size);
03770 
03771       /* check allocated memory. */
03772       if (!synopsis || !description || !arguments || !seealso) {
03773          ast_free(synopsis);
03774          ast_free(description);
03775          ast_free(arguments);
03776          ast_free(seealso);
03777          ast_free(syntax);
03778          return CLI_FAILURE;
03779       }
03780 
03781       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03782       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03783       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03784       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03785    }
03786 
03787    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03788          infotitle, syntitle, synopsis, destitle, description,
03789          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03790 
03791    ast_free(arguments);
03792    ast_free(synopsis);
03793    ast_free(description);
03794    ast_free(seealso);
03795    ast_free(syntax);
03796 
03797    return CLI_SUCCESS;
03798 }

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

Definition at line 3651 of file pbx.c.

References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_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.

03652 {
03653    struct ast_custom_function *acf;
03654    int count_acf = 0;
03655    int like = 0;
03656 
03657    switch (cmd) {
03658    case CLI_INIT:
03659       e->command = "core show functions [like]";
03660       e->usage =
03661          "Usage: core show functions [like <text>]\n"
03662          "       List builtin functions, optionally only those matching a given string\n";
03663       return NULL;
03664    case CLI_GENERATE:
03665       return NULL;
03666    }
03667 
03668    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03669       like = 1;
03670    } else if (a->argc != 3) {
03671       return CLI_SHOWUSAGE;
03672    }
03673 
03674    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03675 
03676    AST_RWLIST_RDLOCK(&acf_root);
03677    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03678       if (!like || strstr(acf->name, a->argv[4])) {
03679          count_acf++;
03680          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03681             S_OR(acf->name, ""),
03682             S_OR(acf->syntax, ""),
03683             S_OR(acf->synopsis, ""));
03684       }
03685    }
03686    AST_RWLIST_UNLOCK(&acf_root);
03687 
03688    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03689 
03690    return CLI_SUCCESS;
03691 }

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

07455 {
07456    int i = 0;
07457    struct ast_var_t *newvariable;
07458 
07459    switch (cmd) {
07460    case CLI_INIT:
07461       e->command = "dialplan show globals";
07462       e->usage =
07463          "Usage: dialplan show globals\n"
07464          "       List current global dialplan variables and their values\n";
07465       return NULL;
07466    case CLI_GENERATE:
07467       return NULL;
07468    }
07469 
07470    ast_rwlock_rdlock(&globalslock);
07471    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
07472       i++;
07473       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
07474    }
07475    ast_rwlock_unlock(&globalslock);
07476    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
07477 
07478    return CLI_SUCCESS;
07479 }

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

06686 {
06687    struct ast_hint *hint;
06688    int watchers;
06689    int num = 0, extenlen;
06690    struct ao2_iterator i;
06691 
06692    switch (cmd) {
06693    case CLI_INIT:
06694       e->command = "core show hint";
06695       e->usage =
06696          "Usage: core show hint <exten>\n"
06697          "       List registered hint.\n"
06698          "       Hint details are shown in four columns. In order from left to right, they are:\n"
06699          "       1. Hint extension URI.\n"
06700          "       2. Mapped device state identifiers.\n"
06701          "       3. Current extension state. The aggregate of mapped device states.\n"
06702          "       4. Watchers - number of subscriptions and other entities watching this hint.\n";
06703 
06704       return NULL;
06705    case CLI_GENERATE:
06706       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
06707    }
06708 
06709    if (a->argc < 4)
06710       return CLI_SHOWUSAGE;
06711 
06712    if (ao2_container_count(hints) == 0) {
06713       ast_cli(a->fd, "There are no registered dialplan hints\n");
06714       return CLI_SUCCESS;
06715    }
06716    
06717    extenlen = strlen(a->argv[3]);
06718    i = ao2_iterator_init(hints, 0);
06719    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06720       ao2_lock(hint);
06721       if (!hint->exten) {
06722          /* The extension has already been destroyed */
06723          ao2_unlock(hint);
06724          continue;
06725       }
06726       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
06727          watchers = ao2_container_count(hint->callbacks);
06728          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06729             ast_get_extension_name(hint->exten),
06730             ast_get_context_name(ast_get_extension_context(hint->exten)),
06731             ast_get_extension_app(hint->exten),
06732             ast_extension_state2str(hint->laststate), watchers);
06733          num++;
06734       }
06735       ao2_unlock(hint);
06736    }
06737    ao2_iterator_destroy(&i);
06738    if (!num)
06739       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
06740    else
06741       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
06742    return CLI_SUCCESS;
06743 }

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

06595 {
06596    struct ast_hint *hint;
06597    int num = 0;
06598    int watchers;
06599    struct ao2_iterator i;
06600 
06601    switch (cmd) {
06602    case CLI_INIT:
06603       e->command = "core show hints";
06604       e->usage =
06605          "Usage: core show hints\n"
06606          "       List registered hints.\n"
06607          "       Hint details are shown in four columns. In order from left to right, they are:\n"
06608          "       1. Hint extension URI.\n"
06609          "       2. Mapped device state identifiers.\n"
06610          "       3. Current extension state. The aggregate of mapped device states.\n"
06611          "       4. Watchers - number of subscriptions and other entities watching this hint.\n";
06612       return NULL;
06613    case CLI_GENERATE:
06614       return NULL;
06615    }
06616 
06617    if (ao2_container_count(hints) == 0) {
06618       ast_cli(a->fd, "There are no registered dialplan hints\n");
06619       return CLI_SUCCESS;
06620    }
06621    /* ... we have hints ... */
06622    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
06623 
06624    i = ao2_iterator_init(hints, 0);
06625    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06626       ao2_lock(hint);
06627       if (!hint->exten) {
06628          /* The extension has already been destroyed */
06629          ao2_unlock(hint);
06630          continue;
06631       }
06632       watchers = ao2_container_count(hint->callbacks);
06633       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06634          ast_get_extension_name(hint->exten),
06635          ast_get_context_name(ast_get_extension_context(hint->exten)),
06636          ast_get_extension_app(hint->exten),
06637          ast_extension_state2str(hint->laststate), watchers);
06638       ao2_unlock(hint);
06639       num++;
06640    }
06641    ao2_iterator_destroy(&i);
06642 
06643    ast_cli(a->fd, "----------------\n");
06644    ast_cli(a->fd, "- %d hints registered\n", num);
06645    return CLI_SUCCESS;
06646 }

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

06748 {
06749    struct ast_switch *sw;
06750 
06751    switch (cmd) {
06752    case CLI_INIT:
06753       e->command = "core show switches";
06754       e->usage =
06755          "Usage: core show switches\n"
06756          "       List registered switches\n";
06757       return NULL;
06758    case CLI_GENERATE:
06759       return NULL;
06760    }
06761 
06762    AST_RWLIST_RDLOCK(&switches);
06763 
06764    if (AST_RWLIST_EMPTY(&switches)) {
06765       AST_RWLIST_UNLOCK(&switches);
06766       ast_cli(a->fd, "There are no registered alternative switches\n");
06767       return CLI_SUCCESS;
06768    }
06769 
06770    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
06771    AST_RWLIST_TRAVERSE(&switches, sw, list)
06772       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
06773 
06774    AST_RWLIST_UNLOCK(&switches);
06775 
06776    return CLI_SUCCESS;
06777 }

static int handle_statechange ( void *  datap  )  [static]

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

04937 {
04938    struct ast_hint *hint;
04939    struct ast_str *hint_app;
04940    struct statechange *sc = datap;
04941    struct ao2_iterator i;
04942    struct ao2_iterator cb_iter;
04943    char context_name[AST_MAX_CONTEXT];
04944    char exten_name[AST_MAX_EXTENSION];
04945 
04946    hint_app = ast_str_create(1024);
04947    if (!hint_app) {
04948       ast_free(sc);
04949       return -1;
04950    }
04951 
04952    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
04953    i = ao2_iterator_init(hints, 0);
04954    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
04955       struct ast_state_cb *state_cb;
04956       char *cur, *parse;
04957       int state;
04958 
04959       ao2_lock(hint);
04960       if (!hint->exten) {
04961          /* The extension has already been destroyed */
04962          ao2_unlock(hint);
04963          continue;
04964       }
04965 
04966       /* Does this hint monitor the device that changed state? */
04967       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04968       parse = ast_str_buffer(hint_app);
04969       while ((cur = strsep(&parse, "&"))) {
04970          if (!strcasecmp(cur, sc->dev)) {
04971             /* The hint monitors the device. */
04972             break;
04973          }
04974       }
04975       if (!cur) {
04976          /* The hint does not monitor the device. */
04977          ao2_unlock(hint);
04978          continue;
04979       }
04980 
04981       /*
04982        * Save off strings in case the hint extension gets destroyed
04983        * while we are notifying the watchers.
04984        */
04985       ast_copy_string(context_name,
04986          ast_get_context_name(ast_get_extension_context(hint->exten)),
04987          sizeof(context_name));
04988       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
04989          sizeof(exten_name));
04990       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04991       ao2_unlock(hint);
04992 
04993       /*
04994        * Get device state for this hint.
04995        *
04996        * NOTE: We cannot hold any locks while determining the hint
04997        * device state or notifying the watchers without causing a
04998        * deadlock.  (conlock, hints, and hint)
04999        */
05000       state = ast_extension_state3(hint_app);
05001       if (state == hint->laststate) {
05002          continue;
05003       }
05004 
05005       /* Device state changed since last check - notify the watchers. */
05006       hint->laststate = state;   /* record we saw the change */
05007 
05008       /* For general callbacks */
05009       cb_iter = ao2_iterator_init(statecbs, 0);
05010       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05011          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
05012       }
05013       ao2_iterator_destroy(&cb_iter);
05014 
05015       /* For extension callbacks */
05016       cb_iter = ao2_iterator_init(hint->callbacks, 0);
05017       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05018          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
05019       }
05020       ao2_iterator_destroy(&cb_iter);
05021    }
05022    ao2_iterator_destroy(&i);
05023    ast_mutex_unlock(&context_merge_lock);
05024 
05025    ast_free(hint_app);
05026    ast_free(sc);
05027    return 0;
05028 }

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

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

07635 {
07636    int oldval = 0;
07637 
07638    switch (cmd) {
07639    case CLI_INIT:
07640       e->command = "dialplan set extenpatternmatchnew false";
07641       e->usage =
07642          "Usage: dialplan set extenpatternmatchnew true|false\n"
07643          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07644       return NULL;
07645    case CLI_GENERATE:
07646       return NULL;
07647    }
07648 
07649    if (a->argc != 4)
07650       return CLI_SHOWUSAGE;
07651 
07652    oldval =  pbx_set_extenpatternmatchnew(0);
07653 
07654    if (!oldval)
07655       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
07656    else
07657       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
07658 
07659    return CLI_SUCCESS;
07660 }

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

Definition at line 1181 of file pbx.c.

References ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

01182 {
01183    const struct ast_exten *ac = ah_a;
01184    const struct ast_exten *bc = ah_b;
01185    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01186 }

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

Definition at line 1174 of file pbx.c.

References ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01175 {
01176    const struct ast_exten *ac = ah_a;
01177    const struct ast_exten *bc = ah_b;
01178    return ac->priority != bc->priority;
01179 }

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

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

01147 {
01148    const struct ast_exten *ac = ah_a;
01149    const struct ast_exten *bc = ah_b;
01150    int x = strcmp(ac->exten, bc->exten);
01151    if (x) { /* if exten names are diff, then return */
01152       return x;
01153    }
01154 
01155    /* but if they are the same, do the cidmatch values match? */
01156    /* not sure which side may be using ast_ext_matchcid_types, so check both */
01157    if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) {
01158       return 0;
01159    }
01160    if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) {
01161       return 0;
01162    }
01163    if (ac->matchcid != bc->matchcid) {
01164       return 1;
01165    }
01166    /* all other cases already disposed of, match now required on callerid string (cidmatch) */
01167    /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
01168    if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) {
01169       return 0;
01170    }
01171    return strcmp(ac->cidmatch, bc->cidmatch);
01172 }

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

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

01195 {
01196    const struct ast_exten *ac = obj;
01197    unsigned int x = ast_hashtab_hash_string(ac->exten);
01198    unsigned int y = 0;
01199    if (ac->matchcid == AST_EXT_MATCHCID_ON)
01200       y = ast_hashtab_hash_string(ac->cidmatch);
01201    return x+y;
01202 }

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

Definition at line 1210 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01211 {
01212    const struct ast_exten *ac = obj;
01213    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01214 }

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

Definition at line 1204 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01205 {
01206    const struct ast_exten *ac = obj;
01207    return ast_hashtab_hash_int(ac->priority);
01208 }

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

Definition at line 11375 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_hint::exten.

Referenced by ast_pbx_init().

11376 {
11377    const struct ast_hint *hint = obj;
11378    const struct ast_exten *exten = arg;
11379 
11380    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
11381 }

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

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

11356 {
11357    const struct ast_hint *hint = obj;
11358    const char *exten_name;
11359    int res;
11360 
11361    exten_name = ast_get_extension_name(hint->exten);
11362    if (ast_strlen_zero(exten_name)) {
11363       /*
11364        * If the exten or extension name isn't set, return 0 so that
11365        * the ao2_find() search will start in the first bucket.
11366        */
11367       res = 0;
11368    } else {
11369       res = ast_str_case_hash(exten_name);
11370    }
11371 
11372    return res;
11373 }

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

Definition at line 5191 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

05192 {
05193    const struct ast_state_cb *cb = obj;
05194    int *id = arg;
05195 
05196    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
05197 }

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

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

10930 {
10931    struct ast_data *data_hint;
10932    struct ast_hint *hint;
10933    int watchers;
10934    struct ao2_iterator i;
10935 
10936    if (ao2_container_count(hints) == 0) {
10937       return 0;
10938    }
10939 
10940    i = ao2_iterator_init(hints, 0);
10941    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
10942       watchers = ao2_container_count(hint->callbacks);
10943       data_hint = ast_data_add_node(data_root, "hint");
10944       if (!data_hint) {
10945          continue;
10946       }
10947       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
10948       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
10949       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
10950       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
10951       ast_data_add_int(data_hint, "watchers", watchers);
10952 
10953       if (!ast_data_search_match(search, data_hint)) {
10954          ast_data_remove_node(data_root, data_hint);
10955       }
10956    }
10957    ao2_iterator_destroy(&i);
10958 
10959    return 0;
10960 }

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

Definition at line 1565 of file pbx.c.

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

Referenced by pbx_find_extension().

01566 {
01567    if (!i->hastime)
01568       return 1;
01569 
01570    return ast_check_timing(&(i->timing));
01571 }

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

05791 {
05792    int failed = 0;
05793    double curloadavg;
05794 #if defined(HAVE_SYSINFO)
05795    long curfreemem;
05796    struct sysinfo sys_info;
05797 #endif
05798 
05799    ast_mutex_lock(&maxcalllock);
05800    if (option_maxcalls) {
05801       if (countcalls >= option_maxcalls) {
05802          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
05803          failed = -1;
05804       }
05805    }
05806    if (option_maxload) {
05807       getloadavg(&curloadavg, 1);
05808       if (curloadavg >= option_maxload) {
05809          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
05810          failed = -1;
05811       }
05812    }
05813 #if defined(HAVE_SYSINFO)
05814    if (option_minmemfree) {
05815       if (!sysinfo(&sys_info)) {
05816          /* make sure that the free system memory is above the configured low watermark
05817           * convert the amount of freeram from mem_units to MB */
05818          curfreemem = sys_info.freeram * sys_info.mem_unit;
05819          curfreemem /= 1024 * 1024;
05820          if (curfreemem < option_minmemfree) {
05821             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
05822             failed = -1;
05823          }
05824       }
05825    }
05826 #endif
05827 
05828    if (!failed) {
05829       countcalls++;
05830       totalcalls++;
05831    }
05832    ast_mutex_unlock(&maxcalllock);
05833 
05834    return failed;
05835 }

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

Definition at line 1983 of file pbx.c.

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

Referenced by add_pattern_node().

01984 {
01985    struct match_char *curr, *lcurr;
01986 
01987    /* insert node into the tree at "current", so the alt_char list from current is
01988       sorted in increasing value as you go to the leaves */
01989    if (!(*parent_ptr)) {
01990       *parent_ptr = node;
01991       return;
01992    }
01993 
01994    if ((*parent_ptr)->specificity > node->specificity) {
01995       /* insert at head */
01996       node->alt_char = (*parent_ptr);
01997       *parent_ptr = node;
01998       return;
01999    } 
02000 
02001    lcurr = *parent_ptr;
02002    for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
02003       if (curr->specificity > node->specificity) {
02004          node->alt_char = curr;
02005          lcurr->alt_char = node;
02006          break;
02007       }
02008       lcurr = curr;
02009    }
02010 
02011    if (!curr) {
02012       lcurr->alt_char = node;
02013    }
02014 
02015 }

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

04120 {
04121    if (!acfptr) {
04122       return 1;
04123    }
04124 
04125    if (!read_escalates(acfptr)) {
04126       return 1;
04127    }
04128 
04129    if (!thread_inhibits_escalations()) {
04130       return 1;
04131    }
04132 
04133    if (live_dangerously) {
04134       /* Global setting overrides the thread's preference */
04135       ast_debug(2, "Reading %s from a dangerous context\n",
04136          acfptr->name);
04137       return 1;
04138    }
04139 
04140    /* We have no reason to allow this function to execute */
04141    return 0;
04142 }

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

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

Referenced by ast_func_write().

04153 {
04154    if (!acfptr) {
04155       return 1;
04156    }
04157 
04158    if (!write_escalates(acfptr)) {
04159       return 1;
04160    }
04161 
04162    if (!thread_inhibits_escalations()) {
04163       return 1;
04164    }
04165 
04166    if (live_dangerously) {
04167       /* Global setting overrides the thread's preference */
04168       ast_debug(2, "Writing %s from a dangerous context\n",
04169          acfptr->name);
04170       return 1;
04171    }
04172 
04173    /* We have no reason to allow this function to execute */
04174    return 0;
04175 }

int load_pbx ( void   ) 

Provided by pbx.c

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

10997 {
10998    int x;
10999 
11000    ast_register_atexit(unload_pbx);
11001 
11002    /* Initialize the PBX */
11003    ast_verb(1, "Asterisk PBX Core Initializing\n");
11004    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
11005       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
11006    }
11007 
11008    ast_verb(1, "Registering builtin applications:\n");
11009    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
11010    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
11011    __ast_custom_function_register(&exception_function, NULL);
11012    __ast_custom_function_register(&testtime_function, NULL);
11013 
11014    /* Register builtin applications */
11015    for (x = 0; x < ARRAY_LEN(builtins); x++) {
11016       ast_verb(1, "[%s]\n", builtins[x].name);
11017       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
11018          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
11019          return -1;
11020       }
11021    }
11022 
11023    /* Register manager application */
11024    ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
11025 
11026    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
11027          AST_EVENT_IE_END))) {
11028       return -1;
11029    }
11030 
11031    return 0;
11032 }

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

Referenced by get_range().

08160 {
08161    int i;
08162 
08163    if (names && *s > '9') {
08164       for (i = 0; names[i]; i++) {
08165          if (!strcasecmp(s, names[i])) {
08166             return i;
08167          }
08168       }
08169    }
08170 
08171    /* Allow months and weekdays to be specified as numbers, as well */
08172    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
08173       /* What the array offset would have been: "1" would be at offset 0 */
08174       return i - 1;
08175    }
08176    return -1; /* error return */
08177 }

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

Send ack once.

Definition at line 7252 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

07253 {
07254    astman_send_listack(s, m, "DialPlan list will follow", "start");
07255 }

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

Manager listing of dial plan.

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

07398 {
07399    const char *exten, *context;
07400    const char *id = astman_get_header(m, "ActionID");
07401    char idtext[256];
07402 
07403    /* Variables used for different counters */
07404    struct dialplan_counters counters;
07405 
07406    if (!ast_strlen_zero(id))
07407       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
07408    else
07409       idtext[0] = '\0';
07410 
07411    memset(&counters, 0, sizeof(counters));
07412 
07413    exten = astman_get_header(m, "Extension");
07414    context = astman_get_header(m, "Context");
07415 
07416    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
07417 
07418    if (!ast_strlen_zero(context) && !counters.context_existence) {
07419       char errorbuf[BUFSIZ];
07420 
07421       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
07422       astman_send_error(s, m, errorbuf);
07423       return 0;
07424    }
07425    if (!ast_strlen_zero(exten) && !counters.extension_existence) {
07426       char errorbuf[BUFSIZ];
07427 
07428       if (!ast_strlen_zero(context))
07429          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
07430       else
07431          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
07432       astman_send_error(s, m, errorbuf);
07433       return 0;
07434    }
07435 
07436    if (!counters.total_items) {
07437       manager_dpsendack(s, m);
07438    }
07439 
07440    astman_append(s, "Event: ShowDialPlanComplete\r\n"
07441       "EventList: Complete\r\n"
07442       "ListItems: %d\r\n"
07443       "ListExtensions: %d\r\n"
07444       "ListPriorities: %d\r\n"
07445       "ListContexts: %d\r\n"
07446       "%s"
07447       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
07448 
07449    /* everything ok */
07450    return 0;
07451 }

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

07265 {
07266    struct ast_context *c;
07267    int res = 0, old_total_exten = dpc->total_exten;
07268 
07269    if (ast_strlen_zero(exten))
07270       exten = NULL;
07271    if (ast_strlen_zero(context))
07272       context = NULL;
07273 
07274    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
07275 
07276    /* try to lock contexts */
07277    if (ast_rdlock_contexts()) {
07278       astman_send_error(s, m, "Failed to lock contexts");
07279       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
07280       return -1;
07281    }
07282 
07283    c = NULL;      /* walk all contexts ... */
07284    while ( (c = ast_walk_contexts(c)) ) {
07285       struct ast_exten *e;
07286       struct ast_include *i;
07287       struct ast_ignorepat *ip;
07288 
07289       if (context && strcmp(ast_get_context_name(c), context) != 0)
07290          continue;   /* not the name we want */
07291 
07292       dpc->context_existence = 1;
07293       dpc->total_context++;
07294 
07295       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
07296 
07297       if (ast_rdlock_context(c)) {  /* failed to lock */
07298          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
07299          continue;
07300       }
07301 
07302       /* XXX note- an empty context is not printed */
07303       e = NULL;      /* walk extensions in context  */
07304       while ( (e = ast_walk_context_extensions(c, e)) ) {
07305          struct ast_exten *p;
07306 
07307          /* looking for extension? is this our extension? */
07308          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
07309             /* not the one we are looking for, continue */
07310             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
07311             continue;
07312          }
07313          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
07314 
07315          dpc->extension_existence = 1;
07316 
07317          dpc->total_exten++;
07318 
07319          p = NULL;      /* walk next extension peers */
07320          while ( (p = ast_walk_extension_priorities(e, p)) ) {
07321             int prio = ast_get_extension_priority(p);
07322 
07323             dpc->total_prio++;
07324             if (!dpc->total_items++)
07325                manager_dpsendack(s, m);
07326             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07327             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
07328 
07329             /* XXX maybe make this conditional, if p != e ? */
07330             if (ast_get_extension_label(p))
07331                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
07332 
07333             if (prio == PRIORITY_HINT) {
07334                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
07335             } else {
07336                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));
07337             }
07338             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
07339          }
07340       }
07341 
07342       i = NULL;      /* walk included and write info ... */
07343       while ( (i = ast_walk_context_includes(c, i)) ) {
07344          if (exten) {
07345             /* Check all includes for the requested extension */
07346             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
07347          } else {
07348             if (!dpc->total_items++)
07349                manager_dpsendack(s, m);
07350             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07351             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));
07352             astman_append(s, "\r\n");
07353             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
07354          }
07355       }
07356 
07357       ip = NULL;  /* walk ignore patterns and write info ... */
07358       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
07359          const char *ipname = ast_get_ignorepat_name(ip);
07360          char ignorepat[AST_MAX_EXTENSION];
07361 
07362          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
07363          if (!exten || ast_extension_match(ignorepat, exten)) {
07364             if (!dpc->total_items++)
07365                manager_dpsendack(s, m);
07366             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07367             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
07368             astman_append(s, "\r\n");
07369          }
07370       }
07371       if (!rinclude) {
07372          struct ast_sw *sw = NULL;
07373          while ( (sw = ast_walk_context_switches(c, sw)) ) {
07374             if (!dpc->total_items++)
07375                manager_dpsendack(s, m);
07376             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
07377             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));  
07378             astman_append(s, "\r\n");
07379             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
07380          }
07381       }
07382 
07383       ast_unlock_context(c);
07384    }
07385    ast_unlock_contexts();
07386 
07387    if (dpc->total_exten == old_total_exten) {
07388       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
07389       /* Nothing new under the sun */
07390       return -1;
07391    } else {
07392       return res;
07393    }
07394 }

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

Definition at line 3001 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

03002 {
03003    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
03004       failing to get a number should count as a match, otherwise not */
03005 
03006    if (ast_strlen_zero(callerid)) {
03007       return ast_strlen_zero(cidpattern) ? 1 : 0;
03008    }
03009 
03010    return ast_extension_match(cidpattern, callerid);
03011 }

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

01808 {
01809    struct match_char *p; /* note minimal stack storage requirements */
01810    struct ast_exten pattern = { .label = label };
01811 #ifdef DEBUG_THIS
01812    if (tree)
01813       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
01814    else
01815       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
01816 #endif
01817    for (p = tree; p; p = p->alt_char) {
01818       if (p->is_pattern) {
01819          if (p->x[0] == 'N') {
01820             if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
01821 #define  NEW_MATCHER_CHK_MATCH          \
01822                if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */             \
01823                   if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */   \
01824                      update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p);                 \
01825                      if (!p->deleted) {                                                                                           \
01826                         if (action == E_FINDLABEL) {                                                                             \
01827                            if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) {                                  \
01828                               ast_debug(4, "Found label in preferred extension\n");                                            \
01829                               return;                                                                                          \
01830                            }                                                                                                    \
01831                         } else {                                                                                                 \
01832                            ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten);                       \
01833                            return; /* the first match, by definition, will be the best, because of the sorted tree */           \
01834                         }                                                                                                        \
01835                      }                                                                                                            \
01836                   }                                                                                                                \
01837                }
01838                
01839 #define  NEW_MATCHER_RECURSE             \
01840                if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0)                 \
01841                                                 || p->next_char->x[0] == '!')) {                                          \
01842                   if (*(str + 1) || p->next_char->x[0] == '!') {                                                         \
01843                      new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
01844                      if (score->exten)  {                                                                             \
01845                           ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten);                         \
01846                         return; /* the first match is all we need */                                                 \
01847                      }                                                                                    \
01848                   } else {                                                                                             \
01849                      new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action);    \
01850                      if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {      \
01851                           ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten :     \
01852                                         "NULL");                                                                        \
01853                         return; /* the first match is all we need */                                                 \
01854                      }                                                                                    \
01855                   }                                                                                                    \
01856                } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) {                                                                  \
01857                   score->canmatch = 1;                                                                                 \
01858                   score->canmatch_exten = get_canmatch_exten(p);                                                       \
01859                   if (action == E_CANMATCH || action == E_MATCHMORE) {                                                 \
01860                        ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str);                                  \
01861                      return;                                                                                          \
01862                   }                                                                                        \
01863                }
01864                
01865                NEW_MATCHER_CHK_MATCH;
01866                NEW_MATCHER_RECURSE;
01867             }
01868          } else if (p->x[0] == 'Z') {
01869             if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
01870                NEW_MATCHER_CHK_MATCH;
01871                NEW_MATCHER_RECURSE;
01872             }
01873          } else if (p->x[0] == 'X') { 
01874             if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
01875                NEW_MATCHER_CHK_MATCH;
01876                NEW_MATCHER_RECURSE;
01877             }
01878          } else if (p->x[0] == '.' && p->x[1] == 0) {
01879             /* how many chars will the . match against? */
01880             int i = 0;
01881             const char *str2 = str;
01882             while (*str2 && *str2 != '/') {
01883                str2++;
01884                i++;
01885             }
01886             if (p->exten && *str2 != '/') {
01887                update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
01888                if (score->exten) {
01889                   ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
01890                   return; /* the first match is all we need */
01891                }
01892             }
01893             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01894                new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
01895                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01896                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
01897                   return; /* the first match is all we need */
01898                }
01899             }
01900          } else if (p->x[0] == '!' && p->x[1] == 0) {
01901             /* how many chars will the . match against? */
01902             int i = 1;
01903             const char *str2 = str;
01904             while (*str2 && *str2 != '/') {
01905                str2++;
01906                i++;
01907             }
01908             if (p->exten && *str2 != '/') {
01909                update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
01910                if (score->exten) {
01911                   ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
01912                   return; /* the first match is all we need */
01913                }
01914             }
01915             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01916                new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
01917                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01918                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
01919                   return; /* the first match is all we need */
01920                }
01921             }
01922          } else if (p->x[0] == '/' && p->x[1] == 0) {
01923             /* the pattern in the tree includes the cid match! */
01924             if (p->next_char && callerid && *callerid) {
01925                new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
01926                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01927                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
01928                   return; /* the first match is all we need */
01929                }
01930             }
01931          } else if (strchr(p->x, *str)) {
01932             ast_debug(4, "Nothing strange about this match\n");
01933             NEW_MATCHER_CHK_MATCH;
01934             NEW_MATCHER_RECURSE;
01935          }
01936       } else if (strchr(p->x, *str)) {
01937          ast_debug(4, "Nothing strange about this match\n");
01938          NEW_MATCHER_CHK_MATCH;
01939          NEW_MATCHER_RECURSE;
01940       }
01941    }
01942    ast_debug(4, "return at end of func\n");
01943 }

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

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

03312 {
03313    int parens = 0;
03314 
03315    *offset = 0;
03316    *length = INT_MAX;
03317    *isfunc = 0;
03318    for (; *var; var++) {
03319       if (*var == '(') {
03320          (*isfunc)++;
03321          parens++;
03322       } else if (*var == ')') {
03323          parens--;
03324       } else if (*var == ':' && parens == 0) {
03325          *var++ = '\0';
03326          sscanf(var, "%30d:%30d", offset, length);
03327          return 1; /* offset:length valid */
03328       }
03329    }
03330    return 0;
03331 }

void pbx_builtin_clear_globals ( void   ) 

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

10710 {
10711    struct ast_var_t *vardata;
10712 
10713    ast_rwlock_wrlock(&globalslock);
10714    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10715       ast_var_delete(vardata);
10716    ast_rwlock_unlock(&globalslock);
10717 }

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

10476 {
10477    struct ast_var_t *variables;
10478    const char *ret = NULL;
10479    int i;
10480    struct varshead *places[2] = { NULL, &globals };
10481 
10482    if (!name)
10483       return NULL;
10484 
10485    if (chan) {
10486       ast_channel_lock(chan);
10487       places[0] = &chan->varshead;
10488    }
10489 
10490    for (i = 0; i < 2; i++) {
10491       if (!places[i])
10492          continue;
10493       if (places[i] == &globals)
10494          ast_rwlock_rdlock(&globalslock);
10495       AST_LIST_TRAVERSE(places[i], variables, entries) {
10496          if (!strcmp(name, ast_var_name(variables))) {
10497             ret = ast_var_value(variables);
10498             break;
10499          }
10500       }
10501       if (places[i] == &globals)
10502          ast_rwlock_unlock(&globalslock);
10503       if (ret)
10504          break;
10505    }
10506 
10507    if (chan)
10508       ast_channel_unlock(chan);
10509 
10510    return ret;
10511 }

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

Definition at line 10731 of file pbx.c.

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

10732 {
10733    char *condition, *branch1, *branch2, *branch;
10734    char *stringp;
10735 
10736    if (ast_strlen_zero(data)) {
10737       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
10738       return 0;
10739    }
10740 
10741    stringp = ast_strdupa(data);
10742    condition = strsep(&stringp,"?");
10743    branch1 = strsep(&stringp,":");
10744    branch2 = strsep(&stringp,"");
10745    branch = pbx_checkcondition(condition) ? branch1 : branch2;
10746 
10747    if (ast_strlen_zero(branch)) {
10748       ast_debug(1, "Not taking any branch\n");
10749       return 0;
10750    }
10751 
10752    return pbx_builtin_goto(chan, branch);
10753 }

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

10670 {
10671    char *name;
10672    char *value;
10673    char *channel;
10674    char tmp[VAR_BUF_SIZE];
10675    static int deprecation_warning = 0;
10676 
10677    if (ast_strlen_zero(data)) {
10678       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
10679       return 0;
10680    }
10681    tmp[0] = 0;
10682    if (!deprecation_warning) {
10683       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
10684       deprecation_warning = 1;
10685    }
10686 
10687    value = ast_strdupa(data);
10688    name = strsep(&value,"=");
10689    channel = strsep(&value,",");
10690    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
10691       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
10692       if (chan2) {
10693          char *s = ast_alloca(strlen(value) + 4);
10694          sprintf(s, "${%s}", value);
10695          pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
10696          chan2 = ast_channel_unref(chan2);
10697       }
10698       pbx_builtin_setvar_helper(chan, name, tmp);
10699    }
10700 
10701    return(0);
10702 }

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

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

09997 {
09998    const char *options = data;
09999    int answer = 1;
10000 
10001    /* Some channels can receive DTMF in unanswered state; some cannot */
10002    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
10003       answer = 0;
10004    }
10005 
10006    /* If the channel is hungup, stop waiting */
10007    if (ast_check_hangup(chan)) {
10008       return -1;
10009    } else if (chan->_state != AST_STATE_UP && answer) {
10010       __ast_answer(chan, 0, 1);
10011    }
10012 
10013    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
10014 
10015    return AST_PBX_INCOMPLETE;
10016 }

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

Definition at line 10704 of file pbx.c.

10705 {
10706    return 0;
10707 }

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

10514 {
10515    struct ast_var_t *newvariable;
10516    struct varshead *headp;
10517 
10518    if (name[strlen(name)-1] == ')') {
10519       char *function = ast_strdupa(name);
10520 
10521       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10522       ast_func_write(chan, function, value);
10523       return;
10524    }
10525 
10526    if (chan) {
10527       ast_channel_lock(chan);
10528       headp = &chan->varshead;
10529    } else {
10530       ast_rwlock_wrlock(&globalslock);
10531       headp = &globals;
10532    }
10533 
10534    if (value && (newvariable = ast_var_assign(name, value))) {
10535       if (headp == &globals)
10536          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10537       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10538    }
10539 
10540    if (chan)
10541       ast_channel_unlock(chan);
10542    else
10543       ast_rwlock_unlock(&globalslock);
10544 }

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

Definition at line 3620 of file pbx.c.

References raise_exception().

03621 {
03622    /* Priority will become 1, next time through the AUTOLOOP */
03623    return raise_exception(chan, reason, 0);
03624 }

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

Definition at line 10792 of file pbx.c.

References ast_say_character_str().

10793 {
10794    int res = 0;
10795 
10796    if (data)
10797       res = ast_say_character_str(chan, data, "", chan->language);
10798    return res;
10799 }

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

Definition at line 10810 of file pbx.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_date, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), and pbx_builtin_setvar_helper().

10811 {
10812    int res = 0;
10813    char *parse;
10814    int unixdate = 0;
10815    char charascii[2];
10816 
10817    AST_DECLARE_APP_ARGS(args,
10818       AST_APP_ARG(datestr);
10819       AST_APP_ARG(digits);
10820    );
10821 
10822 
10823    if (ast_strlen_zero(data)) {
10824       ast_log(LOG_WARNING, "SayDate requires an argument (date)\n");
10825       return -1;
10826    }
10827 
10828    if (!(parse = ast_strdupa(data))) {
10829       ast_log(LOG_WARNING, "Memory Error!\n");
10830       return -1;
10831    }
10832 
10833    AST_STANDARD_APP_ARGS(args, parse);
10834 
10835    if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) {
10836       ast_log(LOG_WARNING, "SayDate escape digits must be a subset from '0123456789*#'\n");
10837       args.digits = "";
10838    }
10839 
10840    if (sscanf(args.datestr, "%d", &unixdate) != 1) {
10841       ast_log(LOG_WARNING, "Firt argument to SayDate must be numeric (date)\n");
10842       return -1;
10843    }
10844 
10845    res = ast_say_date(chan, (time_t)unixdate, args.digits, chan->language);
10846    if (res > 0) {
10847       if (isdigit(res) || (res == '*') || (res == '#')) {
10848          snprintf(charascii, 2, "%c", res);
10849          pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii);
10850          res = 0;
10851       } else {
10852          ast_log(LOG_WARNING, "SayDate: invalid return value (%d) detected\n", res);
10853       }
10854    }
10855    return res;
10856 }

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

Definition at line 10783 of file pbx.c.

References ast_say_digit_str().

10784 {
10785    int res = 0;
10786 
10787    if (data)
10788       res = ast_say_digit_str(chan, data, "", chan->language);
10789    return res;
10790 }

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

Definition at line 10755 of file pbx.c.

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

10756 {
10757    char tmp[256];
10758    char *number = tmp;
10759    char *options;
10760 
10761    if (ast_strlen_zero(data)) {
10762       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
10763       return -1;
10764    }
10765    ast_copy_string(tmp, data, sizeof(tmp));
10766    strsep(&number, ",");
10767    options = strsep(&number, ",");
10768    if (options) {
10769       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
10770          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
10771          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
10772          return -1;
10773       }
10774    }
10775 
10776    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
10777       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
10778    }
10779 
10780    return 0;
10781 }

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

Definition at line 10801 of file pbx.c.

References ast_say_phonetic_str().

10802 {
10803    int res = 0;
10804 
10805    if (data)
10806       res = ast_say_phonetic_str(chan, data, "", chan->language);
10807    return res;
10808 }

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

Definition at line 10858 of file pbx.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_say_time, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, parse(), and pbx_builtin_setvar_helper().

10859 {
10860    int res = 0;
10861    char *parse;
10862    int secs = 0;
10863    char charascii[2];
10864 
10865    AST_DECLARE_APP_ARGS(args,
10866       AST_APP_ARG(timestr);
10867       AST_APP_ARG(digits);
10868    );
10869 
10870    if (ast_strlen_zero(data)) {
10871       ast_log(LOG_WARNING, "SayTime requires an argument (time in seconds)\n");
10872       return -1;
10873    }
10874 
10875    if (!(parse = ast_strdupa(data))) {
10876       ast_log(LOG_WARNING, "Memory Error!\n");
10877       return -1;
10878    }
10879 
10880    AST_STANDARD_APP_ARGS(args, parse);
10881 
10882    if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) {
10883       ast_log(LOG_WARNING, "SayTime escape digits must be a subset from '0123456789*#'\n");
10884       args.digits = "";
10885    }
10886 
10887    if (sscanf(args.timestr, "%d", &secs) != 1) {
10888       ast_log(LOG_WARNING, "Firt argument to SayTime must be numeric (time in seconds)\n");
10889       return -1;
10890    }
10891 
10892    res = ast_say_time(chan, (time_t)secs, args.digits, chan->language);
10893    if (res > 0) {
10894       if (isdigit(res) || (res == '*') || (res == '#')) {
10895          snprintf(charascii, 2, "%c", res);
10896          pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii);
10897          res = 0;
10898       } else {
10899          ast_log(LOG_WARNING, "SayTime: invalid return value (%d) detected\n", res);
10900       }
10901    }
10902    return res;
10903 }

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

10445 {
10446    struct ast_var_t *variables;
10447    const char *var, *val;
10448    int total = 0;
10449 
10450    if (!chan)
10451       return 0;
10452 
10453    ast_str_reset(*buf);
10454 
10455    ast_channel_lock(chan);
10456 
10457    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10458       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10459          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10460          ) {
10461          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10462             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10463             break;
10464          } else
10465             total++;
10466       } else
10467          break;
10468    }
10469 
10470    ast_channel_unlock(chan);
10471 
10472    return total;
10473 }

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

10604 {
10605    char *name, *value, *mydata;
10606 
10607    if (ast_compat_app_set) {
10608       return pbx_builtin_setvar_multiple(chan, data);
10609    }
10610 
10611    if (ast_strlen_zero(data)) {
10612       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10613       return 0;
10614    }
10615 
10616    mydata = ast_strdupa(data);
10617    name = strsep(&mydata, "=");
10618    value = mydata;
10619    if (!value) {
10620       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10621       return 0;
10622    }
10623 
10624    if (strchr(name, ' ')) {
10625       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10626    }
10627 
10628    pbx_builtin_setvar_helper(chan, name, value);
10629 
10630    return 0;
10631 }

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 10546 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_saydate(), pbx_builtin_saytime(), 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().

10547 {
10548    struct ast_var_t *newvariable;
10549    struct varshead *headp;
10550    const char *nametail = name;
10551 
10552    if (name[strlen(name) - 1] == ')') {
10553       char *function = ast_strdupa(name);
10554 
10555       return ast_func_write(chan, function, value);
10556    }
10557 
10558    if (chan) {
10559       ast_channel_lock(chan);
10560       headp = &chan->varshead;
10561    } else {
10562       ast_rwlock_wrlock(&globalslock);
10563       headp = &globals;
10564    }
10565 
10566    /* For comparison purposes, we have to strip leading underscores */
10567    if (*nametail == '_') {
10568       nametail++;
10569       if (*nametail == '_')
10570          nametail++;
10571    }
10572 
10573    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10574       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10575          /* there is already such a variable, delete it */
10576          AST_LIST_REMOVE_CURRENT(entries);
10577          ast_var_delete(newvariable);
10578          break;
10579       }
10580    }
10581    AST_LIST_TRAVERSE_SAFE_END;
10582 
10583    if (value && (newvariable = ast_var_assign(name, value))) {
10584       if (headp == &globals)
10585          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10586       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10587       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10588          "Channel: %s\r\n"
10589          "Variable: %s\r\n"
10590          "Value: %s\r\n"
10591          "Uniqueid: %s\r\n",
10592          chan ? chan->name : "none", name, value,
10593          chan ? chan->uniqueid : "none");
10594    }
10595 
10596    if (chan)
10597       ast_channel_unlock(chan);
10598    else
10599       ast_rwlock_unlock(&globalslock);
10600    return 0;
10601 }

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

10634 {
10635    char *data;
10636    int x;
10637    AST_DECLARE_APP_ARGS(args,
10638       AST_APP_ARG(pair)[24];
10639    );
10640    AST_DECLARE_APP_ARGS(pair,
10641       AST_APP_ARG(name);
10642       AST_APP_ARG(value);
10643    );
10644 
10645    if (ast_strlen_zero(vdata)) {
10646       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10647       return 0;
10648    }
10649 
10650    data = ast_strdupa(vdata);
10651    AST_STANDARD_APP_ARGS(args, data);
10652 
10653    for (x = 0; x < args.argc; x++) {
10654       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10655       if (pair.argc == 2) {
10656          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10657          if (strchr(pair.name, ' '))
10658             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);
10659       } else if (!chan) {
10660          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10661       } else {
10662          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10663       }
10664    }
10665 
10666    return 0;
10667 }

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

10720 {
10721    int res;
10722    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10723       return 0;
10724    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10725       return res;
10726    } else {                                         /* Strings are true */
10727       return 1;
10728    }
10729 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1573 of file pbx.c.

References ast_free.

Referenced by __ast_pbx_run().

01574 {
01575    ast_free(p);
01576 }

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

01500 {
01501    int res;
01502    struct ast_module_user *u = NULL;
01503    const char *saved_c_appl;
01504    const char *saved_c_data;
01505 
01506    if (c->cdr && !ast_check_hangup(c))
01507       ast_cdr_setapp(c->cdr, app->name, data);
01508 
01509    /* save channel values */
01510    saved_c_appl= c->appl;
01511    saved_c_data= c->data;
01512 
01513    c->appl = app->name;
01514    c->data = data;
01515    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01516 
01517    if (app->module)
01518       u = __ast_module_user_add(app->module, c);
01519    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01520          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01521       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01522          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01523          app->name, (char *) data);
01524    }
01525    res = app->execute(c, S_OR(data, ""));
01526    if (app->module && u)
01527       __ast_module_user_remove(app->module, u);
01528    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01529    /* restore channel values */
01530    c->appl = saved_c_appl;
01531    c->data = saved_c_data;
01532    return res;
01533 }

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

04709 {
04710    struct ast_exten *e;
04711    struct ast_app *app;
04712    char *substitute = NULL;
04713    int res;
04714    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04715    char passdata[EXT_DATA_SIZE];
04716 
04717    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04718 
04719    ast_rdlock_contexts();
04720    if (found)
04721       *found = 0;
04722 
04723    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04724    if (e) {
04725       if (found)
04726          *found = 1;
04727       if (matching_action) {
04728          ast_unlock_contexts();
04729          return -1;  /* success, we found it */
04730       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04731          res = e->priority;
04732          ast_unlock_contexts();
04733          return res; /* the priority we were looking for */
04734       } else { /* spawn */
04735          if (!e->cached_app)
04736             e->cached_app = pbx_findapp(e->app);
04737          app = e->cached_app;
04738          if (ast_strlen_zero(e->data)) {
04739             *passdata = '\0';
04740          } else {
04741             const char *tmp;
04742             if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
04743                /* no variables to substitute, copy on through */
04744                ast_copy_string(passdata, e->data, sizeof(passdata));
04745             } else {
04746                /* save e->data on stack for later processing after lock released */
04747                substitute = ast_strdupa(e->data);
04748             }
04749          }
04750          ast_unlock_contexts();
04751          if (!app) {
04752             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04753             return -1;
04754          }
04755          if (c->context != context)
04756             ast_copy_string(c->context, context, sizeof(c->context));
04757          if (c->exten != exten)
04758             ast_copy_string(c->exten, exten, sizeof(c->exten));
04759          c->priority = priority;
04760          if (substitute) {
04761             pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
04762          }
04763 #ifdef CHANNEL_TRACE
04764          ast_channel_trace_update(c);
04765 #endif
04766          ast_debug(1, "Launching '%s'\n", app->name);
04767          if (VERBOSITY_ATLEAST(3)) {
04768             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
04769             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
04770                exten, context, priority,
04771                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
04772                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
04773                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
04774                "in new stack");
04775          }
04776          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
04777                "Channel: %s\r\n"
04778                "Context: %s\r\n"
04779                "Extension: %s\r\n"
04780                "Priority: %d\r\n"
04781                "Application: %s\r\n"
04782                "AppData: %s\r\n"
04783                "Uniqueid: %s\r\n",
04784                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
04785          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04786       }
04787    } else if (q.swo) {  /* not found here, but in another switch */
04788       if (found)
04789          *found = 1;
04790       ast_unlock_contexts();
04791       if (matching_action) {
04792          return -1;
04793       } else {
04794          if (!q.swo->exec) {
04795             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04796             res = -1;
04797          }
04798          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04799       }
04800    } else { /* not found anywhere, see what happened */
04801       ast_unlock_contexts();
04802       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04803       switch (q.status) {
04804       case STATUS_NO_CONTEXT:
04805          if (!matching_action && !combined_find_spawn)
04806             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04807          break;
04808       case STATUS_NO_EXTENSION:
04809          if (!matching_action && !combined_find_spawn)
04810             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04811          break;
04812       case STATUS_NO_PRIORITY:
04813          if (!matching_action && !combined_find_spawn)
04814             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04815          break;
04816       case STATUS_NO_LABEL:
04817          if (context && !combined_find_spawn)
04818             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04819          break;
04820       default:
04821          ast_debug(1, "Shouldn't happen!\n");
04822       }
04823 
04824       return (matching_action) ? 0 : -1;
04825    }
04826 }

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

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

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

Definition at line 1551 of file pbx.c.

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

Referenced by pbx_find_extension().

01552 {
01553    struct ast_switch *asw;
01554 
01555    AST_RWLIST_RDLOCK(&switches);
01556    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01557       if (!strcasecmp(asw->name, sw))
01558          break;
01559    }
01560    AST_RWLIST_UNLOCK(&switches);
01561 
01562    return asw;
01563 }

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

References ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by ast_readconfig().

04060 {
04061    if (new_live_dangerously && !live_dangerously) {
04062       ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
04063          "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
04064    }
04065 
04066    if (!new_live_dangerously && live_dangerously) {
04067       ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
04068    }
04069    live_dangerously = new_live_dangerously;
04070 }

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

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

11272 {
11273    char *exten, *pri, *context;
11274    char *stringp;
11275    int ipri;
11276    int mode = 0;
11277 
11278    if (ast_strlen_zero(goto_string)) {
11279       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
11280       return -1;
11281    }
11282    stringp = ast_strdupa(goto_string);
11283    context = strsep(&stringp, ","); /* guaranteed non-null */
11284    exten = strsep(&stringp, ",");
11285    pri = strsep(&stringp, ",");
11286    if (!exten) {  /* Only a priority in this one */
11287       pri = context;
11288       exten = NULL;
11289       context = NULL;
11290    } else if (!pri) {   /* Only an extension and priority in this one */
11291       pri = exten;
11292       exten = context;
11293       context = NULL;
11294    }
11295    if (*pri == '+') {
11296       mode = 1;
11297       pri++;
11298    } else if (*pri == '-') {
11299       mode = -1;
11300       pri++;
11301    }
11302    if (sscanf(pri, "%30d", &ipri) != 1) {
11303       ipri = ast_findlabel_extension(chan, context ? context : chan->context,
11304          exten ? exten : chan->exten, pri,
11305          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
11306       if (ipri < 1) {
11307          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
11308          return -1;
11309       } else
11310          mode = 0;
11311    }
11312    /* At this point we have a priority and maybe an extension and a context */
11313 
11314    if (mode)
11315       ipri = chan->priority + (ipri * mode);
11316 
11317    if (async)
11318       ast_async_goto(chan, context, exten, ipri);
11319    else
11320       ast_explicit_goto(chan, context, exten, ipri);
11321 
11322    return 0;
11323 
11324 }

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

03435 {
03436    struct ast_str *str = ast_str_create(16);
03437    const char *cret;
03438 
03439    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03440    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03441    *ret = cret ? workspace : NULL;
03442    ast_free(str);
03443 }

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

References autofallthrough.

Referenced by pbx_load_module().

05942 {
05943    int oldval = autofallthrough;
05944    autofallthrough = newval;
05945    return oldval;
05946 }

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

References extenpatternmatchnew.

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

05949 {
05950    int oldval = extenpatternmatchnew;
05951    extenpatternmatchnew = newval;
05952    return oldval;
05953 }

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

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

Referenced by pbx_load_module().

05956 {
05957    if (overrideswitch) {
05958       ast_free(overrideswitch);
05959    }
05960    if (!ast_strlen_zero(newval)) {
05961       overrideswitch = ast_strdup(newval);
05962    } else {
05963       overrideswitch = NULL;
05964    }
05965 }

static void pbx_shutdown ( void   )  [static]

Definition at line 11391 of file pbx.c.

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

Referenced by ast_pbx_init().

11392 {
11393    if (hints) {
11394       ao2_ref(hints, -1);
11395       hints = NULL;
11396    }
11397    if (statecbs) {
11398       ao2_ref(statecbs, -1);
11399       statecbs = NULL;
11400    }
11401    if (contexts_table) {
11402       ast_hashtab_destroy(contexts_table, NULL);
11403    }
11404    pbx_builtin_clear_globals();
11405 }

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

04481 {
04482    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04483    char *cp4 = NULL;
04484    const char *tmp, *whereweare, *orig_cp2 = cp2;
04485    int length, offset, offset2, isfunction;
04486    char *workspace = NULL;
04487    char *ltmp = NULL, *var = NULL;
04488    char *nextvar, *nextexp, *nextthing;
04489    char *vars, *vare;
04490    int pos, brackets, needsub, len;
04491 
04492    *cp2 = 0; /* just in case nothing ends up there */
04493    whereweare=tmp=cp1;
04494    while (!ast_strlen_zero(whereweare) && count) {
04495       /* Assume we're copying the whole remaining string */
04496       pos = strlen(whereweare);
04497       nextvar = NULL;
04498       nextexp = NULL;
04499       nextthing = strchr(whereweare, '$');
04500       if (nextthing) {
04501          switch (nextthing[1]) {
04502          case '{':
04503             nextvar = nextthing;
04504             pos = nextvar - whereweare;
04505             break;
04506          case '[':
04507             nextexp = nextthing;
04508             pos = nextexp - whereweare;
04509             break;
04510          default:
04511             pos = 1;
04512          }
04513       }
04514 
04515       if (pos) {
04516          /* Can't copy more than 'count' bytes */
04517          if (pos > count)
04518             pos = count;
04519 
04520          /* Copy that many bytes */
04521          memcpy(cp2, whereweare, pos);
04522 
04523          count -= pos;
04524          cp2 += pos;
04525          whereweare += pos;
04526          *cp2 = 0;
04527       }
04528 
04529       if (nextvar) {
04530          /* We have a variable.  Find the start and end, and determine
04531             if we are going to have to recursively call ourselves on the
04532             contents */
04533          vars = vare = nextvar + 2;
04534          brackets = 1;
04535          needsub = 0;
04536 
04537          /* Find the end of it */
04538          while (brackets && *vare) {
04539             if ((vare[0] == '$') && (vare[1] == '{')) {
04540                needsub++;
04541             } else if (vare[0] == '{') {
04542                brackets++;
04543             } else if (vare[0] == '}') {
04544                brackets--;
04545             } else if ((vare[0] == '$') && (vare[1] == '['))
04546                needsub++;
04547             vare++;
04548          }
04549          if (brackets)
04550             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04551          len = vare - vars - 1;
04552 
04553          /* Skip totally over variable string */
04554          whereweare += (len + 3);
04555 
04556          if (!var)
04557             var = ast_alloca(VAR_BUF_SIZE);
04558 
04559          /* Store variable name (and truncate) */
04560          ast_copy_string(var, vars, len + 1);
04561 
04562          /* Substitute if necessary */
04563          if (needsub) {
04564             size_t used;
04565             if (!ltmp)
04566                ltmp = ast_alloca(VAR_BUF_SIZE);
04567 
04568             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04569             vars = ltmp;
04570          } else {
04571             vars = var;
04572          }
04573 
04574          if (!workspace)
04575             workspace = ast_alloca(VAR_BUF_SIZE);
04576 
04577          workspace[0] = '\0';
04578 
04579          parse_variable_name(vars, &offset, &offset2, &isfunction);
04580          if (isfunction) {
04581             /* Evaluate function */
04582             if (c || !headp)
04583                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04584             else {
04585                struct varshead old;
04586                struct ast_channel *c = ast_dummy_channel_alloc();
04587                if (c) {
04588                   memcpy(&old, &c->varshead, sizeof(old));
04589                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04590                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04591                   /* Don't deallocate the varshead that was passed in */
04592                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04593                   c = ast_channel_unref(c);
04594                } else {
04595                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04596                }
04597             }
04598             ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
04599          } else {
04600             /* Retrieve variable value */
04601             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04602          }
04603          if (cp4) {
04604             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04605 
04606             length = strlen(cp4);
04607             if (length > count)
04608                length = count;
04609             memcpy(cp2, cp4, length);
04610             count -= length;
04611             cp2 += length;
04612             *cp2 = 0;
04613          }
04614       } else if (nextexp) {
04615          /* We have an expression.  Find the start and end, and determine
04616             if we are going to have to recursively call ourselves on the
04617             contents */
04618          vars = vare = nextexp + 2;
04619          brackets = 1;
04620          needsub = 0;
04621 
04622          /* Find the end of it */
04623          while (brackets && *vare) {
04624             if ((vare[0] == '$') && (vare[1] == '[')) {
04625                needsub++;
04626                brackets++;
04627                vare++;
04628             } else if (vare[0] == '[') {
04629                brackets++;
04630             } else if (vare[0] == ']') {
04631                brackets--;
04632             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04633                needsub++;
04634                vare++;
04635             }
04636             vare++;
04637          }
04638          if (brackets)
04639             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04640          len = vare - vars - 1;
04641 
04642          /* Skip totally over expression */
04643          whereweare += (len + 3);
04644 
04645          if (!var)
04646             var = ast_alloca(VAR_BUF_SIZE);
04647 
04648          /* Store variable name (and truncate) */
04649          ast_copy_string(var, vars, len + 1);
04650 
04651          /* Substitute if necessary */
04652          if (needsub) {
04653             size_t used;
04654             if (!ltmp)
04655                ltmp = ast_alloca(VAR_BUF_SIZE);
04656 
04657             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04658             vars = ltmp;
04659          } else {
04660             vars = var;
04661          }
04662 
04663          length = ast_expr(vars, cp2, count, c);
04664 
04665          if (length) {
04666             ast_debug(1, "Expression result is '%s'\n", cp2);
04667             count -= length;
04668             cp2 += length;
04669             *cp2 = 0;
04670          }
04671       }
04672    }
04673    *used = cp2 - orig_cp2;
04674 }

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

Definition at line 4682 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

04683 {
04684    size_t used;
04685    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04686 }

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

Definition at line 5859 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

05860 {
05861    /* Oh joyeous kernel, we're a new thread, with nothing to do but
05862       answer this channel and get it going.
05863    */
05864    /* NOTE:
05865       The launcher of this function _MUST_ increment 'countcalls'
05866       before invoking the function; it will be decremented when the
05867       PBX has finished running on the channel
05868     */
05869    struct ast_channel *c = data;
05870 
05871    __ast_pbx_run(c, NULL);
05872    decrease_call_count();
05873 
05874    pthread_exit(NULL);
05875 
05876    return NULL;
05877 }

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

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

06469 {
06470    /* Maximum number of characters added by terminal coloring is 22 */
06471    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
06472    char seealsotitle[40];
06473    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
06474    char *seealso = NULL;
06475    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
06476 
06477    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
06478    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
06479 
06480    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
06481    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
06482    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
06483    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
06484    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
06485 
06486 #ifdef AST_XML_DOCS
06487    if (aa->docsrc == AST_XML_DOC) {
06488       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
06489       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
06490       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
06491       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
06492 
06493       if (!synopsis || !description || !arguments || !seealso) {
06494          goto return_cleanup;
06495       }
06496    } else
06497 #endif
06498    {
06499       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06500       synopsis = ast_malloc(synopsis_size);
06501 
06502       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06503       description = ast_malloc(description_size);
06504 
06505       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06506       arguments = ast_malloc(arguments_size);
06507 
06508       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06509       seealso = ast_malloc(seealso_size);
06510 
06511       if (!synopsis || !description || !arguments || !seealso) {
06512          goto return_cleanup;
06513       }
06514 
06515       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
06516       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
06517       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
06518       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
06519    }
06520 
06521    /* Handle the syntax the same for both XML and raw docs */
06522    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06523    if (!(syntax = ast_malloc(syntax_size))) {
06524       goto return_cleanup;
06525    }
06526    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
06527 
06528    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
06529          infotitle, syntitle, synopsis, destitle, description,
06530          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
06531 
06532 return_cleanup:
06533    ast_free(description);
06534    ast_free(arguments);
06535    ast_free(synopsis);
06536    ast_free(seealso);
06537    ast_free(syntax);
06538 }

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

helper function to print an extension

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

06906 {
06907    int prio = ast_get_extension_priority(e);
06908    if (prio == PRIORITY_HINT) {
06909       snprintf(buf, buflen, "hint: %s",
06910          ast_get_extension_app(e));
06911    } else {
06912       snprintf(buf, buflen, "%d. %s(%s)",
06913          prio, ast_get_extension_app(e),
06914          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06915    }
06916 }

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

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

03595 {
03596    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03597    struct pbx_exception *exception = NULL;
03598 
03599    if (!ds) {
03600       ds = ast_datastore_alloc(&exception_store_info, NULL);
03601       if (!ds)
03602          return -1;
03603       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03604          ast_datastore_free(ds);
03605          return -1;
03606       }
03607       ds->data = exception;
03608       ast_channel_datastore_add(chan, ds);
03609    } else
03610       exception = ds->data;
03611 
03612    ast_string_field_set(exception, reason, reason);
03613    ast_string_field_set(exception, context, chan->context);
03614    ast_string_field_set(exception, exten, chan->exten);
03615    exception->priority = chan->priority;
03616    set_ext_pri(chan, "e", priority);
03617    return 0;
03618 }

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

03856                                                                  {
03857    int res = 0;
03858    struct ast_custom_escalating_function *cur_escalation;
03859 
03860    AST_RWLIST_RDLOCK(&escalation_root);
03861    AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) {
03862       if (cur_escalation->acf == acf) {
03863          res = cur_escalation->read_escalates;
03864          break;
03865       }
03866    }
03867    AST_RWLIST_UNLOCK(&escalation_root);
03868    return res;
03869 }

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

05432 {
05433    ast_channel_lock(c);
05434    ast_copy_string(c->exten, exten, sizeof(c->exten));
05435    c->priority = pri;
05436    ast_channel_unlock(c);
05437 }

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

07075 {
07076    struct ast_context *c = NULL;
07077    int res = 0, old_total_exten = dpc->total_exten;
07078 
07079    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
07080 
07081    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
07082    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
07083    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
07084    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
07085    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
07086    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
07087    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
07088    ast_rdlock_contexts();
07089 
07090    /* walk all contexts ... */
07091    while ( (c = ast_walk_contexts(c)) ) {
07092       int context_info_printed = 0;
07093 
07094       if (context && strcmp(ast_get_context_name(c), context))
07095          continue;   /* skip this one, name doesn't match */
07096 
07097       dpc->context_existence = 1;
07098 
07099       if (!c->pattern_tree) {
07100          /* Ignore check_return warning from Coverity for ast_exists_extension below */
07101          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
07102       }
07103 
07104       ast_rdlock_context(c);
07105 
07106       dpc->total_context++;
07107       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
07108          ast_get_context_name(c), ast_get_context_registrar(c));
07109       context_info_printed = 1;
07110 
07111       if (c->pattern_tree)
07112       {
07113          cli_match_char_tree(c->pattern_tree, " ", fd);
07114       } else {
07115          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
07116       }
07117 
07118       ast_unlock_context(c);
07119 
07120       /* if we print something in context, make an empty line */
07121       if (context_info_printed)
07122          ast_cli(fd, "\n");
07123    }
07124    ast_unlock_contexts();
07125 
07126    return (dpc->total_exten == old_total_exten) ? -1 : res;
07127 }

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

06920 {
06921    struct ast_context *c = NULL;
06922    int res = 0, old_total_exten = dpc->total_exten;
06923 
06924    ast_rdlock_contexts();
06925 
06926    /* walk all contexts ... */
06927    while ( (c = ast_walk_contexts(c)) ) {
06928       struct ast_exten *e;
06929       struct ast_include *i;
06930       struct ast_ignorepat *ip;
06931 #ifndef LOW_MEMORY
06932       char buf[1024], buf2[1024];
06933 #else
06934       char buf[256], buf2[256];
06935 #endif
06936       int context_info_printed = 0;
06937 
06938       if (context && strcmp(ast_get_context_name(c), context))
06939          continue;   /* skip this one, name doesn't match */
06940 
06941       dpc->context_existence = 1;
06942 
06943       ast_rdlock_context(c);
06944 
06945       /* are we looking for exten too? if yes, we print context
06946        * only if we find our extension.
06947        * Otherwise print context even if empty ?
06948        * XXX i am not sure how the rinclude is handled.
06949        * I think it ought to go inside.
06950        */
06951       if (!exten) {
06952          dpc->total_context++;
06953          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06954             ast_get_context_name(c), ast_get_context_registrar(c));
06955          context_info_printed = 1;
06956       }
06957 
06958       /* walk extensions ... */
06959       e = NULL;
06960       while ( (e = ast_walk_context_extensions(c, e)) ) {
06961          struct ast_exten *p;
06962 
06963          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
06964             continue;   /* skip, extension match failed */
06965 
06966          dpc->extension_existence = 1;
06967 
06968          /* may we print context info? */
06969          if (!context_info_printed) {
06970             dpc->total_context++;
06971             if (rinclude) { /* TODO Print more info about rinclude */
06972                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
06973                   ast_get_context_name(c), ast_get_context_registrar(c));
06974             } else {
06975                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06976                   ast_get_context_name(c), ast_get_context_registrar(c));
06977             }
06978             context_info_printed = 1;
06979          }
06980          dpc->total_prio++;
06981 
06982          /* write extension name and first peer */
06983          if (e->matchcid == AST_EXT_MATCHCID_ON)
06984             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
06985          else
06986             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
06987 
06988          print_ext(e, buf2, sizeof(buf2));
06989 
06990          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
06991             ast_get_extension_registrar(e));
06992 
06993          dpc->total_exten++;
06994          /* walk next extension peers */
06995          p = e;   /* skip the first one, we already got it */
06996          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06997             const char *el = ast_get_extension_label(p);
06998             dpc->total_prio++;
06999             if (el)
07000                snprintf(buf, sizeof(buf), "   [%s]", el);
07001             else
07002                buf[0] = '\0';
07003             print_ext(p, buf2, sizeof(buf2));
07004 
07005             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
07006                ast_get_extension_registrar(p));
07007          }
07008       }
07009 
07010       /* walk included and write info ... */
07011       i = NULL;
07012       while ( (i = ast_walk_context_includes(c, i)) ) {
07013          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
07014          if (exten) {
07015             /* Check all includes for the requested extension */
07016             if (includecount >= AST_PBX_MAX_STACK) {
07017                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
07018             } else {
07019                int dupe = 0;
07020                int x;
07021                for (x = 0; x < includecount; x++) {
07022                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
07023                      dupe++;
07024                      break;
07025                   }
07026                }
07027                if (!dupe) {
07028                   includes[includecount] = ast_get_include_name(i);
07029                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
07030                } else {
07031                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
07032                }
07033             }
07034          } else {
07035             ast_cli(fd, "  Include =>        %-45s [%s]\n",
07036                buf, ast_get_include_registrar(i));
07037          }
07038       }
07039 
07040       /* walk ignore patterns and write info ... */
07041       ip = NULL;
07042       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
07043          const char *ipname = ast_get_ignorepat_name(ip);
07044          char ignorepat[AST_MAX_EXTENSION];
07045          snprintf(buf, sizeof(buf), "'%s'", ipname);
07046          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
07047          if (!exten || ast_extension_match(ignorepat, exten)) {
07048             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
07049                buf, ast_get_ignorepat_registrar(ip));
07050          }
07051       }
07052       if (!rinclude) {
07053          struct ast_sw *sw = NULL;
07054          while ( (sw = ast_walk_context_switches(c, sw)) ) {
07055             snprintf(buf, sizeof(buf), "'%s/%s'",
07056                ast_get_switch_name(sw),
07057                ast_get_switch_data(sw));
07058             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
07059                buf, ast_get_switch_registrar(sw));
07060          }
07061       }
07062 
07063       ast_unlock_context(c);
07064 
07065       /* if we print something in context, make an empty line */
07066       if (context_info_printed)
07067          ast_cli(fd, "\n");
07068    }
07069    ast_unlock_contexts();
07070 
07071    return (dpc->total_exten == old_total_exten) ? -1 : res;
07072 }

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

Definition at line 11383 of file pbx.c.

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

11384 {
11385    const struct ast_state_cb *state_cb = obj;
11386    ast_state_cb_type change_cb = arg;
11387 
11388    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
11389 }

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

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

03345 {
03346    char *ret = workspace;
03347    int lr;  /* length of the input string after the copy */
03348 
03349    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
03350 
03351    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
03352 
03353    /* Quick check if no need to do anything */
03354    if (offset == 0 && length >= lr) /* take the whole string */
03355       return ret;
03356 
03357    if (offset < 0)   {  /* translate negative offset into positive ones */
03358       offset = lr + offset;
03359       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03360          offset = 0;
03361    }
03362 
03363    /* too large offset result in empty string so we know what to return */
03364    if (offset >= lr)
03365       return ret + lr;  /* the final '\0' */
03366 
03367    ret += offset;    /* move to the start position */
03368    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
03369       ret[length] = '\0';
03370    else if (length < 0) {
03371       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
03372          ret[lr + length - offset] = '\0';
03373       else
03374          ret[0] = '\0';
03375    }
03376 
03377    return ret;
03378 }

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

04096 {
04097    int *thread_inhibit_escalations;
04098 
04099    thread_inhibit_escalations = ast_threadstorage_get(
04100       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04101 
04102    if (thread_inhibit_escalations == NULL) {
04103       ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
04104       /* On error, assume that we are inhibiting */
04105       return 1;
04106    }
04107 
04108    return *thread_inhibit_escalations;
04109 }

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

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

01749 {
01750    struct match_char *m3;
01751    struct match_char *m4;
01752    struct ast_exten *e3;
01753 
01754    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01755       return node->exten;
01756    }
01757 
01758    if (node && node->x[0] == '!' && !node->x[1]) {
01759       return node->exten;
01760    }
01761 
01762    if (!node || !node->next_char) {
01763       return NULL;
01764    }
01765 
01766    m3 = node->next_char;
01767 
01768    if (m3->exten) {
01769       return m3->exten;
01770    }
01771    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01772       if (m4->exten) {
01773          return m4->exten;
01774       }
01775    }
01776    for (m4 = m3; m4; m4 = m4->alt_char) {
01777       e3 = trie_find_next_match(m3);
01778       if (e3) {
01779          return e3;
01780       }
01781    }
01782 
01783    return NULL;
01784 }

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

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

07687 {
07688    struct ast_context *context = NULL;
07689    struct ast_exten *eroot = NULL, *e = NULL;
07690 
07691    ast_rdlock_contexts();
07692    while ((context = ast_walk_contexts(context))) {
07693       while ((eroot = ast_walk_context_extensions(context, eroot))) {
07694          while ((e = ast_walk_extension_priorities(eroot, e))) {
07695             if (e->cached_app == app)
07696                e->cached_app = NULL;
07697          }
07698       }
07699    }
07700    ast_unlock_contexts();
07701 
07702    return;
07703 }

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

01653 {
01654    /* if this extension is marked as deleted, then skip this -- if it never shows
01655       on the scoreboard, it will never be found, nor will halt the traversal. */
01656    if (deleted)
01657       return;
01658    board->total_specificity = spec;
01659    board->total_length = length;
01660    board->exten = exten;
01661    board->last_char = last;
01662    board->node = node;
01663 #ifdef NEED_DEBUG_HERE
01664    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01665 #endif
01666 }

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

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

09883 {
09884    int res;
09885    struct ast_frame *f;
09886    double waitsec;
09887    int waittime;
09888 
09889    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
09890       waitsec = -1;
09891    if (waitsec > -1) {
09892       waittime = waitsec * 1000.0;
09893       ast_safe_sleep(chan, waittime);
09894    } else do {
09895       res = ast_waitfor(chan, -1);
09896       if (res < 0)
09897          return;
09898       f = ast_read(chan);
09899       if (f)
09900          ast_frfree(f);
09901    } while(f);
09902 }

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

03878                                                                   {
03879    int res = 0;
03880    struct ast_custom_escalating_function *cur_escalation;
03881 
03882    AST_RWLIST_RDLOCK(&escalation_root);
03883    AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) {
03884       if (cur_escalation->acf == acf) {
03885          res = cur_escalation->write_escalates;
03886          break;
03887       }
03888    }
03889    AST_RWLIST_UNLOCK(&escalation_root);
03890    return res;
03891 }


Variable Documentation

int autofallthrough = 1 [static]

Definition at line 1220 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 849 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 1294 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 1299 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 1228 of file pbx.c.

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

const char* const days[] [static]

Definition at line 8285 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 1225 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

Definition at line 862 of file pbx.c.

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

Definition at line 3646 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

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

Definition at line 3578 of file pbx.c.

Referenced by acf_exception_read(), and raise_exception().

int extenpatternmatchnew = 0 [static]

Definition at line 1221 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 865 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 1314 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 10962 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 870 of file pbx.c.

Referenced by ast_readconfig().

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

Definition at line 1227 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

const char* const months[] [static]

Definition at line 8297 of file pbx.c.

Referenced by ast_build_timing().

char* overrideswitch = NULL [static]

Definition at line 1222 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 7665 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 10967 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 10023 of file pbx.c.

Referenced by pbx_builtin_resetcdr().

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

Definition at line 1305 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 864 of file pbx.c.

Referenced by pbx_find_extension().

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

Definition at line 10114 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 870 of file pbx.c.

Referenced by ast_thread_inhibit_escalations(), and thread_inhibits_escalations().

int totalcalls [static]

Definition at line 1229 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 857 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1