Fri Feb 10 06:36:53 2012

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 "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/cel.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
#include "asterisk/astobj2.h"

Include dependency graph for pbx.c:

Go to the source code of this file.

Data Structures

struct  acf_root
struct  app_tmp
struct  apps
struct  ast_app
 ast_app: A registered application More...
struct  ast_context
 ast_context: An extension context More...
struct  ast_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_hintdevice
 Structure for dial plan hint devices. More...
struct  ast_ignorepat
 ast_ignorepat: Ignore patterns in dial plan More...
struct  ast_include
 ast_include: include= support in extensions.conf More...
struct  ast_state_cb
 ast_state_cb: An extension state notify register item More...
struct  ast_sw
 ast_sw: Switch statement in extensions.conf More...
struct  async_stat
struct  cfextension_states
struct  dialplan_counters
 Counters for the show dialplan manager command. More...
struct  fake_context
struct  match_char
 match_char: forms a syntax tree for quick matching of extension patterns More...
struct  pattern_node
struct  pbx_builtin
 Declaration of builtin applications. More...
struct  pbx_exception
struct  scoreboard
struct  statechange
struct  store_hint
struct  store_hints
struct  switches

Defines

#define AST_PBX_MAX_STACK   128
#define BACKGROUND_MATCHEXTEN   (1 << 2)
#define BACKGROUND_NOANSWER   (1 << 1)
#define BACKGROUND_PLAYBACK   (1 << 3)
#define BACKGROUND_SKIP   (1 << 0)
#define EXT_DATA_SIZE   8192
#define HASH_EXTENHINT_SIZE   563
#define HINTDEVICE_DATA_LENGTH   16
#define INC_DST_OVERFLOW_CHECK
#define NEW_MATCHER_CHK_MATCH
#define NEW_MATCHER_RECURSE
#define SAY_STUBS
#define STATUS_NO_CONTEXT   1
#define STATUS_NO_EXTENSION   2
#define STATUS_NO_LABEL   4
#define STATUS_NO_PRIORITY   3
#define STATUS_SUCCESS   5
#define SWITCH_DATA_LENGTH   256
#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3
#define VAR_NORMAL   1
#define VAR_SOFTTRAN   2
#define WAITEXTEN_DIALTONE   (1 << 1)
#define WAITEXTEN_MOH   (1 << 0)

Functions

void __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function.
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
static void __ast_internal_context_destroy (struct ast_context *con)
static enum ast_pbx_result __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args)
static void __fini_acf_root (void)
static void __fini_apps (void)
static void __fini_switches (void)
static void __init_acf_root (void)
static void __init_apps (void)
static void __init_extensionstate_buf (void)
static void __init_hintdevice_data (void)
static void __init_switch_data (void)
static void __init_switches (void)
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static int acf_retrieve_docs (struct ast_custom_function *acf)
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
static int add_hintdevice (struct ast_hint *hint, const char *devicelist)
 add hintdevice structure and link it into the container.
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, struct ast_format_cap *cap, const char *addr, 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, struct ast_format_cap *cap, const char *addr, 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_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 *a, const char *b)
 the full routine to compare extensions in rules.
static int ext_cmp1 (const char **p, unsigned char *bitwise)
 helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
static int ext_strncpy (char *dst, const char *src, int len)
 copy a string skipping whitespace
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
static struct ast_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)
 Find Hint by callback id.
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 hintdevice_cmp_multiple (void *obj, void *arg, int flags)
static void hintdevice_destroy (void *obj)
static int hintdevice_hash_cb (const void *obj, const int flags)
static int hintdevice_remove_cb (void *deviceobj, void *arg, int flags)
static int hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int include_valid (struct ast_include *i)
static int increase_call_count (const struct ast_channel *c)
 Increase call count for channel.
static void insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node)
int load_pbx (void)
static int lookup_name (const char *s, const char *const names[], int max)
 Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
static void manager_dpsendack (struct mansession *s, const struct message *m)
 Send ack once.
static int manager_show_dialplan (struct mansession *s, const struct message *m)
 Manager listing of dial plan.
static int manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
 Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not.
static int matchcid (const char *cidpattern, const char *callerid)
static void new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name.
static int pbx_builtin_answer (struct ast_channel *, const char *)
static int pbx_builtin_background (struct ast_channel *, const char *)
static int pbx_builtin_busy (struct ast_channel *, const char *)
void pbx_builtin_clear_globals (void)
static int pbx_builtin_congestion (struct ast_channel *, const char *)
static int pbx_builtin_execiftime (struct ast_channel *, const char *)
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable.
static int pbx_builtin_goto (struct ast_channel *, const char *)
static int pbx_builtin_gotoif (struct ast_channel *, const char *)
static int pbx_builtin_gotoiftime (struct ast_channel *, const char *)
static int pbx_builtin_hangup (struct ast_channel *, const char *)
static int pbx_builtin_importvar (struct ast_channel *, const char *)
static int pbx_builtin_incomplete (struct ast_channel *, const char *)
static int pbx_builtin_noop (struct ast_channel *, const char *)
static int pbx_builtin_proceeding (struct ast_channel *, const char *)
static int pbx_builtin_progress (struct ast_channel *, const char *)
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value.
int pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason)
static int pbx_builtin_resetcdr (struct ast_channel *, const char *)
static int pbx_builtin_ringing (struct ast_channel *, const char *)
static int pbx_builtin_saycharacters (struct ast_channel *, const char *)
static int pbx_builtin_saydigits (struct ast_channel *, const char *)
static int pbx_builtin_saynumber (struct ast_channel *, const char *)
static int pbx_builtin_sayphonetic (struct ast_channel *, const char *)
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
 Create a human-readable string, specifying all variables and their corresponding values.
static int pbx_builtin_setamaflags (struct ast_channel *, const char *)
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
int pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
static int pbx_builtin_wait (struct ast_channel *, const char *)
static int pbx_builtin_waitexten (struct ast_channel *, const char *)
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
static void pbx_destroy (struct ast_pbx *p)
int pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data)
 Execute an application.
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
 The return value depends on the action:.
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)
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_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
static void * pbx_thread (void *data)
static void print_app_docs (struct ast_app *aa, int fd)
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
static int raise_exception (struct ast_channel *chan, const char *reason, int priority)
static int remove_hintdevice (struct ast_hint *hint)
static void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
static int show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
static int statecbs_cmp (void *obj, void *arg, int flags)
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace.
static int testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
static struct ast_extentrie_find_next_match (struct match_char *node)
static void unreference_cached_app (struct ast_app *app)
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
static void wait_for_hangup (struct ast_channel *chan, const void *data)

Variables

static int autofallthrough = 1
static struct ast_app_option background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },}
static struct pbx_builtin builtins []
 Declaration of builtin applications.
static ast_mutex_t conlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Lock for the ast_context list.
static ast_mutex_t context_merge_lock = { PTHREAD_MUTEX_INITIALIZER , 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 = { {0} , NULL, 1 }
static struct ast_threadstorage hintdevice_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_hintdevice_data , .custom_init = NULL , }
static struct ao2_containerhintdevices
 Container for hint devices.
static struct ao2_containerhints
static struct ast_data_handler hints_data_provider
static ast_mutex_t maxcalllock = { PTHREAD_MUTEX_INITIALIZER , 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 int totalcalls
static struct ast_app_option waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },}


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file pbx.c.


Define Documentation

#define AST_PBX_MAX_STACK   128

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

Definition at line 1563 of file pbx.c.

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 783 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 782 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 784 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 781 of file pbx.c.

Referenced by pbx_builtin_background().

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

Referenced by pbx_extension_helper(), and realtime_exec().

#define HASH_EXTENHINT_SIZE   563

Definition at line 963 of file pbx.c.

Referenced by ast_pbx_init().

#define HINTDEVICE_DATA_LENGTH   16

Definition at line 956 of file pbx.c.

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

#define STATUS_NO_CONTEXT   1

Definition at line 2801 of file pbx.c.

#define STATUS_NO_EXTENSION   2

Definition at line 2802 of file pbx.c.

#define STATUS_NO_LABEL   4

Definition at line 2804 of file pbx.c.

#define STATUS_NO_PRIORITY   3

Definition at line 2803 of file pbx.c.

#define STATUS_SUCCESS   5

Definition at line 2805 of file pbx.c.

#define SWITCH_DATA_LENGTH   256

Definition at line 773 of file pbx.c.

#define VAR_BUF_SIZE   4096

#define VAR_HARDTRAN   3

Definition at line 779 of file pbx.c.

#define VAR_NORMAL   1

Definition at line 777 of file pbx.c.

#define VAR_SOFTTRAN   2

Definition at line 778 of file pbx.c.

#define WAITEXTEN_DIALTONE   (1 << 1)

Definition at line 794 of file pbx.c.

Referenced by pbx_builtin_waitexten().

#define WAITEXTEN_MOH   (1 << 0)

Definition at line 793 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 9280 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_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().

09281 {
09282    struct ast_context *tmp, *tmpl=NULL;
09283    struct ast_exten *exten_item, *prio_item;
09284 
09285    for (tmp = list; tmp; ) {
09286       struct ast_context *next = NULL; /* next starting point */
09287          /* The following code used to skip forward to the next
09288             context with matching registrar, but this didn't
09289             make sense; individual priorities registrar'd to
09290             the matching registrar could occur in any context! */
09291       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
09292       if (con) {
09293          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
09294             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
09295             if ( !strcasecmp(tmp->name, con->name) ) {
09296                break;   /* found it */
09297             }
09298          }
09299       }
09300 
09301       if (!tmp)   /* not found, we are done */
09302          break;
09303       ast_wrlock_context(tmp);
09304 
09305       if (registrar) {
09306          /* then search thru and remove any extens that match registrar. */
09307          struct ast_hashtab_iter *exten_iter;
09308          struct ast_hashtab_iter *prio_iter;
09309          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
09310          struct ast_include *i, *pi = NULL, *ni = NULL;
09311          struct ast_sw *sw = NULL;
09312 
09313          /* remove any ignorepats whose registrar matches */
09314          for (ip = tmp->ignorepats; ip; ip = ipn) {
09315             ipn = ip->next;
09316             if (!strcmp(ip->registrar, registrar)) {
09317                if (ipl) {
09318                   ipl->next = ip->next;
09319                   ast_free(ip);
09320                   continue; /* don't change ipl */
09321                } else {
09322                   tmp->ignorepats = ip->next;
09323                   ast_free(ip);
09324                   continue; /* don't change ipl */
09325                }
09326             }
09327             ipl = ip;
09328          }
09329          /* remove any includes whose registrar matches */
09330          for (i = tmp->includes; i; i = ni) {
09331             ni = i->next;
09332             if (strcmp(i->registrar, registrar) == 0) {
09333                /* remove from list */
09334                if (pi) {
09335                   pi->next = i->next;
09336                   /* free include */
09337                   ast_free(i);
09338                   continue; /* don't change pi */
09339                } else {
09340                   tmp->includes = i->next;
09341                   /* free include */
09342                   ast_free(i);
09343                   continue; /* don't change pi */
09344                }
09345             }
09346             pi = i;
09347          }
09348          /* remove any switches whose registrar matches */
09349          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
09350             if (strcmp(sw->registrar,registrar) == 0) {
09351                AST_LIST_REMOVE_CURRENT(list);
09352                ast_free(sw);
09353             }
09354          }
09355          AST_LIST_TRAVERSE_SAFE_END;
09356 
09357          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
09358             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
09359             while ((exten_item=ast_hashtab_next(exten_iter))) {
09360                int end_traversal = 1;
09361                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
09362                while ((prio_item=ast_hashtab_next(prio_iter))) {
09363                   char extension[AST_MAX_EXTENSION];
09364                   char cidmatch[AST_MAX_EXTENSION];
09365                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
09366                      continue;
09367                   }
09368                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
09369                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
09370                   /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */
09371                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
09372                   if (prio_item->cidmatch) {
09373                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
09374                   }
09375                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1);
09376                }
09377                /* Explanation:
09378                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
09379                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
09380                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
09381                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
09382                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
09383                 * free the iterator
09384                 */
09385                if (end_traversal) {
09386                   ast_hashtab_end_traversal(prio_iter);
09387                } else {
09388                   ast_free(prio_iter);
09389                }
09390             }
09391             ast_hashtab_end_traversal(exten_iter);
09392          }
09393 
09394          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
09395          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
09396             another registrar. It's not empty if there are any extensions */
09397          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
09398             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09399             ast_hashtab_remove_this_object(contexttab, tmp);
09400 
09401             next = tmp->next;
09402             if (tmpl)
09403                tmpl->next = next;
09404             else
09405                contexts = next;
09406             /* Okay, now we're safe to let it go -- in a sense, we were
09407                ready to let it go as soon as we locked it. */
09408             ast_unlock_context(tmp);
09409             __ast_internal_context_destroy(tmp);
09410          } else {
09411             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
09412                     tmp->refcount, tmp->root);
09413             ast_unlock_context(tmp);
09414             next = tmp->next;
09415             tmpl = tmp;
09416          }
09417       } else if (con) {
09418          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
09419          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09420          ast_hashtab_remove_this_object(contexttab, tmp);
09421 
09422          next = tmp->next;
09423          if (tmpl)
09424             tmpl->next = next;
09425          else
09426             contexts = next;
09427          /* Okay, now we're safe to let it go -- in a sense, we were
09428             ready to let it go as soon as we locked it. */
09429          ast_unlock_context(tmp);
09430          __ast_internal_context_destroy(tmp);
09431       }
09432 
09433       /* if we have a specific match, we are done, otherwise continue */
09434       tmp = con ? NULL : next;
09435    }
09436 }

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 3715 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_msg_init(), and load_pbx().

03716 {
03717    struct ast_custom_function *cur;
03718    char tmps[80];
03719 
03720    if (!acf) {
03721       return -1;
03722    }
03723 
03724    acf->mod = mod;
03725 #ifdef AST_XML_DOCS
03726    acf->docsrc = AST_STATIC_DOC;
03727 #endif
03728 
03729    if (acf_retrieve_docs(acf)) {
03730       return -1;
03731    }
03732 
03733    AST_RWLIST_WRLOCK(&acf_root);
03734 
03735    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03736       if (!strcmp(acf->name, cur->name)) {
03737          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03738          AST_RWLIST_UNLOCK(&acf_root);
03739          return -1;
03740       }
03741    }
03742 
03743    /* Store in alphabetical order */
03744    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03745       if (strcasecmp(acf->name, cur->name) < 0) {
03746          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03747          break;
03748       }
03749    }
03750    AST_RWLIST_TRAVERSE_SAFE_END;
03751 
03752    if (!cur) {
03753       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03754    }
03755 
03756    AST_RWLIST_UNLOCK(&acf_root);
03757 
03758    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03759 
03760    return 0;
03761 }

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

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

10683 {
10684    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
10685 
10686    if (!chan)
10687       return -2;
10688 
10689    if (context == NULL)
10690       context = chan->context;
10691    if (exten == NULL)
10692       exten = chan->exten;
10693 
10694    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
10695    if (ast_exists_extension(chan, context, exten, priority,
10696       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
10697       return goto_func(chan, context, exten, priority);
10698    else {
10699       return AST_PBX_GOTO_FAILED;
10700    }
10701 }

static void __ast_internal_context_destroy ( struct ast_context con  )  [static]

Definition at line 9233 of file pbx.c.

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

Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().

09234 {
09235    struct ast_include *tmpi;
09236    struct ast_sw *sw;
09237    struct ast_exten *e, *el, *en;
09238    struct ast_ignorepat *ipi;
09239    struct ast_context *tmp = con;
09240 
09241    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
09242       struct ast_include *tmpil = tmpi;
09243       tmpi = tmpi->next;
09244       ast_free(tmpil);
09245    }
09246    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
09247       struct ast_ignorepat *ipl = ipi;
09248       ipi = ipi->next;
09249       ast_free(ipl);
09250    }
09251    if (tmp->registrar)
09252       ast_free(tmp->registrar);
09253 
09254    /* destroy the hash tabs */
09255    if (tmp->root_table) {
09256       ast_hashtab_destroy(tmp->root_table, 0);
09257    }
09258    /* and destroy the pattern tree */
09259    if (tmp->pattern_tree)
09260       destroy_pattern_tree(tmp->pattern_tree);
09261 
09262    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
09263       ast_free(sw);
09264    for (e = tmp->root; e;) {
09265       for (en = e->peer; en;) {
09266          el = en;
09267          en = en->peer;
09268          destroy_exten(el);
09269       }
09270       el = e;
09271       e = e->next;
09272       destroy_exten(el);
09273    }
09274    tmp->root = NULL;
09275    ast_rwlock_destroy(&tmp->lock);
09276    ast_free(tmp);
09277 }

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 5099 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_name(), 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().

05101 {
05102    int found = 0; /* set if we find at least one match */
05103    int res = 0;
05104    int autoloopflag;
05105    int error = 0;    /* set an error conditions */
05106 
05107    /* A little initial setup here */
05108    if (c->pbx) {
05109       ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
05110       /* XXX and now what ? */
05111       ast_free(c->pbx);
05112    }
05113    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
05114       return -1;
05115    /* Set reasonable defaults */
05116    c->pbx->rtimeoutms = 10000;
05117    c->pbx->dtimeoutms = 5000;
05118 
05119    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
05120    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
05121 
05122    if (ast_strlen_zero(c->exten)) {
05123       /* If not successful fall back to 's' - but only if there is no given exten  */
05124       ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", ast_channel_name(c), c->context, c->exten, c->priority);
05125       /* XXX the original code used the existing priority in the call to
05126        * ast_exists_extension(), and reset it to 1 afterwards.
05127        * I believe the correct thing is to set it to 1 immediately.
05128       */
05129       set_ext_pri(c, "s", 1);
05130    }
05131 
05132    ast_channel_lock(c);
05133    if (c->cdr) {
05134       /* allow CDR variables that have been collected after channel was created to be visible during call */
05135       ast_cdr_update(c);
05136    }
05137    ast_channel_unlock(c);
05138    for (;;) {
05139       char dst_exten[256]; /* buffer to accumulate digits */
05140       int pos = 0;      /* XXX should check bounds */
05141       int digit = 0;
05142       int invalid = 0;
05143       int timeout = 0;
05144 
05145       /* loop on priorities in this context/exten */
05146       while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05147          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05148          &found, 1))) {
05149          if (!ast_check_hangup(c)) {
05150             ++c->priority;
05151             continue;
05152          }
05153 
05154          /* Check softhangup flags. */
05155          if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05156             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05157             continue;
05158          }
05159          if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05160             if (ast_exists_extension(c, c->context, "T", 1,
05161                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05162                set_ext_pri(c, "T", 1);
05163                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05164                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05165                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05166                continue;
05167             } else if (ast_exists_extension(c, c->context, "e", 1,
05168                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05169                raise_exception(c, "ABSOLUTETIMEOUT", 1);
05170                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05171                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05172                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05173                continue;
05174             }
05175 
05176             /* Call timed out with no special extension to jump to. */
05177             error = 1;
05178             break;
05179          }
05180          ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
05181             c->exten, c->priority);
05182          error = 1;
05183          break;
05184       } /* end while  - from here on we can use 'break' to go out */
05185       if (found && res) {
05186          /* Something bad happened, or a hangup has been requested. */
05187          if (strchr("0123456789ABCDEF*#", res)) {
05188             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
05189             pos = 0;
05190             dst_exten[pos++] = digit = res;
05191             dst_exten[pos] = '\0';
05192          } else if (res == AST_PBX_INCOMPLETE) {
05193             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c));
05194             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c));
05195 
05196             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
05197             if (!ast_matchmore_extension(c, c->context, c->exten, 1,
05198                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05199                invalid = 1;
05200             } else {
05201                ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
05202                digit = 1;
05203                pos = strlen(dst_exten);
05204             }
05205          } else {
05206             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c));
05207             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c));
05208 
05209             if ((res == AST_PBX_ERROR)
05210                && ast_exists_extension(c, c->context, "e", 1,
05211                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05212                /* if we are already on the 'e' exten, don't jump to it again */
05213                if (!strcmp(c->exten, "e")) {
05214                   ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c));
05215                   error = 1;
05216                } else {
05217                   raise_exception(c, "ERROR", 1);
05218                   continue;
05219                }
05220             }
05221 
05222             if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05223                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05224                continue;
05225             }
05226             if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05227                if (ast_exists_extension(c, c->context, "T", 1,
05228                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05229                   set_ext_pri(c, "T", 1);
05230                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05231                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05232                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05233                   continue;
05234                } else if (ast_exists_extension(c, c->context, "e", 1,
05235                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05236                   raise_exception(c, "ABSOLUTETIMEOUT", 1);
05237                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05238                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05239                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05240                   continue;
05241                }
05242                /* Call timed out with no special extension to jump to. */
05243             }
05244             ast_channel_lock(c);
05245             if (c->cdr) {
05246                ast_cdr_update(c);
05247             }
05248             ast_channel_unlock(c);
05249             error = 1;
05250             break;
05251          }
05252       }
05253       if (error)
05254          break;
05255 
05256       /*!\note
05257        * We get here on a failure of some kind:  non-existing extension or
05258        * hangup.  We have options, here.  We can either catch the failure
05259        * and continue, or we can drop out entirely. */
05260 
05261       if (invalid
05262          || !ast_exists_extension(c, c->context, c->exten, 1,
05263             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05264          /*!\note
05265           * If there is no match at priority 1, it is not a valid extension anymore.
05266           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
05267           * neither exist.
05268           */
05269          if (ast_exists_extension(c, c->context, "i", 1,
05270             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05271             ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, ast_channel_name(c));
05272             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
05273             set_ext_pri(c, "i", 1);
05274          } else if (ast_exists_extension(c, c->context, "e", 1,
05275             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05276             raise_exception(c, "INVALID", 1);
05277          } else {
05278             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
05279                ast_channel_name(c), c->exten, c->context);
05280             error = 1; /* we know what to do with it */
05281             break;
05282          }
05283       } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05284          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
05285          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05286       } else { /* keypress received, get more digits for a full extension */
05287          int waittime = 0;
05288          if (digit)
05289             waittime = c->pbx->dtimeoutms;
05290          else if (!autofallthrough)
05291             waittime = c->pbx->rtimeoutms;
05292          if (!waittime) {
05293             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
05294             if (!status)
05295                status = "UNKNOWN";
05296             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
05297             if (!strcasecmp(status, "CONGESTION"))
05298                res = pbx_builtin_congestion(c, "10");
05299             else if (!strcasecmp(status, "CHANUNAVAIL"))
05300                res = pbx_builtin_congestion(c, "10");
05301             else if (!strcasecmp(status, "BUSY"))
05302                res = pbx_builtin_busy(c, "10");
05303             error = 1; /* XXX disable message */
05304             break;   /* exit from the 'for' loop */
05305          }
05306 
05307          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
05308             break;
05309          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
05310             timeout = 1;
05311          if (!timeout
05312             && ast_exists_extension(c, c->context, dst_exten, 1,
05313                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */
05314             set_ext_pri(c, dst_exten, 1);
05315          } else {
05316             /* No such extension */
05317             if (!timeout && !ast_strlen_zero(dst_exten)) {
05318                /* An invalid extension */
05319                if (ast_exists_extension(c, c->context, "i", 1,
05320                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05321                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, ast_channel_name(c));
05322                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
05323                   set_ext_pri(c, "i", 1);
05324                } else if (ast_exists_extension(c, c->context, "e", 1,
05325                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05326                   raise_exception(c, "INVALID", 1);
05327                } else {
05328                   ast_log(LOG_WARNING,
05329                      "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
05330                      dst_exten, c->context);
05331                   found = 1; /* XXX disable message */
05332                   break;
05333                }
05334             } else {
05335                /* A simple timeout */
05336                if (ast_exists_extension(c, c->context, "t", 1,
05337                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05338                   ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
05339                   set_ext_pri(c, "t", 1);
05340                } else if (ast_exists_extension(c, c->context, "e", 1,
05341                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05342                   raise_exception(c, "RESPONSETIMEOUT", 1);
05343                } else {
05344                   ast_log(LOG_WARNING,
05345                      "Timeout, but no rule 't' or 'e' in context '%s'\n",
05346                      c->context);
05347                   found = 1; /* XXX disable message */
05348                   break;
05349                }
05350             }
05351          }
05352          ast_channel_lock(c);
05353          if (c->cdr) {
05354             ast_verb(2, "CDR updated on %s\n",ast_channel_name(c));
05355             ast_cdr_update(c);
05356          }
05357          ast_channel_unlock(c);
05358       }
05359    }
05360 
05361    if (!found && !error) {
05362       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
05363    }
05364 
05365    if (!args || !args->no_hangup_chan) {
05366       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
05367    }
05368 
05369    if ((!args || !args->no_hangup_chan)
05370       && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN)
05371       && ast_exists_extension(c, c->context, "h", 1,
05372          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05373       set_ext_pri(c, "h", 1);
05374       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
05375          ast_cdr_end(c->cdr);
05376       }
05377       while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05378          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05379          &found, 1)) == 0) {
05380          c->priority++;
05381       }
05382       if (found && res) {
05383          /* Something bad happened, or a hangup has been requested. */
05384          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c));
05385          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c));
05386       }
05387    }
05388    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
05389    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
05390    pbx_destroy(c->pbx);
05391    c->pbx = NULL;
05392 
05393    if (!args || !args->no_hangup_chan) {
05394       ast_hangup(c);
05395    }
05396 
05397    return 0;
05398 }

static void __fini_acf_root ( void   )  [static]

Definition at line 1272 of file pbx.c.

01275 {

static void __fini_apps ( void   )  [static]

Definition at line 1327 of file pbx.c.

01361 {

static void __fini_switches ( void   )  [static]

Definition at line 1329 of file pbx.c.

01361 {

static void __init_acf_root ( void   )  [static]

Definition at line 1272 of file pbx.c.

01275 {

static void __init_apps ( void   )  [static]

Definition at line 1327 of file pbx.c.

01361 {

static void __init_extensionstate_buf ( void   )  [static]

Definition at line 807 of file pbx.c.

00810 : An extension

static void __init_hintdevice_data ( void   )  [static]

Definition at line 957 of file pbx.c.

00974 {

static void __init_switch_data ( void   )  [static]

Definition at line 806 of file pbx.c.

00810 : An extension

static void __init_switches ( void   )  [static]

Definition at line 1329 of file pbx.c.

01361 {

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

Definition at line 2573 of file pbx.c.

References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.

Referenced by extension_match_core().

02574 {
02575    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
02576 
02577 #ifdef NEED_DEBUG_HERE
02578    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
02579 #endif
02580 
02581    if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */
02582 #ifdef NEED_DEBUG_HERE
02583       ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
02584 #endif
02585       return 1;
02586    }
02587 
02588    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
02589       int ld = strlen(data), lp = strlen(pattern);
02590 
02591       if (lp < ld) {    /* pattern too short, cannot match */
02592 #ifdef NEED_DEBUG_HERE
02593          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
02594 #endif
02595          return 0;
02596       }
02597       /* depending on the mode, accept full or partial match or both */
02598       if (mode == E_MATCH) {
02599 #ifdef NEED_DEBUG_HERE
02600          ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data);
02601 #endif
02602          return !strcmp(pattern, data); /* 1 on match, 0 on fail */
02603       }
02604       if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */
02605 #ifdef NEED_DEBUG_HERE
02606          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
02607 #endif
02608          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
02609       } else {
02610 #ifdef NEED_DEBUG_HERE
02611          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
02612 #endif
02613          return 0;
02614       }
02615    }
02616    pattern++; /* skip leading _ */
02617    /*
02618     * XXX below we stop at '/' which is a separator for the CID info. However we should
02619     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
02620     */
02621    while (*data && *pattern && *pattern != '/') {
02622       const char *end;
02623 
02624       if (*data == '-') { /* skip '-' in data (just a separator) */
02625          data++;
02626          continue;
02627       }
02628       switch (toupper(*pattern)) {
02629       case '[':   /* a range */
02630          end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
02631          if (end == NULL) {
02632             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02633             return 0;   /* unconditional failure */
02634          }
02635          for (pattern++; pattern != end; pattern++) {
02636             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
02637                if (*data >= pattern[0] && *data <= pattern[2])
02638                   break;   /* match found */
02639                else {
02640                   pattern += 2; /* skip a total of 3 chars */
02641                   continue;
02642                }
02643             } else if (*data == pattern[0])
02644                break;   /* match found */
02645          }
02646          if (pattern == end) {
02647 #ifdef NEED_DEBUG_HERE
02648             ast_log(LOG_NOTICE,"return (0) when pattern==end\n");
02649 #endif
02650             return 0;
02651          }
02652          pattern = end; /* skip and continue */
02653          break;
02654       case 'N':
02655          if (*data < '2' || *data > '9') {
02656 #ifdef NEED_DEBUG_HERE
02657             ast_log(LOG_NOTICE,"return (0) N is matched\n");
02658 #endif
02659             return 0;
02660          }
02661          break;
02662       case 'X':
02663          if (*data < '0' || *data > '9') {
02664 #ifdef NEED_DEBUG_HERE
02665             ast_log(LOG_NOTICE,"return (0) X is matched\n");
02666 #endif
02667             return 0;
02668          }
02669          break;
02670       case 'Z':
02671          if (*data < '1' || *data > '9') {
02672 #ifdef NEED_DEBUG_HERE
02673             ast_log(LOG_NOTICE,"return (0) Z is matched\n");
02674 #endif
02675             return 0;
02676          }
02677          break;
02678       case '.':   /* Must match, even with more digits */
02679 #ifdef NEED_DEBUG_HERE
02680          ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
02681 #endif
02682          return 1;
02683       case '!':   /* Early match */
02684 #ifdef NEED_DEBUG_HERE
02685          ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
02686 #endif
02687          return 2;
02688       case ' ':
02689       case '-':   /* Ignore these in patterns */
02690          data--; /* compensate the final data++ */
02691          break;
02692       default:
02693          if (*data != *pattern) {
02694 #ifdef NEED_DEBUG_HERE
02695             ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
02696 #endif
02697             return 0;
02698          }
02699       }
02700       data++;
02701       pattern++;
02702    }
02703    if (*data)        /* data longer than pattern, no match */ {
02704 #ifdef NEED_DEBUG_HERE
02705       ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
02706 #endif
02707       return 0;
02708    }
02709 
02710    /*
02711     * match so far, but ran off the end of the data.
02712     * Depending on what is next, determine match or not.
02713     */
02714    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
02715 #ifdef NEED_DEBUG_HERE
02716       ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
02717 #endif
02718       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
02719    } else if (*pattern == '!')   {     /* early match */
02720 #ifdef NEED_DEBUG_HERE
02721       ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
02722 #endif
02723       return 2;
02724    } else {                /* partial match */
02725 #ifdef NEED_DEBUG_HERE
02726       ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
02727 #endif
02728       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
02729    }
02730 }

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

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

03453 {
03454    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03455    struct pbx_exception *exception = NULL;
03456    if (!ds || !ds->data)
03457       return -1;
03458    exception = ds->data;
03459    if (!strcasecmp(data, "REASON"))
03460       ast_copy_string(buf, exception->reason, buflen);
03461    else if (!strcasecmp(data, "CONTEXT"))
03462       ast_copy_string(buf, exception->context, buflen);
03463    else if (!strncasecmp(data, "EXTEN", 5))
03464       ast_copy_string(buf, exception->exten, buflen);
03465    else if (!strcasecmp(data, "PRIORITY"))
03466       snprintf(buf, buflen, "%d", exception->priority);
03467    else
03468       return -1;
03469    return 0;
03470 }

static int acf_retrieve_docs ( struct ast_custom_function acf  )  [static]

Definition at line 3670 of file pbx.c.

References ast_custom_function::arguments, ast_free, ast_module_name(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, desc, ast_custom_function::desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, and ast_custom_function::syntax.

Referenced by __ast_custom_function_register().

03671 {
03672 #ifdef AST_XML_DOCS
03673    char *tmpxml;
03674 
03675    /* Let's try to find it in the Documentation XML */
03676    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
03677       return 0;
03678    }
03679 
03680    if (ast_string_field_init(acf, 128)) {
03681       return -1;
03682    }
03683 
03684    /* load synopsis */
03685    tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
03686    ast_string_field_set(acf, synopsis, tmpxml);
03687    ast_free(tmpxml);
03688 
03689    /* load description */
03690    tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
03691    ast_string_field_set(acf, desc, tmpxml);
03692    ast_free(tmpxml);
03693 
03694    /* load syntax */
03695    tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
03696    ast_string_field_set(acf, syntax, tmpxml);
03697    ast_free(tmpxml);
03698 
03699    /* load arguments */
03700    tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
03701    ast_string_field_set(acf, arguments, tmpxml);
03702    ast_free(tmpxml);
03703 
03704    /* load seealso */
03705    tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
03706    ast_string_field_set(acf, seealso, tmpxml);
03707    ast_free(tmpxml);
03708 
03709    acf->docsrc = AST_XML_DOC;
03710 #endif
03711 
03712    return 0;
03713 }

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

Definition at line 2251 of file pbx.c.

References add_pattern_node(), already_in_tree(), ARRAY_LEN, ast_copy_string(), ast_debug, ast_log(), pattern_node::buf, ast_exten::cidmatch, match_char::deleted, match_char::exten, ast_exten::exten, get_pattern_node(), 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().

02252 {
02253    struct match_char *m1 = NULL;
02254    struct match_char *m2 = NULL;
02255    struct match_char **m0;
02256    const char *pos;
02257    int already;
02258    int pattern = 0;
02259    int idx_cur;
02260    int idx_next;
02261    char extenbuf[512];
02262    struct pattern_node pat_node[2];
02263 
02264    if (e1->matchcid) {
02265       if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
02266          ast_log(LOG_ERROR,
02267             "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
02268             e1->exten, e1->cidmatch);
02269          return NULL;
02270       }
02271       sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe.  We just checked. */
02272    } else {
02273       ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
02274    }
02275 
02276 #ifdef NEED_DEBUG
02277    ast_debug(1, "Adding exten %s to tree\n", extenbuf);
02278 #endif
02279    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
02280    m0 = &con->pattern_tree;
02281    already = 1;
02282 
02283    pos = extenbuf;
02284    if (*pos == '_') {
02285       pattern = 1;
02286       ++pos;
02287    }
02288    idx_cur = 0;
02289    pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
02290    for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
02291       idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
02292       pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
02293 
02294       /* See about adding node to tree. */
02295       m2 = NULL;
02296       if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
02297          && m2->next_char) {
02298          if (!pat_node[idx_next].buf[0]) {
02299             /*
02300              * This is the end of the pattern, but not the end of the tree.
02301              * Mark this node with the exten... a shorter pattern might win
02302              * if the longer one doesn't match.
02303              */
02304             if (findonly) {
02305                return m2;
02306             }
02307             if (m2->exten) {
02308                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02309                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02310             }
02311             m2->exten = e1;
02312             m2->deleted = 0;
02313          }
02314          m1 = m2->next_char; /* m1 points to the node to compare against */
02315          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
02316       } else { /* not already OR not m2 OR nor m2->next_char */
02317          if (m2) {
02318             if (findonly) {
02319                return m2;
02320             }
02321             m1 = m2; /* while m0 stays the same */
02322          } else {
02323             if (findonly) {
02324                return m1;
02325             }
02326             m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
02327             if (!m1) { /* m1 is the node just added */
02328                return NULL;
02329             }
02330             m0 = &m1->next_char;
02331          }
02332          if (!pat_node[idx_next].buf[0]) {
02333             if (m2 && m2->exten) {
02334                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02335                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02336             }
02337             m1->deleted = 0;
02338             m1->exten = e1;
02339          }
02340 
02341          /* The 'already' variable is a mini-optimization designed to make it so that we
02342           * don't have to call already_in_tree when we know it will return false.
02343           */
02344          already = 0;
02345       }
02346    }
02347    return m1;
02348 }

static int add_hintdevice ( struct ast_hint hint,
const char *  devicelist 
) [static]

add hintdevice structure and link it into the container.

Definition at line 1047 of file pbx.c.

References ao2_ref, ao2_t_alloc, ao2_t_link, ao2_t_ref, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_hintdevice::hint, ast_hintdevice::hintdevice, hintdevice_data, hintdevice_destroy(), parse(), str, and strsep().

Referenced by ast_add_hint(), and ast_change_hint().

01048 {
01049    struct ast_str *str;
01050    char *parse;
01051    char *cur;
01052    struct ast_hintdevice *device;
01053    int devicelength;
01054 
01055    if (!hint || !devicelist) {
01056       /* Trying to add garbage? Don't bother. */
01057       return 0;
01058    }
01059    if (!(str = ast_str_thread_get(&hintdevice_data, 16))) {
01060       return -1;
01061    }
01062    ast_str_set(&str, 0, "%s", devicelist);
01063    parse = ast_str_buffer(str);
01064 
01065    while ((cur = strsep(&parse, "&"))) {
01066       devicelength = strlen(cur);
01067       device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy,
01068          "allocating a hintdevice structure");
01069       if (!device) {
01070          return -1;
01071       }
01072       strcpy(device->hintdevice, cur);
01073       ao2_ref(hint, +1);
01074       device->hint = hint;
01075       ao2_t_link(hintdevices, device, "Linking device into hintdevice container.");
01076       ao2_t_ref(device, -1, "hintdevice is linked so we can unref");
01077    }
01078 
01079    return 0;
01080 }

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

02054 {
02055    struct match_char *m;
02056 
02057    if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
02058       return NULL;
02059    }
02060 
02061    /* strcpy is safe here since we know its size and have allocated
02062     * just enough space for when we allocated m
02063     */
02064    strcpy(m->x, pattern->buf);
02065 
02066    /* the specificity scores are the same as used in the old
02067       pattern matcher. */
02068    m->is_pattern = is_pattern;
02069    if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
02070       m->specificity = 0x0832;
02071    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
02072       m->specificity = 0x0931;
02073    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
02074       m->specificity = 0x0a30;
02075    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
02076       m->specificity = 0x18000;
02077    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
02078       m->specificity = 0x28000;
02079    } else {
02080       m->specificity = pattern->specif;
02081    }
02082 
02083    if (!con->pattern_tree) {
02084       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
02085    } else {
02086       if (already) { /* switch to the new regime (traversing vs appending)*/
02087          insert_in_next_chars_alt_char_list(nextcharptr, m);
02088       } else {
02089          insert_in_next_chars_alt_char_list(&current->next_char, m);
02090       }
02091    }
02092 
02093    return m;
02094 }

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

08438 {
08439    struct ast_exten *ep;
08440    struct ast_exten *eh=e;
08441    int repeated_label = 0; /* Track if this label is a repeat, assume no. */
08442 
08443    for (ep = NULL; e ; ep = e, e = e->peer) {
08444       if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
08445          ast_log(LOG_WARNING, "Extension '%s', priority %d in '%s', label '%s' already in use at "
08446                "priority %d\n", tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
08447          repeated_label = 1;
08448       }
08449       if (e->priority >= tmp->priority) {
08450          break;
08451       }
08452    }
08453 
08454    if (repeated_label) {   /* Discard the label since it's a repeat. */
08455       tmp->label = NULL;
08456    }
08457 
08458    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
08459       ast_hashtab_insert_safe(eh->peer_table, tmp);
08460 
08461       if (tmp->label) {
08462          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08463       }
08464       ep->peer = tmp;
08465       return 0;   /* success */
08466    }
08467    if (e->priority == tmp->priority) {
08468       /* Can't have something exactly the same.  Is this a
08469          replacement?  If so, replace, otherwise, bonk. */
08470       if (!replace) {
08471          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
08472          if (tmp->datad) {
08473             tmp->datad(tmp->data);
08474             /* if you free this, null it out */
08475             tmp->data = NULL;
08476          }
08477 
08478          ast_free(tmp);
08479          return -1;
08480       }
08481       /* we are replacing e, so copy the link fields and then update
08482        * whoever pointed to e to point to us
08483        */
08484       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
08485       tmp->peer = e->peer; /* always meaningful */
08486       if (ep)  {     /* We're in the peer list, just insert ourselves */
08487          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
08488 
08489          if (e->label) {
08490             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
08491          }
08492 
08493          ast_hashtab_insert_safe(eh->peer_table,tmp);
08494          if (tmp->label) {
08495             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
08496          }
08497 
08498          ep->peer = tmp;
08499       } else if (el) {     /* We're the first extension. Take over e's functions */
08500          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08501          tmp->peer_table = e->peer_table;
08502          tmp->peer_label_table = e->peer_label_table;
08503          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
08504          ast_hashtab_insert_safe(tmp->peer_table,tmp);
08505          if (e->label) {
08506             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08507          }
08508          if (tmp->label) {
08509             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08510          }
08511 
08512          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08513          ast_hashtab_insert_safe(con->root_table, tmp);
08514          el->next = tmp;
08515          /* The pattern trie points to this exten; replace the pointer,
08516             and all will be well */
08517          if (x) { /* if the trie isn't formed yet, don't sweat this */
08518             if (x->exten) { /* this test for safety purposes */
08519                x->exten = tmp; /* replace what would become a bad pointer */
08520             } else {
08521                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08522             }
08523          }
08524       } else {       /* We're the very first extension.  */
08525          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08526          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08527          ast_hashtab_insert_safe(con->root_table, tmp);
08528          tmp->peer_table = e->peer_table;
08529          tmp->peer_label_table = e->peer_label_table;
08530          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
08531          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08532          if (e->label) {
08533             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08534          }
08535          if (tmp->label) {
08536             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08537          }
08538 
08539          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08540          ast_hashtab_insert_safe(con->root_table, tmp);
08541          con->root = tmp;
08542          /* The pattern trie points to this exten; replace the pointer,
08543             and all will be well */
08544          if (x) { /* if the trie isn't formed yet; no problem */
08545             if (x->exten) { /* this test for safety purposes */
08546                x->exten = tmp; /* replace what would become a bad pointer */
08547             } else {
08548                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08549             }
08550          }
08551       }
08552       if (tmp->priority == PRIORITY_HINT)
08553          ast_change_hint(e,tmp);
08554       /* Destroy the old one */
08555       if (e->datad)
08556          e->datad(e->data);
08557       ast_free(e);
08558    } else { /* Slip ourselves in just before e */
08559       tmp->peer = e;
08560       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
08561       if (ep) {         /* Easy enough, we're just in the peer list */
08562          if (tmp->label) {
08563             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08564          }
08565          ast_hashtab_insert_safe(eh->peer_table, tmp);
08566          ep->peer = tmp;
08567       } else {       /* we are the first in some peer list, so link in the ext list */
08568          tmp->peer_table = e->peer_table;
08569          tmp->peer_label_table = e->peer_label_table;
08570          e->peer_table = 0;
08571          e->peer_label_table = 0;
08572          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08573          if (tmp->label) {
08574             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08575          }
08576          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08577          ast_hashtab_insert_safe(con->root_table, tmp);
08578          if (el)
08579             el->next = tmp;   /* in the middle... */
08580          else
08581             con->root = tmp; /* ... or at the head */
08582          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
08583       }
08584       /* And immediately return success. */
08585       if (tmp->priority == PRIORITY_HINT) {
08586          ast_add_hint(tmp);
08587       }
08588    }
08589    return 0;
08590 }

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

Definition at line 1991 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

01992 {
01993    struct match_char *t;
01994 
01995    if (!current) {
01996       return 0;
01997    }
01998 
01999    for (t = current; t; t = t->alt_char) {
02000       if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
02001          return t;
02002       }
02003    }
02004 
02005    return 0;
02006 }

int ast_active_calls ( void   ) 

Retrieve the number of active calls.

Definition at line 5546 of file pbx.c.

References countcalls.

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

05547 {
05548    return countcalls;
05549 }

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

08274 {
08275    int ret = -1;
08276    struct ast_context *c;
08277 
08278    c = find_context_locked(context);
08279    if (c) {
08280       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08281          application, data, datad, registrar);
08282       ast_unlock_contexts();
08283    }
08284 
08285    return ret;
08286 }

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

References ast_add_extension2_lockopt().

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

08621 {
08622    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
08623       application, data, datad, registrar, 1);
08624 }

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

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

Referenced by ast_add_extension2(), and ast_add_extension_nolock().

08637 {
08638    /*
08639     * Sort extensions (or patterns) according to the rules indicated above.
08640     * These are implemented by the function ext_cmp()).
08641     * All priorities for the same ext/pattern/cid are kept in a list,
08642     * using the 'peer' field  as a link field..
08643     */
08644    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
08645    int res;
08646    int length;
08647    char *p;
08648    char expand_buf[VAR_BUF_SIZE];
08649    struct ast_exten dummy_exten = {0};
08650    char dummy_name[1024];
08651 
08652    if (ast_strlen_zero(extension)) {
08653       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",
08654             con->name);
08655       return -1;
08656    }
08657 
08658    /* If we are adding a hint evalulate in variables and global variables */
08659    if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
08660       struct ast_channel *c = ast_dummy_channel_alloc();
08661 
08662       if (c) {
08663          ast_copy_string(c->exten, extension, sizeof(c->exten));
08664          ast_copy_string(c->context, con->name, sizeof(c->context));
08665       }
08666       pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
08667       application = expand_buf;
08668       if (c) {
08669          ast_channel_unref(c);
08670       }
08671    }
08672 
08673    length = sizeof(struct ast_exten);
08674    length += strlen(extension) + 1;
08675    length += strlen(application) + 1;
08676    if (label)
08677       length += strlen(label) + 1;
08678    if (callerid)
08679       length += strlen(callerid) + 1;
08680    else
08681       length ++;  /* just the '\0' */
08682 
08683    /* Be optimistic:  Build the extension structure first */
08684    if (!(tmp = ast_calloc(1, length)))
08685       return -1;
08686 
08687    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
08688       label = 0;
08689 
08690    /* use p as dst in assignments, as the fields are const char * */
08691    p = tmp->stuff;
08692    if (label) {
08693       tmp->label = p;
08694       strcpy(p, label);
08695       p += strlen(label) + 1;
08696    }
08697    tmp->exten = p;
08698    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
08699    tmp->priority = priority;
08700    tmp->cidmatch = p;   /* but use p for assignments below */
08701 
08702    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
08703    if (callerid) {
08704       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
08705       tmp->matchcid = 1;
08706    } else {
08707       *p++ = '\0';
08708       tmp->matchcid = 0;
08709    }
08710    tmp->app = p;
08711    strcpy(p, application);
08712    tmp->parent = con;
08713    tmp->data = data;
08714    tmp->datad = datad;
08715    tmp->registrar = registrar;
08716 
08717    if (lock_context) {
08718       ast_wrlock_context(con);
08719    }
08720 
08721    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
08722                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
08723       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
08724       dummy_exten.exten = dummy_name;
08725       dummy_exten.matchcid = 0;
08726       dummy_exten.cidmatch = 0;
08727       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
08728       if (!tmp2) {
08729          /* hmmm, not in the trie; */
08730          add_exten_to_pattern_tree(con, tmp, 0);
08731          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
08732       }
08733    }
08734    res = 0; /* some compilers will think it is uninitialized otherwise */
08735    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
08736       res = ext_cmp(e->exten, tmp->exten);
08737       if (res == 0) { /* extension match, now look at cidmatch */
08738          if (!e->matchcid && !tmp->matchcid)
08739             res = 0;
08740          else if (tmp->matchcid && !e->matchcid)
08741             res = 1;
08742          else if (e->matchcid && !tmp->matchcid)
08743             res = -1;
08744          else
08745             res = ext_cmp(e->cidmatch, tmp->cidmatch);
08746       }
08747       if (res >= 0)
08748          break;
08749    }
08750    if (e && res == 0) { /* exact match, insert in the priority chain */
08751       res = add_priority(con, tmp, el, e, replace);
08752       if (lock_context) {
08753          ast_unlock_context(con);
08754       }
08755       if (res < 0) {
08756          errno = EEXIST;   /* XXX do we care ? */
08757          return 0; /* XXX should we return -1 maybe ? */
08758       }
08759    } else {
08760       /*
08761        * not an exact match, this is the first entry with this pattern,
08762        * so insert in the main list right before 'e' (if any)
08763        */
08764       tmp->next = e;
08765       if (el) {  /* there is another exten already in this context */
08766          el->next = tmp;
08767          tmp->peer_table = ast_hashtab_create(13,
08768                      hashtab_compare_exten_numbers,
08769                      ast_hashtab_resize_java,
08770                      ast_hashtab_newsize_java,
08771                      hashtab_hash_priority,
08772                      0);
08773          tmp->peer_label_table = ast_hashtab_create(7,
08774                         hashtab_compare_exten_labels,
08775                         ast_hashtab_resize_java,
08776                         ast_hashtab_newsize_java,
08777                         hashtab_hash_labels,
08778                         0);
08779          if (label) {
08780             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08781          }
08782          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08783       } else {  /* this is the first exten in this context */
08784          if (!con->root_table)
08785             con->root_table = ast_hashtab_create(27,
08786                                        hashtab_compare_extens,
08787                                        ast_hashtab_resize_java,
08788                                        ast_hashtab_newsize_java,
08789                                        hashtab_hash_extens,
08790                                        0);
08791          con->root = tmp;
08792          con->root->peer_table = ast_hashtab_create(13,
08793                         hashtab_compare_exten_numbers,
08794                         ast_hashtab_resize_java,
08795                         ast_hashtab_newsize_java,
08796                         hashtab_hash_priority,
08797                         0);
08798          con->root->peer_label_table = ast_hashtab_create(7,
08799                            hashtab_compare_exten_labels,
08800                            ast_hashtab_resize_java,
08801                            ast_hashtab_newsize_java,
08802                            hashtab_hash_labels,
08803                            0);
08804          if (label) {
08805             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
08806          }
08807          ast_hashtab_insert_safe(con->root->peer_table, tmp);
08808 
08809       }
08810       ast_hashtab_insert_safe(con->root_table, tmp);
08811       if (lock_context) {
08812          ast_unlock_context(con);
08813       }
08814       if (tmp->priority == PRIORITY_HINT) {
08815          ast_add_hint(tmp);
08816       }
08817    }
08818    if (option_debug) {
08819       if (tmp->matchcid) {
08820          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
08821                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
08822       } else {
08823          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
08824                  tmp->exten, tmp->priority, con->name, con);
08825       }
08826    }
08827 
08828    if (tmp->matchcid) {
08829       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
08830              tmp->exten, tmp->priority, tmp->cidmatch, con->name);
08831    } else {
08832       ast_verb(3, "Added extension '%s' priority %d to %s\n",
08833              tmp->exten, tmp->priority, con->name);
08834    }
08835 
08836    return 0;
08837 }

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

References ast_add_extension2_lockopt(), and find_context().

Referenced by ast_merge_contexts_and_delete().

08254 {
08255    int ret = -1;
08256    struct ast_context *c;
08257 
08258    c = find_context(context);
08259    if (c) {
08260       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
08261          application, data, datad, registrar, 1);
08262    }
08263 
08264    return ret;
08265 }

static int ast_add_hint ( struct ast_exten e  )  [static]

Add hint to hint list, check initial extension state.

Definition at line 4888 of file pbx.c.

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

Referenced by add_priority(), and ast_add_extension2_lockopt().

04889 {
04890    struct ast_hint *hint_new;
04891    struct ast_hint *hint_found;
04892 
04893    if (!e) {
04894       return -1;
04895    }
04896 
04897    /*
04898     * We must create the hint we wish to add before determining if
04899     * it is already in the hints container to avoid possible
04900     * deadlock when getting the current extension state.
04901     */
04902    hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
04903    if (!hint_new) {
04904       return -1;
04905    }
04906 
04907    /* Initialize new hint. */
04908    hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
04909    if (!hint_new->callbacks) {
04910       ao2_ref(hint_new, -1);
04911       return -1;
04912    }
04913    hint_new->exten = e;
04914    hint_new->laststate = ast_extension_state2(e);
04915 
04916    /* Prevent multiple add hints from adding the same hint at the same time. */
04917    ao2_lock(hints);
04918 
04919    /* Search if hint exists, do nothing */
04920    hint_found = ao2_find(hints, e, 0);
04921    if (hint_found) {
04922       ao2_ref(hint_found, -1);
04923       ao2_unlock(hints);
04924       ao2_ref(hint_new, -1);
04925       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
04926          ast_get_extension_name(e), ast_get_extension_app(e));
04927       return -1;
04928    }
04929 
04930    /* Add new hint to the hints container */
04931    ast_debug(2, "HINTS: Adding hint %s: %s\n",
04932       ast_get_extension_name(e), ast_get_extension_app(e));
04933    ao2_link(hints, hint_new);
04934    if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
04935       ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
04936          ast_get_extension_name(e),
04937          ast_get_context_name(ast_get_extension_context(e)));
04938    }
04939 
04940    ao2_unlock(hints);
04941    ao2_ref(hint_new, -1);
04942 
04943    return 0;
04944 }

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

References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_accountcode(), ast_channel_alloc, ast_channel_linkedid(), ast_channel_lock, ast_channel_masquerade(), ast_channel_name(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_format_copy(), 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(), fax_detect_framehook(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().

08312 {
08313    int res = 0;
08314    struct ast_channel *tmpchan;
08315    struct {
08316       char *accountcode;
08317       char *exten;
08318       char *context;
08319       char *linkedid;
08320       char *name;
08321       struct ast_cdr *cdr;
08322       int amaflags;
08323       int state;
08324       struct ast_format readformat;
08325       struct ast_format writeformat;
08326    } tmpvars = { 0, };
08327 
08328    ast_channel_lock(chan);
08329    if (chan->pbx) { /* This channel is currently in the PBX */
08330       ast_explicit_goto(chan, context, exten, priority + 1);
08331       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08332       ast_channel_unlock(chan);
08333       return res;
08334    }
08335 
08336    /* In order to do it when the channel doesn't really exist within
08337     * the PBX, we have to make a new channel, masquerade, and start the PBX
08338     * at the new location */
08339    tmpvars.accountcode = ast_strdupa(ast_channel_accountcode(chan));
08340    tmpvars.exten = ast_strdupa(chan->exten);
08341    tmpvars.context = ast_strdupa(chan->context);
08342    tmpvars.linkedid = ast_strdupa(ast_channel_linkedid(chan));
08343    tmpvars.name = ast_strdupa(ast_channel_name(chan));
08344    tmpvars.amaflags = chan->amaflags;
08345    tmpvars.state = chan->_state;
08346    ast_format_copy(&tmpvars.writeformat, &chan->writeformat);
08347    ast_format_copy(&tmpvars.readformat, &chan->readformat);
08348    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08349 
08350    ast_channel_unlock(chan);
08351 
08352    /* Do not hold any channel locks while calling channel_alloc() since the function
08353     * locks the channel container when linking the new channel in. */
08354    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08355       ast_cdr_discard(tmpvars.cdr);
08356       return -1;
08357    }
08358 
08359    /* copy the cdr info over */
08360    if (tmpvars.cdr) {
08361       ast_cdr_discard(tmpchan->cdr);
08362       tmpchan->cdr = tmpvars.cdr;
08363       tmpvars.cdr = NULL;
08364    }
08365 
08366    /* Make formats okay */
08367    ast_format_copy(&tmpchan->readformat, &tmpvars.readformat);
08368    ast_format_copy(&tmpchan->writeformat, &tmpvars.writeformat);
08369 
08370    /* Setup proper location. Never hold another channel lock while calling this function. */
08371    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08372 
08373    /* Masquerade into tmp channel */
08374    if (ast_channel_masquerade(tmpchan, chan)) {
08375       /* Failed to set up the masquerade.  It's probably chan_local
08376        * in the middle of optimizing itself out.  Sad. :( */
08377       ast_hangup(tmpchan);
08378       tmpchan = NULL;
08379       res = -1;
08380    } else {
08381       ast_do_masquerade(tmpchan);
08382       /* Start the PBX going on our stolen channel */
08383       if (ast_pbx_start(tmpchan)) {
08384          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmpchan));
08385          ast_hangup(tmpchan);
08386          res = -1;
08387       }
08388    }
08389 
08390    return res;
08391 }

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

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

08394 {
08395    struct ast_channel *chan;
08396    int res = -1;
08397 
08398    if ((chan = ast_channel_get_by_name(channame))) {
08399       res = ast_async_goto(chan, context, exten, priority);
08400       chan = ast_channel_unref(chan);
08401    }
08402 
08403    return res;
08404 }

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

References __ast_goto_if_exists().

10709 {
10710    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10711 }

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

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), and handle_redirect().

10774 {
10775    return pbx_parseable_goto(chan, goto_string, 1);
10776 }

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

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

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

07896 {
07897    char *info;
07898    int j, num_fields, last_sep = -1;
07899 
07900    /* Check for empty just in case */
07901    if (ast_strlen_zero(info_in)) {
07902       return 0;
07903    }
07904 
07905    /* make a copy just in case we were passed a static string */
07906    info = ast_strdupa(info_in);
07907 
07908    /* count the number of fields in the timespec */
07909    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
07910       if (info[j] == ',') {
07911          last_sep = j;
07912          num_fields++;
07913       }
07914    }
07915 
07916    /* save the timezone, if it is specified */
07917    if (num_fields == 5) {
07918       i->timezone = ast_strdup(info + last_sep + 1);
07919    } else {
07920       i->timezone = NULL;
07921    }
07922 
07923    /* Assume everything except time */
07924    i->monthmask = 0xfff;   /* 12 bits */
07925    i->daymask = 0x7fffffffU; /* 31 bits */
07926    i->dowmask = 0x7f; /* 7 bits */
07927    /* on each call, use strsep() to move info to the next argument */
07928    get_timerange(i, strsep(&info, "|,"));
07929    if (info)
07930       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
07931    if (info)
07932       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
07933    if (info)
07934       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
07935    return 1;
07936 }

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

References E_CANMATCH, and pbx_extension_helper().

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

05042 {
05043    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05044 }

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

Change hint for an extension.

Definition at line 4947 of file pbx.c.

References add_hintdevice(), ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_log(), ast_hint::exten, hints, LOG_WARNING, OBJ_UNLINK, and remove_hintdevice().

Referenced by add_priority().

04948 {
04949    struct ast_hint *hint;
04950 
04951    if (!oe || !ne) {
04952       return -1;
04953    }
04954 
04955    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
04956 
04957    /*
04958     * Unlink the hint from the hints container as the extension
04959     * name (which is the hash value) could change.
04960     */
04961    hint = ao2_find(hints, oe, OBJ_UNLINK);
04962    if (!hint) {
04963       ao2_unlock(hints);
04964       return -1;
04965    }
04966 
04967    remove_hintdevice(hint);
04968 
04969    /* Update the hint and put it back in the hints container. */
04970    ao2_lock(hint);
04971    hint->exten = ne;
04972    ao2_unlock(hint);
04973    ao2_link(hints, hint);
04974    if (add_hintdevice(hint, ast_get_extension_app(ne))) {
04975       ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
04976          ast_get_extension_name(ne),
04977          ast_get_context_name(ast_get_extension_context(ne)));
04978    }
04979 
04980    ao2_unlock(hints);
04981    ao2_ref(hint, -1);
04982 
04983    return 0;
04984 }

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

References ast_check_timing2(), and ast_tvnow().

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

07939 {
07940    return ast_check_timing2(i, ast_tvnow());
07941 }

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

07944 {
07945    struct ast_tm tm;
07946 
07947    ast_localtime(&tv, &tm, i->timezone);
07948 
07949    /* If it's not the right month, return */
07950    if (!(i->monthmask & (1 << tm.tm_mon)))
07951       return 0;
07952 
07953    /* If it's not that time of the month.... */
07954    /* Warning, tm_mday has range 1..31! */
07955    if (!(i->daymask & (1 << (tm.tm_mday-1))))
07956       return 0;
07957 
07958    /* If it's not the right day of the week */
07959    if (!(i->dowmask & (1 << tm.tm_wday)))
07960       return 0;
07961 
07962    /* Sanity check the hour just to be safe */
07963    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07964       ast_log(LOG_WARNING, "Insane time...\n");
07965       return 0;
07966    }
07967 
07968    /* Now the tough part, we calculate if it fits
07969       in the right time based on min/hour */
07970    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))))
07971       return 0;
07972 
07973    /* If we got this far, then we're good */
07974    return 1;
07975 }

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

10779 {
10780    struct ast_app *app = NULL;
10781    int which = 0;
10782    char *ret = NULL;
10783    size_t wordlen = strlen(word);
10784 
10785    AST_RWLIST_RDLOCK(&apps);
10786    AST_RWLIST_TRAVERSE(&apps, app, list) {
10787       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10788          ret = ast_strdup(app->name);
10789          break;
10790       }
10791    }
10792    AST_RWLIST_UNLOCK(&apps);
10793 
10794    return ret;
10795 }

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

08180 {
08181    int ret = -1;
08182    struct ast_context *c;
08183 
08184    c = find_context_locked(context);
08185    if (c) {
08186       ret = ast_context_add_ignorepat2(c, value, registrar);
08187       ast_unlock_contexts();
08188    }
08189    return ret;
08190 }

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

Definition at line 8192 of file pbx.c.

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

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

08193 {
08194    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08195    int length;
08196    char *pattern;
08197    length = sizeof(struct ast_ignorepat);
08198    length += strlen(value) + 1;
08199    if (!(ignorepat = ast_calloc(1, length)))
08200       return -1;
08201    /* The cast to char * is because we need to write the initial value.
08202     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08203     * sees the cast as dereferencing a type-punned pointer and warns about
08204     * it.  This is the workaround (we're telling gcc, yes, that's really
08205     * what we wanted to do).
08206     */
08207    pattern = (char *) ignorepat->pattern;
08208    strcpy(pattern, value);
08209    ignorepat->next = NULL;
08210    ignorepat->registrar = registrar;
08211    ast_wrlock_context(con);
08212    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08213       ignorepatl = ignorepatc;
08214       if (!strcasecmp(ignorepatc->pattern, value)) {
08215          /* Already there */
08216          ast_unlock_context(con);
08217          errno = EEXIST;
08218          return -1;
08219       }
08220    }
08221    if (ignorepatl)
08222       ignorepatl->next = ignorepat;
08223    else
08224       con->ignorepats = ignorepat;
08225    ast_unlock_context(con);
08226    return 0;
08227 
08228 }

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

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

Referenced by handle_cli_dialplan_add_include().

07724 {
07725    int ret = -1;
07726    struct ast_context *c;
07727 
07728    c = find_context_locked(context);
07729    if (c) {
07730       ret = ast_context_add_include2(c, include, registrar);
07731       ast_unlock_contexts();
07732    }
07733    return ret;
07734 }

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

07994 {
07995    struct ast_include *new_include;
07996    char *c;
07997    struct ast_include *i, *il = NULL; /* include, include_last */
07998    int length;
07999    char *p;
08000 
08001    length = sizeof(struct ast_include);
08002    length += 2 * (strlen(value) + 1);
08003 
08004    /* allocate new include structure ... */
08005    if (!(new_include = ast_calloc(1, length)))
08006       return -1;
08007    /* Fill in this structure. Use 'p' for assignments, as the fields
08008     * in the structure are 'const char *'
08009     */
08010    p = new_include->stuff;
08011    new_include->name = p;
08012    strcpy(p, value);
08013    p += strlen(value) + 1;
08014    new_include->rname = p;
08015    strcpy(p, value);
08016    /* Strip off timing info, and process if it is there */
08017    if ( (c = strchr(p, ',')) ) {
08018       *c++ = '\0';
08019       new_include->hastime = ast_build_timing(&(new_include->timing), c);
08020    }
08021    new_include->next      = NULL;
08022    new_include->registrar = registrar;
08023 
08024    ast_wrlock_context(con);
08025 
08026    /* ... go to last include and check if context is already included too... */
08027    for (i = con->includes; i; i = i->next) {
08028       if (!strcasecmp(i->name, new_include->name)) {
08029          ast_destroy_timing(&(new_include->timing));
08030          ast_free(new_include);
08031          ast_unlock_context(con);
08032          errno = EEXIST;
08033          return -1;
08034       }
08035       il = i;
08036    }
08037 
08038    /* ... include new context into context list, unlock, return */
08039    if (il)
08040       il->next = new_include;
08041    else
08042       con->includes = new_include;
08043    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
08044 
08045    ast_unlock_context(con);
08046 
08047    return 0;
08048 }

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

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

08056 {
08057    int ret = -1;
08058    struct ast_context *c;
08059 
08060    c = find_context_locked(context);
08061    if (c) { /* found, add switch to this context */
08062       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
08063       ast_unlock_contexts();
08064    }
08065    return ret;
08066 }

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

08077 {
08078    struct ast_sw *new_sw;
08079    struct ast_sw *i;
08080    int length;
08081    char *p;
08082 
08083    length = sizeof(struct ast_sw);
08084    length += strlen(value) + 1;
08085    if (data)
08086       length += strlen(data);
08087    length++;
08088 
08089    /* allocate new sw structure ... */
08090    if (!(new_sw = ast_calloc(1, length)))
08091       return -1;
08092    /* ... fill in this structure ... */
08093    p = new_sw->stuff;
08094    new_sw->name = p;
08095    strcpy(new_sw->name, value);
08096    p += strlen(value) + 1;
08097    new_sw->data = p;
08098    if (data) {
08099       strcpy(new_sw->data, data);
08100       p += strlen(data) + 1;
08101    } else {
08102       strcpy(new_sw->data, "");
08103       p++;
08104    }
08105    new_sw->eval     = eval;
08106    new_sw->registrar = registrar;
08107 
08108    /* ... try to lock this context ... */
08109    ast_wrlock_context(con);
08110 
08111    /* ... go to last sw and check if context is already swd too... */
08112    AST_LIST_TRAVERSE(&con->alts, i, list) {
08113       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
08114          ast_free(new_sw);
08115          ast_unlock_context(con);
08116          errno = EEXIST;
08117          return -1;
08118       }
08119    }
08120 
08121    /* ... sw new context into context list, unlock, return */
08122    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
08123 
08124    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
08125 
08126    ast_unlock_context(con);
08127 
08128    return 0;
08129 }

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

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

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

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 2777 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(), handle_cli_dialplan_add_extension(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().

02778 {
02779    struct ast_context *tmp;
02780    struct fake_context item;
02781 
02782    if (!name) {
02783       return NULL;
02784    }
02785    ast_rdlock_contexts();
02786    if (contexts_table) {
02787       ast_copy_string(item.name, name, sizeof(item.name));
02788       tmp = ast_hashtab_lookup(contexts_table, &item);
02789    } else {
02790       tmp = NULL;
02791       while ((tmp = ast_walk_contexts(tmp))) {
02792          if (!strcasecmp(name, tmp->name)) {
02793             break;
02794          }
02795       }
02796    }
02797    ast_unlock_contexts();
02798    return tmp;
02799 }

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 7324 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(), handle_cli_dialplan_add_extension(), load_module(), lua_register_hints(), 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().

07325 {
07326    struct ast_context *tmp, **local_contexts;
07327    struct fake_context search;
07328    int length = sizeof(struct ast_context) + strlen(name) + 1;
07329 
07330    if (!contexts_table) {
07331       /* Protect creation of contexts_table from reentrancy. */
07332       ast_wrlock_contexts();
07333       if (!contexts_table) {
07334          contexts_table = ast_hashtab_create(17,
07335             ast_hashtab_compare_contexts,
07336             ast_hashtab_resize_java,
07337             ast_hashtab_newsize_java,
07338             ast_hashtab_hash_contexts,
07339             0);
07340       }
07341       ast_unlock_contexts();
07342    }
07343 
07344    ast_copy_string(search.name, name, sizeof(search.name));
07345    if (!extcontexts) {
07346       ast_rdlock_contexts();
07347       local_contexts = &contexts;
07348       tmp = ast_hashtab_lookup(contexts_table, &search);
07349       ast_unlock_contexts();
07350       if (tmp) {
07351          tmp->refcount++;
07352          return tmp;
07353       }
07354    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07355       local_contexts = extcontexts;
07356       tmp = ast_hashtab_lookup(exttable, &search);
07357       if (tmp) {
07358          tmp->refcount++;
07359          return tmp;
07360       }
07361    }
07362 
07363    if ((tmp = ast_calloc(1, length))) {
07364       ast_rwlock_init(&tmp->lock);
07365       ast_mutex_init(&tmp->macrolock);
07366       strcpy(tmp->name, name);
07367       tmp->root = NULL;
07368       tmp->root_table = NULL;
07369       tmp->registrar = ast_strdup(registrar);
07370       tmp->includes = NULL;
07371       tmp->ignorepats = NULL;
07372       tmp->refcount = 1;
07373    } else {
07374       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07375       return NULL;
07376    }
07377 
07378    if (!extcontexts) {
07379       ast_wrlock_contexts();
07380       tmp->next = *local_contexts;
07381       *local_contexts = tmp;
07382       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07383       ast_unlock_contexts();
07384       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07385       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07386    } else {
07387       tmp->next = *local_contexts;
07388       if (exttable)
07389          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07390 
07391       *local_contexts = tmp;
07392       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07393       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07394    }
07395    return tmp;
07396 }

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

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

Referenced by _macro_exec().

05925 {
05926    struct ast_context *c;
05927    int ret = -1;
05928 
05929    c = find_context_locked(context);
05930    if (c) {
05931       ast_unlock_contexts();
05932 
05933       /* if we found context, lock macrolock */
05934       ret = ast_mutex_lock(&c->macrolock);
05935    }
05936 
05937    return ret;
05938 }

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

References ast_context_remove_extension_callerid().

Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), remove_exten_if_exist(), unregister_exten(), and UnregisterExtension().

05730 {
05731    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05732 }

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

References ast_context_remove_extension_callerid2().

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

05760 {
05761    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05762 }

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

05735 {
05736    int ret = -1; /* default error return */
05737    struct ast_context *c;
05738 
05739    c = find_context_locked(context);
05740    if (c) { /* ... remove extension ... */
05741       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
05742          matchcallerid, registrar, 0);
05743       ast_unlock_contexts();
05744    }
05745 
05746    return ret;
05747 }

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

05765 {
05766    struct ast_exten *exten, *prev_exten = NULL;
05767    struct ast_exten *peer;
05768    struct ast_exten ex, *exten2, *exten3;
05769    char dummy_name[1024];
05770    struct ast_exten *previous_peer = NULL;
05771    struct ast_exten *next_peer = NULL;
05772    int found = 0;
05773 
05774    if (!already_locked)
05775       ast_wrlock_context(con);
05776 
05777    /* Handle this is in the new world */
05778 
05779    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05780     * peers, not just those matching the callerid. */
05781 #ifdef NEED_DEBUG
05782    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05783 #endif
05784 #ifdef CONTEXT_DEBUG
05785    check_contexts(__FILE__, __LINE__);
05786 #endif
05787    /* find this particular extension */
05788    ex.exten = dummy_name;
05789    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05790    ex.cidmatch = callerid;
05791    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05792    exten = ast_hashtab_lookup(con->root_table, &ex);
05793    if (exten) {
05794       if (priority == 0) {
05795          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05796          if (!exten2)
05797             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);
05798          if (con->pattern_tree) {
05799             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05800 
05801             if (x->exten) { /* this test for safety purposes */
05802                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05803                x->exten = 0; /* get rid of what will become a bad pointer */
05804             } else {
05805                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05806             }
05807          }
05808       } else {
05809          ex.priority = priority;
05810          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05811          if (exten2) {
05812 
05813             if (exten2->label) { /* if this exten has a label, remove that, too */
05814                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05815                if (!exten3)
05816                   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);
05817             }
05818 
05819             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05820             if (!exten3)
05821                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);
05822             if (exten2 == exten && exten2->peer) {
05823                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05824                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05825             }
05826             if (ast_hashtab_size(exten->peer_table) == 0) {
05827                /* well, if the last priority of an exten is to be removed,
05828                   then, the extension is removed, too! */
05829                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05830                if (!exten3)
05831                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05832                if (con->pattern_tree) {
05833                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05834                   if (x->exten) { /* this test for safety purposes */
05835                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05836                      x->exten = 0; /* get rid of what will become a bad pointer */
05837                   }
05838                }
05839             }
05840          } else {
05841             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05842                   priority, exten->exten, con->name);
05843          }
05844       }
05845    } else {
05846       /* hmmm? this exten is not in this pattern tree? */
05847       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05848             extension, con->name);
05849    }
05850 #ifdef NEED_DEBUG
05851    if (con->pattern_tree) {
05852       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05853       log_match_char_tree(con->pattern_tree, " ");
05854    }
05855 #endif
05856 
05857    /* scan the extension list to find first matching extension-registrar */
05858    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05859       if (!strcmp(exten->exten, extension) &&
05860          (!registrar || !strcmp(exten->registrar, registrar)) &&
05861          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05862          break;
05863    }
05864    if (!exten) {
05865       /* we can't find right extension */
05866       if (!already_locked)
05867          ast_unlock_context(con);
05868       return -1;
05869    }
05870 
05871    /* scan the priority list to remove extension with exten->priority == priority */
05872    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05873        peer && !strcmp(peer->exten, extension) && (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch)));
05874          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05875       if ((priority == 0 || peer->priority == priority) &&
05876             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05877             (!registrar || !strcmp(peer->registrar, registrar) )) {
05878          found = 1;
05879 
05880          /* we are first priority extension? */
05881          if (!previous_peer) {
05882             /*
05883              * We are first in the priority chain, so must update the extension chain.
05884              * The next node is either the next priority or the next extension
05885              */
05886             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05887             if (peer->peer) {
05888                /* move the peer_table and peer_label_table down to the next peer, if
05889                   it is there */
05890                peer->peer->peer_table = peer->peer_table;
05891                peer->peer->peer_label_table = peer->peer_label_table;
05892                peer->peer_table = NULL;
05893                peer->peer_label_table = NULL;
05894             }
05895             if (!prev_exten) {   /* change the root... */
05896                con->root = next_node;
05897             } else {
05898                prev_exten->next = next_node; /* unlink */
05899             }
05900             if (peer->peer)   { /* update the new head of the pri list */
05901                peer->peer->next = peer->next;
05902             }
05903          } else { /* easy, we are not first priority in extension */
05904             previous_peer->peer = peer->peer;
05905          }
05906 
05907          /* now, free whole priority extension */
05908          destroy_exten(peer);
05909       } else {
05910          previous_peer = peer;
05911       }
05912    }
05913    if (!already_locked)
05914       ast_unlock_context(con);
05915    return found ? 0 : -1;
05916 }

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

Definition at line 8135 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_ignorepat().

08136 {
08137    int ret = -1;
08138    struct ast_context *c;
08139 
08140    c = find_context_locked(context);
08141    if (c) {
08142       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
08143       ast_unlock_contexts();
08144    }
08145    return ret;
08146 }

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

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

08149 {
08150    struct ast_ignorepat *ip, *ipl = NULL;
08151 
08152    ast_wrlock_context(con);
08153 
08154    for (ip = con->ignorepats; ip; ip = ip->next) {
08155       if (!strcmp(ip->pattern, ignorepat) &&
08156          (!registrar || (registrar == ip->registrar))) {
08157          if (ipl) {
08158             ipl->next = ip->next;
08159             ast_free(ip);
08160          } else {
08161             con->ignorepats = ip->next;
08162             ast_free(ip);
08163          }
08164          ast_unlock_context(con);
08165          return 0;
08166       }
08167       ipl = ip;
08168    }
08169 
08170    ast_unlock_context(con);
08171    errno = EINVAL;
08172    return -1;
08173 }

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

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

Referenced by handle_cli_dialplan_remove_include().

05623 {
05624    int ret = -1;
05625    struct ast_context *c;
05626 
05627    c = find_context_locked(context);
05628    if (c) {
05629       /* found, remove include from this context ... */
05630       ret = ast_context_remove_include2(c, include, registrar);
05631       ast_unlock_contexts();
05632    }
05633    return ret;
05634 }

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

05646 {
05647    struct ast_include *i, *pi = NULL;
05648    int ret = -1;
05649 
05650    ast_wrlock_context(con);
05651 
05652    /* find our include */
05653    for (i = con->includes; i; pi = i, i = i->next) {
05654       if (!strcmp(i->name, include) &&
05655             (!registrar || !strcmp(i->registrar, registrar))) {
05656          /* remove from list */
05657          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05658          if (pi)
05659             pi->next = i->next;
05660          else
05661             con->includes = i->next;
05662          /* free include and return */
05663          ast_destroy_timing(&(i->timing));
05664          ast_free(i);
05665          ret = 0;
05666          break;
05667       }
05668    }
05669 
05670    ast_unlock_context(con);
05671 
05672    return ret;
05673 }

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

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

05681 {
05682    int ret = -1; /* default error return */
05683    struct ast_context *c;
05684 
05685    c = find_context_locked(context);
05686    if (c) {
05687       /* remove switch from this context ... */
05688       ret = ast_context_remove_switch2(c, sw, data, registrar);
05689       ast_unlock_contexts();
05690    }
05691    return ret;
05692 }

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

05703 {
05704    struct ast_sw *i;
05705    int ret = -1;
05706 
05707    ast_wrlock_context(con);
05708 
05709    /* walk switches */
05710    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05711       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05712          (!registrar || !strcmp(i->registrar, registrar))) {
05713          /* found, remove from list */
05714          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05715          AST_LIST_REMOVE_CURRENT(list);
05716          ast_free(i); /* free switch and return */
05717          ret = 0;
05718          break;
05719       }
05720    }
05721    AST_LIST_TRAVERSE_SAFE_END;
05722 
05723    ast_unlock_context(con);
05724 
05725    return ret;
05726 }

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

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

Referenced by _macro_exec().

05946 {
05947    struct ast_context *c;
05948    int ret = -1;
05949 
05950    c = find_context_locked(context);
05951    if (c) {
05952       ast_unlock_contexts();
05953 
05954       /* if we found context, unlock macrolock */
05955       ret = ast_mutex_unlock(&c->macrolock);
05956    }
05957 
05958    return ret;
05959 }

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

10664 {
10665    struct ast_include *inc = NULL;
10666    int res = 0;
10667 
10668    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10669       if (ast_context_find(inc->rname))
10670          continue;
10671 
10672       res = -1;
10673       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10674          ast_get_context_name(con), inc->rname);
10675       break;
10676    }
10677 
10678    return res;
10679 }

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

References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.

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

03641 {
03642    struct ast_custom_function *cur;
03643 
03644    if (!acf) {
03645       return -1;
03646    }
03647 
03648    AST_RWLIST_WRLOCK(&acf_root);
03649    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03650 #ifdef AST_XML_DOCS
03651       if (cur->docsrc == AST_XML_DOC) {
03652          ast_string_field_free_memory(acf);
03653       }
03654 #endif
03655       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03656    }
03657    AST_RWLIST_UNLOCK(&acf_root);
03658 
03659    return cur ? 0 : -1;
03660 }

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

07978 {
07979    if (i->timezone) {
07980       ast_free(i->timezone);
07981       i->timezone = NULL;
07982    }
07983    return 0;
07984 }

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

04450 {
04451    switch (devstate) {
04452    case AST_DEVICE_ONHOLD:
04453       return AST_EXTENSION_ONHOLD;
04454    case AST_DEVICE_BUSY:
04455       return AST_EXTENSION_BUSY;
04456    case AST_DEVICE_UNKNOWN:
04457       return AST_EXTENSION_NOT_INUSE;
04458    case AST_DEVICE_UNAVAILABLE:
04459    case AST_DEVICE_INVALID:
04460       return AST_EXTENSION_UNAVAILABLE;
04461    case AST_DEVICE_RINGINUSE:
04462       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04463    case AST_DEVICE_RINGING:
04464       return AST_EXTENSION_RINGING;
04465    case AST_DEVICE_INUSE:
04466       return AST_EXTENSION_INUSE;
04467    case AST_DEVICE_NOT_INUSE:
04468       return AST_EXTENSION_NOT_INUSE;
04469    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04470       break;
04471    }
04472 
04473    return AST_EXTENSION_NOT_INUSE;
04474 }

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 5026 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(), action_originate(), 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(), fax_detect_framehook(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), setsubstate(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().

05027 {
05028    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05029 }

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 8288 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(), msg_route(), pbx_parseable_goto(), and return_exec().

08289 {
08290    if (!chan)
08291       return -1;
08292 
08293    ast_channel_lock(chan);
08294 
08295    if (!ast_strlen_zero(context))
08296       ast_copy_string(chan->context, context, sizeof(chan->context));
08297    if (!ast_strlen_zero(exten))
08298       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08299    if (priority > -1) {
08300       chan->priority = priority;
08301       /* see flag description in channel.h for explanation */
08302       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08303          chan->priority--;
08304    }
08305 
08306    ast_channel_unlock(chan);
08307 
08308    return 0;
08309 }

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

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

02755 {
02756    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02757       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02758    return extension_match_core(pattern, data, needmore);
02759 }

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

References ext_cmp().

Referenced by lua_extension_cmp().

02557 {
02558    return ext_cmp(a, b);
02559 }

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

02750 {
02751    return extension_match_core(pattern, data, E_MATCH);
02752 }

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

04520 {
04521    struct ast_exten *e;
04522 
04523    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04524       return -1;                   /* No hint, return -1 */
04525    }
04526 
04527    if (e->exten[0] == '_') {
04528       /* Create this hint on-the-fly */
04529       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04530          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04531          e->registrar);
04532       if (!(e = ast_hint_extension(c, context, exten))) {
04533          /* Improbable, but not impossible */
04534          return -1;
04535       }
04536    }
04537 
04538    return ast_extension_state2(e);  /* Check all devices in the hint */
04539 }

static int ast_extension_state2 ( struct ast_exten e  )  [static]

Check state of extension by using hints.

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

04495 {
04496    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
04497 
04498    if (!e || !hint_app) {
04499       return -1;
04500    }
04501 
04502    ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
04503    return ast_extension_state3(hint_app);
04504 }

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 4507 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(), show_channels_cb(), and skinny_extensionstate_cb().

04508 {
04509    int i;
04510 
04511    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04512       if (extension_states[i].extension_state == extension_state)
04513          return extension_states[i].text;
04514    }
04515    return "Unknown";
04516 }

static int ast_extension_state3 ( struct ast_str hint_app  )  [static]

Definition at line 4476 of file pbx.c.

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

Referenced by ast_extension_state2(), and handle_statechange().

04477 {
04478    char *cur;
04479    char *rest;
04480    struct ast_devstate_aggregate agg;
04481 
04482    /* One or more devices separated with a & character */
04483    rest = ast_str_buffer(hint_app);
04484 
04485    ast_devstate_aggregate_init(&agg);
04486    while ((cur = strsep(&rest, "&"))) {
04487       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
04488    }
04489 
04490    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
04491 }

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

References ast_extension_state_add_destroy().

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

04754 {
04755    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
04756 }

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

04667 {
04668    struct ast_hint *hint;
04669    struct ast_state_cb *state_cb;
04670    struct ast_exten *e;
04671    int id;
04672 
04673    /* If there's no context and extension:  add callback to statecbs list */
04674    if (!context && !exten) {
04675       /* Prevent multiple adds from adding the same change_cb at the same time. */
04676       ao2_lock(statecbs);
04677 
04678       /* Remove any existing change_cb. */
04679       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
04680 
04681       /* Now insert the change_cb */
04682       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04683          ao2_unlock(statecbs);
04684          return -1;
04685       }
04686       state_cb->id = 0;
04687       state_cb->change_cb = change_cb;
04688       state_cb->destroy_cb = destroy_cb;
04689       state_cb->data = data;
04690       ao2_link(statecbs, state_cb);
04691 
04692       ao2_ref(state_cb, -1);
04693       ao2_unlock(statecbs);
04694       return 0;
04695    }
04696 
04697    if (!context || !exten)
04698       return -1;
04699 
04700    /* This callback type is for only one hint, so get the hint */
04701    e = ast_hint_extension(NULL, context, exten);
04702    if (!e) {
04703       return -1;
04704    }
04705 
04706    /* If this is a pattern, dynamically create a new extension for this
04707     * particular match.  Note that this will only happen once for each
04708     * individual extension, because the pattern will no longer match first.
04709     */
04710    if (e->exten[0] == '_') {
04711       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04712          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04713          e->registrar);
04714       e = ast_hint_extension(NULL, context, exten);
04715       if (!e || e->exten[0] == '_') {
04716          return -1;
04717       }
04718    }
04719 
04720    /* Find the hint in the hints container */
04721    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04722    hint = ao2_find(hints, e, 0);
04723    if (!hint) {
04724       ao2_unlock(hints);
04725       return -1;
04726    }
04727 
04728    /* Now insert the callback in the callback list  */
04729    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04730       ao2_ref(hint, -1);
04731       ao2_unlock(hints);
04732       return -1;
04733    }
04734    do {
04735       id = stateid++;      /* Unique ID for this callback */
04736       /* Do not allow id to ever be -1 or 0. */
04737    } while (id == -1 || id == 0);
04738    state_cb->id = id;
04739    state_cb->change_cb = change_cb; /* Pointer to callback routine */
04740    state_cb->destroy_cb = destroy_cb;
04741    state_cb->data = data;     /* Data for the callback */
04742    ao2_link(hint->callbacks, state_cb);
04743 
04744    ao2_ref(state_cb, -1);
04745    ao2_ref(hint, -1);
04746    ao2_unlock(hints);
04747 
04748    return id;
04749 }

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

04775 {
04776    struct ast_state_cb *p_cur;
04777    int ret = -1;
04778 
04779    if (!id) {  /* id == 0 is a callback without extension */
04780       if (!change_cb) {
04781          return ret;
04782       }
04783       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
04784       if (p_cur) {
04785          ret = 0;
04786          ao2_ref(p_cur, -1);
04787       }
04788    } else { /* callback with extension, find the callback based on ID */
04789       struct ast_hint *hint;
04790 
04791       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04792       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04793       if (hint) {
04794          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
04795          if (p_cur) {
04796             ret = 0;
04797             ao2_ref(p_cur, -1);
04798          }
04799          ao2_ref(hint, -1);
04800       }
04801       ao2_unlock(hints);
04802    }
04803 
04804    return ret;
04805 }

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

05032 {
05033    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05034 }

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

References E_FINDLABEL, and pbx_extension_helper().

Referenced by pbx_load_config().

05037 {
05038    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05039 }

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 3784 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(), 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().

03785 {
03786    char *copy = ast_strdupa(function);
03787    char *args = func_args(copy);
03788    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03789    int res;
03790    struct ast_module_user *u = NULL;
03791 
03792    if (acfptr == NULL) {
03793       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03794    } else if (!acfptr->read && !acfptr->read2) {
03795       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03796    } else if (acfptr->read) {
03797       if (acfptr->mod) {
03798          u = __ast_module_user_add(acfptr->mod, chan);
03799       }
03800       res = acfptr->read(chan, copy, args, workspace, len);
03801       if (acfptr->mod && u) {
03802          __ast_module_user_remove(acfptr->mod, u);
03803       }
03804       return res;
03805    } else {
03806       struct ast_str *str = ast_str_create(16);
03807       if (acfptr->mod) {
03808          u = __ast_module_user_add(acfptr->mod, chan);
03809       }
03810       res = acfptr->read2(chan, copy, args, &str, 0);
03811       if (acfptr->mod && u) {
03812          __ast_module_user_remove(acfptr->mod, u);
03813       }
03814       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03815       ast_free(str);
03816       return res;
03817    }
03818    return -1;
03819 }

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 3821 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(), 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().

03822 {
03823    char *copy = ast_strdupa(function);
03824    char *args = func_args(copy);
03825    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03826    int res;
03827    struct ast_module_user *u = NULL;
03828 
03829    if (acfptr == NULL) {
03830       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03831    } else if (!acfptr->read && !acfptr->read2) {
03832       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03833    } else {
03834       if (acfptr->mod) {
03835          u = __ast_module_user_add(acfptr->mod, chan);
03836       }
03837       ast_str_reset(*str);
03838       if (acfptr->read2) {
03839          /* ast_str enabled */
03840          res = acfptr->read2(chan, copy, args, str, maxlen);
03841       } else {
03842          /* Legacy function pointer, allocate buffer for result */
03843          int maxsize = ast_str_size(*str);
03844          if (maxlen > -1) {
03845             if (maxlen == 0) {
03846                if (acfptr->read_max) {
03847                   maxsize = acfptr->read_max;
03848                } else {
03849                   maxsize = VAR_BUF_SIZE;
03850                }
03851             } else {
03852                maxsize = maxlen;
03853             }
03854             ast_str_make_space(str, maxsize);
03855          }
03856          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03857       }
03858       if (acfptr->mod && u) {
03859          __ast_module_user_remove(acfptr->mod, u);
03860       }
03861       return res;
03862    }
03863    return -1;
03864 }

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 3866 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(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.

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

03867 {
03868    char *copy = ast_strdupa(function);
03869    char *args = func_args(copy);
03870    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03871 
03872    if (acfptr == NULL)
03873       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03874    else if (!acfptr->write)
03875       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03876    else {
03877       int res;
03878       struct ast_module_user *u = NULL;
03879       if (acfptr->mod)
03880          u = __ast_module_user_add(acfptr->mod, chan);
03881       res = acfptr->write(chan, copy, args, value);
03882       if (acfptr->mod && u)
03883          __ast_module_user_remove(acfptr->mod, u);
03884       return res;
03885    }
03886 
03887    return -1;
03888 }

const char* ast_get_context_name ( struct ast_context con  ) 

const char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 10553 of file pbx.c.

References ast_context::registrar.

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

10554 {
10555    return c ? c->registrar : NULL;
10556 }

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

References ast_exten::cidmatch.

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

10579 {
10580    return e ? e->cidmatch : NULL;
10581 }

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

Definition at line 10520 of file pbx.c.

References ast_exten::parent.

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

10521 {
10522    return exten ? exten->parent : NULL;
10523 }

const char* ast_get_extension_label ( struct ast_exten exten  ) 

Definition at line 10530 of file pbx.c.

References ast_exten::label.

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

10531 {
10532    return exten ? exten->label : NULL;
10533 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 10573 of file pbx.c.

References ast_exten::matchcid.

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

10574 {
10575    return e ? e->matchcid : 0;
10576 }

const char* ast_get_extension_name ( struct ast_exten exten  ) 

int ast_get_extension_priority ( struct ast_exten exten  ) 

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

10546 {
10547    return exten ? exten->priority : -1;
10548 }

const char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 10558 of file pbx.c.

References ast_exten::registrar.

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

10559 {
10560    return e ? e->registrar : NULL;
10561 }

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

04989 {
04990    struct ast_exten *e = ast_hint_extension(c, context, exten);
04991 
04992    if (e) {
04993       if (hint)
04994          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04995       if (name) {
04996          const char *tmp = ast_get_extension_app_data(e);
04997          if (tmp)
04998             ast_copy_string(name, tmp, namesize);
04999       }
05000       return -1;
05001    }
05002    return 0;
05003 }

const char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

const char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

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

10569 {
10570    return ip ? ip->registrar : NULL;
10571 }

const char* ast_get_include_name ( struct ast_include inc  ) 

const char* ast_get_include_registrar ( struct ast_include i  ) 

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

10564 {
10565    return i ? i->registrar : NULL;
10566 }

const char* ast_get_switch_data ( struct ast_sw sw  ) 

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

10599 {
10600    return sw ? sw->data : NULL;
10601 }

int ast_get_switch_eval ( struct ast_sw sw  ) 

Definition at line 10603 of file pbx.c.

References ast_sw::eval.

Referenced by context_merge_incls_swits_igps_other_registrars().

10604 {
10605    return sw->eval;
10606 }

const char* ast_get_switch_name ( struct ast_sw sw  ) 

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

10594 {
10595    return sw ? sw->name : NULL;
10596 }

const char* ast_get_switch_registrar ( struct ast_sw sw  ) 

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

10609 {
10610    return sw ? sw->registrar : NULL;
10611 }

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

References __ast_goto_if_exists().

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

10704 {
10705    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10706 }

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

hashtable functions for contexts

Definition at line 1186 of file pbx.c.

References ast_context::name.

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

01187 {
01188    const struct ast_context *ac = ah_a;
01189    const struct ast_context *bc = ah_b;
01190    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01191       return 1;
01192    /* assume context names are registered in a string table! */
01193    return strcmp(ac->name, bc->name);
01194 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

Definition at line 1229 of file pbx.c.

References ast_hashtab_hash_string(), and ast_context::name.

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

01230 {
01231    const struct ast_context *ac = obj;
01232    return ast_hashtab_hash_string(ac->name);
01233 }

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

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

04441 {
04442    struct ast_exten *e;
04443    ast_rdlock_contexts();
04444    e = ast_hint_extension_nolock(c, context, exten);
04445    ast_unlock_contexts();
04446    return e;
04447 }

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

04435 {
04436    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04437    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04438 }

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 8230 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(), mgcp_ss(), and skinny_ss().

08231 {
08232    struct ast_context *con = ast_context_find(context);
08233 
08234    if (con) {
08235       struct ast_ignorepat *pat;
08236 
08237       for (pat = con->ignorepats; pat; pat = pat->next) {
08238          if (ast_extension_match(pat->pattern, pattern))
08239             return 1;
08240       }
08241    }
08242 
08243    return 0;
08244 }

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 5046 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(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().

05047 {
05048    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05049 }

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

07529 {
07530    double ft;
07531    struct ast_context *tmp;
07532    struct ast_context *oldcontextslist;
07533    struct ast_hashtab *oldtable;
07534    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07535    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07536    struct store_hint *saved_hint;
07537    struct ast_hint *hint;
07538    struct ast_exten *exten;
07539    int length;
07540    struct ast_state_cb *thiscb;
07541    struct ast_hashtab_iter *iter;
07542    struct ao2_iterator i;
07543    struct timeval begintime;
07544    struct timeval writelocktime;
07545    struct timeval endlocktime;
07546    struct timeval enddeltime;
07547 
07548    /*
07549     * It is very important that this function hold the hints
07550     * container lock _and_ the conlock during its operation; not
07551     * only do we need to ensure that the list of contexts and
07552     * extensions does not change, but also that no hint callbacks
07553     * (watchers) are added or removed during the merge/delete
07554     * process
07555     *
07556     * In addition, the locks _must_ be taken in this order, because
07557     * there are already other code paths that use this order
07558     */
07559 
07560    begintime = ast_tvnow();
07561    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07562    ast_wrlock_contexts();
07563    iter = ast_hashtab_start_traversal(contexts_table);
07564    while ((tmp = ast_hashtab_next(iter))) {
07565       context_merge(extcontexts, exttable, tmp, registrar);
07566    }
07567    ast_hashtab_end_traversal(iter);
07568 
07569    ao2_lock(hints);
07570    writelocktime = ast_tvnow();
07571 
07572    /* preserve all watchers for hints */
07573    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07574    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07575       if (ao2_container_count(hint->callbacks)) {
07576          ao2_lock(hint);
07577          if (!hint->exten) {
07578             /* The extension has already been destroyed. (Should never happen here) */
07579             ao2_unlock(hint);
07580             continue;
07581          }
07582 
07583          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07584             + sizeof(*saved_hint);
07585          if (!(saved_hint = ast_calloc(1, length))) {
07586             ao2_unlock(hint);
07587             continue;
07588          }
07589 
07590          /* This removes all the callbacks from the hint into saved_hint. */
07591          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07592             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07593             /*
07594              * We intentionally do not unref thiscb to account for the
07595              * non-ao2 reference in saved_hint->callbacks
07596              */
07597          }
07598 
07599          saved_hint->laststate = hint->laststate;
07600          saved_hint->context = saved_hint->data;
07601          strcpy(saved_hint->data, hint->exten->parent->name);
07602          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07603          strcpy(saved_hint->exten, hint->exten->exten);
07604          ao2_unlock(hint);
07605          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07606       }
07607    }
07608    ao2_iterator_destroy(&i);
07609 
07610    /* save the old table and list */
07611    oldtable = contexts_table;
07612    oldcontextslist = contexts;
07613 
07614    /* move in the new table and list */
07615    contexts_table = exttable;
07616    contexts = *extcontexts;
07617 
07618    /*
07619     * Restore the watchers for hints that can be found; notify
07620     * those that cannot be restored.
07621     */
07622    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07623       struct pbx_find_info q = { .stacklen = 0 };
07624 
07625       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07626          PRIORITY_HINT, NULL, "", E_MATCH);
07627       /*
07628        * If this is a pattern, dynamically create a new extension for this
07629        * particular match.  Note that this will only happen once for each
07630        * individual extension, because the pattern will no longer match first.
07631        */
07632       if (exten && exten->exten[0] == '_') {
07633          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
07634             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
07635             exten->registrar);
07636          /* rwlocks are not recursive locks */
07637          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
07638             saved_hint->exten);
07639       }
07640 
07641       /* Find the hint in the hints container */
07642       hint = exten ? ao2_find(hints, exten, 0) : NULL;
07643       if (!hint) {
07644          /*
07645           * Notify watchers of this removed hint later when we aren't
07646           * encumberd by so many locks.
07647           */
07648          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
07649       } else {
07650          ao2_lock(hint);
07651          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07652             ao2_link(hint->callbacks, thiscb);
07653             /* Ref that we added when putting into saved_hint->callbacks */
07654             ao2_ref(thiscb, -1);
07655          }
07656          hint->laststate = saved_hint->laststate;
07657          ao2_unlock(hint);
07658          ao2_ref(hint, -1);
07659          ast_free(saved_hint);
07660       }
07661    }
07662 
07663    ao2_unlock(hints);
07664    ast_unlock_contexts();
07665 
07666    /*
07667     * Notify watchers of all removed hints with the same lock
07668     * environment as handle_statechange().
07669     */
07670    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
07671       /* this hint has been removed, notify the watchers */
07672       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07673          thiscb->change_cb(saved_hint->context, saved_hint->exten,
07674             AST_EXTENSION_REMOVED, thiscb->data);
07675          /* Ref that we added when putting into saved_hint->callbacks */
07676          ao2_ref(thiscb, -1);
07677       }
07678       ast_free(saved_hint);
07679    }
07680 
07681    ast_mutex_unlock(&context_merge_lock);
07682    endlocktime = ast_tvnow();
07683 
07684    /*
07685     * The old list and hashtab no longer are relevant, delete them
07686     * while the rest of asterisk is now freely using the new stuff
07687     * instead.
07688     */
07689 
07690    ast_hashtab_destroy(oldtable, NULL);
07691 
07692    for (tmp = oldcontextslist; tmp; ) {
07693       struct ast_context *next;  /* next starting point */
07694 
07695       next = tmp->next;
07696       __ast_internal_context_destroy(tmp);
07697       tmp = next;
07698    }
07699    enddeltime = ast_tvnow();
07700 
07701    ft = ast_tvdiff_us(writelocktime, begintime);
07702    ft /= 1000000.0;
07703    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07704 
07705    ft = ast_tvdiff_us(endlocktime, writelocktime);
07706    ft /= 1000000.0;
07707    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07708 
07709    ft = ast_tvdiff_us(enddeltime, endlocktime);
07710    ft /= 1000000.0;
07711    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07712 
07713    ft = ast_tvdiff_us(enddeltime, begintime);
07714    ft /= 1000000.0;
07715    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07716 }

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

10769 {
10770    return pbx_parseable_goto(chan, goto_string, 0);
10771 }

int ast_pbx_init ( void   ) 

int ast_pbx_outgoing_app ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
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 9107 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_name(), 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().

09108 {
09109    struct ast_channel *chan;
09110    struct app_tmp *tmp;
09111    int res = -1, cdr_res = -1;
09112    struct outgoing_helper oh;
09113 
09114    memset(&oh, 0, sizeof(oh));
09115    oh.vars = vars;
09116    oh.account = account;
09117 
09118    if (locked_channel)
09119       *locked_channel = NULL;
09120    if (ast_strlen_zero(app)) {
09121       res = -1;
09122       goto outgoing_app_cleanup;
09123    }
09124    if (synchronous) {
09125       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
09126       if (chan) {
09127          ast_set_variables(chan, vars);
09128          if (account)
09129             ast_cdr_setaccount(chan, account);
09130          if (chan->_state == AST_STATE_UP) {
09131             res = 0;
09132             ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
09133             tmp = ast_calloc(1, sizeof(*tmp));
09134             if (!tmp || ast_string_field_init(tmp, 252)) {
09135                if (tmp) {
09136                   ast_free(tmp);
09137                }
09138                res = -1;
09139             } else {
09140                ast_string_field_set(tmp, app, app);
09141                ast_string_field_set(tmp, data, appdata);
09142                tmp->chan = chan;
09143                if (synchronous > 1) {
09144                   if (locked_channel)
09145                      ast_channel_unlock(chan);
09146                   ast_pbx_run_app(tmp);
09147                } else {
09148                   if (locked_channel)
09149                      ast_channel_lock(chan);
09150                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
09151                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", ast_channel_name(chan), strerror(errno));
09152                      ast_string_field_free_memory(tmp);
09153                      ast_free(tmp);
09154                      if (locked_channel)
09155                         ast_channel_unlock(chan);
09156                      ast_hangup(chan);
09157                      res = -1;
09158                   } else {
09159                      if (locked_channel)
09160                         *locked_channel = chan;
09161                   }
09162                }
09163             }
09164          } else {
09165             ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan));
09166             if (chan->cdr) { /* update the cdr */
09167                /* here we update the status of the call, which sould be busy.
09168                 * if that fails then we set the status to failed */
09169                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09170                   ast_cdr_failed(chan->cdr);
09171             }
09172             ast_hangup(chan);
09173          }
09174       }
09175 
09176       if (res < 0) { /* the call failed for some reason */
09177          if (*reason == 0) { /* if the call failed (not busy or no answer)
09178                         * update the cdr with the failed message */
09179             cdr_res = ast_pbx_outgoing_cdr_failed();
09180             if (cdr_res != 0) {
09181                res = cdr_res;
09182                goto outgoing_app_cleanup;
09183             }
09184          }
09185       }
09186 
09187    } else {
09188       struct async_stat *as;
09189       if (!(as = ast_calloc(1, sizeof(*as)))) {
09190          res = -1;
09191          goto outgoing_app_cleanup;
09192       }
09193       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
09194       if (!chan) {
09195          ast_free(as);
09196          res = -1;
09197          goto outgoing_app_cleanup;
09198       }
09199       as->chan = chan;
09200       ast_copy_string(as->app, app, sizeof(as->app));
09201       if (appdata)
09202          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09203       as->timeout = timeout;
09204       ast_set_variables(chan, vars);
09205       if (account)
09206          ast_cdr_setaccount(chan, account);
09207       /* Start a new thread, and get something handling this channel. */
09208       if (locked_channel)
09209          ast_channel_lock(chan);
09210       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09211          ast_log(LOG_WARNING, "Failed to start async wait\n");
09212          ast_free(as);
09213          if (locked_channel)
09214             ast_channel_unlock(chan);
09215          ast_hangup(chan);
09216          res = -1;
09217          goto outgoing_app_cleanup;
09218       } else {
09219          if (locked_channel)
09220             *locked_channel = chan;
09221       }
09222       res = 0;
09223    }
09224 outgoing_app_cleanup:
09225    ast_variables_destroy(vars);
09226    return res;
09227 }

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

08912 {
08913    /* allocate a channel */
08914    struct ast_channel *chan = ast_dummy_channel_alloc();
08915 
08916    if (!chan)
08917       return -1;  /* failure */
08918 
08919    chan->cdr = ast_cdr_alloc();
08920    if (!chan->cdr) {
08921       /* allocation of the cdr failed */
08922       chan = ast_channel_unref(chan);   /* free the channel */
08923       return -1;                /* return failure */
08924    }
08925 
08926    /* allocation of the cdr was successful */
08927    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
08928    ast_cdr_start(chan->cdr);       /* record the start and stop time */
08929    ast_cdr_end(chan->cdr);
08930    ast_cdr_failed(chan->cdr);      /* set the status to failed */
08931    ast_cdr_detach(chan->cdr);      /* post and free the record */
08932    chan->cdr = NULL;
08933    chan = ast_channel_unref(chan);         /* free the channel */
08934 
08935    return 0;  /* success */
08936 }

int ast_pbx_outgoing_exten ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
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 8938 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_name(), 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().

08939 {
08940    struct ast_channel *chan;
08941    struct async_stat *as;
08942    int res = -1, cdr_res = -1;
08943    struct outgoing_helper oh;
08944 
08945    if (synchronous) {
08946       oh.context = context;
08947       oh.exten = exten;
08948       oh.priority = priority;
08949       oh.cid_num = cid_num;
08950       oh.cid_name = cid_name;
08951       oh.account = account;
08952       oh.vars = vars;
08953       oh.parent_channel = NULL;
08954 
08955       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
08956       if (channel) {
08957          *channel = chan;
08958          if (chan)
08959             ast_channel_lock(chan);
08960       }
08961       if (chan) {
08962          if (chan->_state == AST_STATE_UP) {
08963                res = 0;
08964             ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
08965 
08966             if (synchronous > 1) {
08967                if (channel)
08968                   ast_channel_unlock(chan);
08969                if (ast_pbx_run(chan)) {
08970                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan));
08971                   if (channel)
08972                      *channel = NULL;
08973                   ast_hangup(chan);
08974                   chan = NULL;
08975                   res = -1;
08976                }
08977             } else {
08978                if (ast_pbx_start(chan)) {
08979                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", ast_channel_name(chan));
08980                   if (channel) {
08981                      *channel = NULL;
08982                      ast_channel_unlock(chan);
08983                   }
08984                   ast_hangup(chan);
08985                   res = -1;
08986                }
08987                chan = NULL;
08988             }
08989          } else {
08990             ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan));
08991 
08992             if (chan->cdr) { /* update the cdr */
08993                /* here we update the status of the call, which sould be busy.
08994                 * if that fails then we set the status to failed */
08995                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08996                   ast_cdr_failed(chan->cdr);
08997             }
08998 
08999             if (channel) {
09000                *channel = NULL;
09001                ast_channel_unlock(chan);
09002             }
09003             ast_hangup(chan);
09004             chan = NULL;
09005          }
09006       }
09007 
09008       if (res < 0) { /* the call failed for some reason */
09009          if (*reason == 0) { /* if the call failed (not busy or no answer)
09010                         * update the cdr with the failed message */
09011             cdr_res = ast_pbx_outgoing_cdr_failed();
09012             if (cdr_res != 0) {
09013                res = cdr_res;
09014                goto outgoing_exten_cleanup;
09015             }
09016          }
09017 
09018          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
09019          /* check if "failed" exists */
09020          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
09021             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
09022             if (chan) {
09023                char failed_reason[4] = "";
09024                if (!ast_strlen_zero(context))
09025                   ast_copy_string(chan->context, context, sizeof(chan->context));
09026                set_ext_pri(chan, "failed", 1);
09027                ast_set_variables(chan, vars);
09028                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
09029                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
09030                if (account)
09031                   ast_cdr_setaccount(chan, account);
09032                if (ast_pbx_run(chan)) {
09033                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan));
09034                   ast_hangup(chan);
09035                }
09036                chan = NULL;
09037             }
09038          }
09039       }
09040    } else {
09041       if (!(as = ast_calloc(1, sizeof(*as)))) {
09042          res = -1;
09043          goto outgoing_exten_cleanup;
09044       }
09045       chan = ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name);
09046       if (channel) {
09047          *channel = chan;
09048          if (chan)
09049             ast_channel_lock(chan);
09050       }
09051       if (!chan) {
09052          ast_free(as);
09053          res = -1;
09054          goto outgoing_exten_cleanup;
09055       }
09056       as->chan = chan;
09057       ast_copy_string(as->context, context, sizeof(as->context));
09058       set_ext_pri(as->chan,  exten, priority);
09059       as->timeout = timeout;
09060       ast_set_variables(chan, vars);
09061       if (account)
09062          ast_cdr_setaccount(chan, account);
09063       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09064          ast_log(LOG_WARNING, "Failed to start async wait\n");
09065          ast_free(as);
09066          if (channel) {
09067             *channel = NULL;
09068             ast_channel_unlock(chan);
09069          }
09070          ast_hangup(chan);
09071          res = -1;
09072          goto outgoing_exten_cleanup;
09073       }
09074       res = 0;
09075    }
09076 outgoing_exten_cleanup:
09077    ast_variables_destroy(vars);
09078    return res;
09079 }

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

05542 {
05543    return ast_pbx_run_args(c, NULL);
05544 }

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

run the application and free the descriptor once done

Definition at line 9091 of file pbx.c.

References app_tmp::app, ast_channel_name(), 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().

09092 {
09093    struct app_tmp *tmp = data;
09094    struct ast_app *app;
09095    app = pbx_findapp(tmp->app);
09096    if (app) {
09097       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, ast_channel_name(tmp->chan));
09098       pbx_exec(tmp->chan, app, tmp->data);
09099    } else
09100       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
09101    ast_hangup(tmp->chan);
09102    ast_string_field_free_memory(tmp);
09103    ast_free(tmp);
09104    return NULL;
09105 }

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 5521 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 action_dialplan_exec(), ast_pbx_run(), dial_exec_full(), handle_gosub(), msg_route(), and try_calling().

05522 {
05523    enum ast_pbx_result res = AST_PBX_SUCCESS;
05524 
05525    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05526       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05527       return AST_PBX_FAILED;
05528    }
05529 
05530    if (increase_call_count(c)) {
05531       return AST_PBX_CALL_LIMIT;
05532    }
05533 
05534    res = __ast_pbx_run(c, args);
05535 
05536    decrease_call_count();
05537 
05538    return res;
05539 }

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 5494 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(), rpt_call(), skinny_new(), unistim_new(), and usbradio_new().

05495 {
05496    pthread_t t;
05497 
05498    if (!c) {
05499       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05500       return AST_PBX_FAILED;
05501    }
05502 
05503    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05504       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05505       return AST_PBX_FAILED;
05506    }
05507 
05508    if (increase_call_count(c))
05509       return AST_PBX_CALL_LIMIT;
05510 
05511    /* Start a new thread, and get something handling this channel. */
05512    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05513       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05514       decrease_call_count();
05515       return AST_PBX_FAILED;
05516    }
05517 
05518    return AST_PBX_SUCCESS;
05519 }

int ast_processed_calls ( void   ) 

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

Definition at line 5551 of file pbx.c.

References totalcalls.

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

05552 {
05553    return totalcalls;
05554 }

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

10503 {
10504    return ast_rwlock_rdlock(&con->lock);
10505 }

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 5962 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, COLOR_BRCYAN, 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(), ast_msg_init(), and load_pbx().

05963 {
05964    struct ast_app *tmp, *cur = NULL;
05965    char tmps[80];
05966    int length, res;
05967 #ifdef AST_XML_DOCS
05968    char *tmpxml;
05969 #endif
05970 
05971    AST_RWLIST_WRLOCK(&apps);
05972    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
05973       if (!(res = strcasecmp(app, tmp->name))) {
05974          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
05975          AST_RWLIST_UNLOCK(&apps);
05976          return -1;
05977       } else if (res < 0)
05978          break;
05979    }
05980 
05981    length = sizeof(*tmp) + strlen(app) + 1;
05982 
05983    if (!(tmp = ast_calloc(1, length))) {
05984       AST_RWLIST_UNLOCK(&apps);
05985       return -1;
05986    }
05987 
05988    if (ast_string_field_init(tmp, 128)) {
05989       AST_RWLIST_UNLOCK(&apps);
05990       ast_free(tmp);
05991       return -1;
05992    }
05993 
05994    strcpy(tmp->name, app);
05995    tmp->execute = execute;
05996    tmp->module = mod;
05997 
05998 #ifdef AST_XML_DOCS
05999    /* Try to lookup the docs in our XML documentation database */
06000    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
06001       /* load synopsis */
06002       tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
06003       ast_string_field_set(tmp, synopsis, tmpxml);
06004       ast_free(tmpxml);
06005 
06006       /* load description */
06007       tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
06008       ast_string_field_set(tmp, description, tmpxml);
06009       ast_free(tmpxml);
06010 
06011       /* load syntax */
06012       tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
06013       ast_string_field_set(tmp, syntax, tmpxml);
06014       ast_free(tmpxml);
06015 
06016       /* load arguments */
06017       tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
06018       ast_string_field_set(tmp, arguments, tmpxml);
06019       ast_free(tmpxml);
06020 
06021       /* load seealso */
06022       tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
06023       ast_string_field_set(tmp, seealso, tmpxml);
06024       ast_free(tmpxml);
06025       tmp->docsrc = AST_XML_DOC;
06026    } else {
06027 #endif
06028       ast_string_field_set(tmp, synopsis, synopsis);
06029       ast_string_field_set(tmp, description, description);
06030 #ifdef AST_XML_DOCS
06031       tmp->docsrc = AST_STATIC_DOC;
06032    }
06033 #endif
06034 
06035    /* Store in alphabetical order */
06036    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
06037       if (strcasecmp(tmp->name, cur->name) < 0) {
06038          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
06039          break;
06040       }
06041    }
06042    AST_RWLIST_TRAVERSE_SAFE_END;
06043    if (!cur)
06044       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
06045 
06046    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
06047 
06048    AST_RWLIST_UNLOCK(&apps);
06049 
06050    return 0;
06051 }

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

06058 {
06059    struct ast_switch *tmp;
06060 
06061    AST_RWLIST_WRLOCK(&switches);
06062    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
06063       if (!strcasecmp(tmp->name, sw->name)) {
06064          AST_RWLIST_UNLOCK(&switches);
06065          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
06066          return -1;
06067       }
06068    }
06069    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
06070    AST_RWLIST_UNLOCK(&switches);
06071 
06072    return 0;
06073 }

static int ast_remove_hint ( struct ast_exten e  )  [static]

Remove hint from extension.

Definition at line 4853 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, OBJ_UNLINK, and remove_hintdevice().

Referenced by destroy_exten().

04854 {
04855    /* Cleanup the Notifys if hint is removed */
04856    struct ast_hint *hint;
04857 
04858    if (!e) {
04859       return -1;
04860    }
04861 
04862    hint = ao2_find(hints, e, OBJ_UNLINK);
04863    if (!hint) {
04864       return -1;
04865    }
04866 
04867    remove_hintdevice(hint);
04868 
04869    /*
04870     * The extension is being destroyed so we must save some
04871     * information to notify that the extension is deactivated.
04872     */
04873    ao2_lock(hint);
04874    ast_copy_string(hint->context_name,
04875       ast_get_context_name(ast_get_extension_context(hint->exten)),
04876       sizeof(hint->context_name));
04877    ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten),
04878       sizeof(hint->exten_name));
04879    hint->exten = NULL;
04880    ao2_unlock(hint);
04881 
04882    ao2_ref(hint, -1);
04883 
04884    return 0;
04885 }

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

References E_SPAWN, and pbx_extension_helper().

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

05052 {
05053    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05054 }

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

05007 {
05008    struct ast_exten *e = ast_hint_extension(c, context, exten);
05009 
05010    if (!e) {
05011       return 0;
05012    }
05013 
05014    if (hint) {
05015       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05016    }
05017    if (name) {
05018       const char *tmp = ast_get_extension_app_data(e);
05019       if (tmp) {
05020          ast_str_set(name, namesize, "%s", tmp);
05021       }
05022    }
05023    return -1;
05024 }

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

References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), ast_channel_unlock, ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_DATA_DIR, ast_config_AST_DB, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_SYSTEM_NAME, ast_config_AST_VAR_DIR, 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_var_t::entries, 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().

03252 {
03253    const char not_found = '\0';
03254    char *tmpvar;
03255    const char *ret;
03256    const char *s; /* the result */
03257    int offset, length;
03258    int i, need_substring;
03259    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03260 
03261    if (c) {
03262       ast_channel_lock(c);
03263       places[0] = &c->varshead;
03264    }
03265    /*
03266     * Make a copy of var because parse_variable_name() modifies the string.
03267     * Then if called directly, we might need to run substring() on the result;
03268     * remember this for later in 'need_substring', 'offset' and 'length'
03269     */
03270    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03271    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03272 
03273    /*
03274     * Look first into predefined variables, then into variable lists.
03275     * Variable 's' points to the result, according to the following rules:
03276     * s == &not_found (set at the beginning) means that we did not find a
03277     * matching variable and need to look into more places.
03278     * If s != &not_found, s is a valid result string as follows:
03279     * s = NULL if the variable does not have a value;
03280     * you typically do this when looking for an unset predefined variable.
03281     * s = workspace if the result has been assembled there;
03282     * typically done when the result is built e.g. with an snprintf(),
03283     * so we don't need to do an additional copy.
03284     * s != workspace in case we have a string, that needs to be copied
03285     * (the ast_copy_string is done once for all at the end).
03286     * Typically done when the result is already available in some string.
03287     */
03288    s = &not_found;   /* default value */
03289    if (c) { /* This group requires a valid channel */
03290       /* Names with common parts are looked up a piece at a time using strncmp. */
03291       if (!strncmp(var, "CALL", 4)) {
03292          if (!strncmp(var + 4, "ING", 3)) {
03293             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03294                ast_str_set(str, maxlen, "%d",
03295                   ast_party_id_presentation(&c->caller.id));
03296                s = ast_str_buffer(*str);
03297             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03298                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03299                s = ast_str_buffer(*str);
03300             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03301                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03302                s = ast_str_buffer(*str);
03303             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03304                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03305                s = ast_str_buffer(*str);
03306             }
03307          }
03308       } else if (!strcmp(var, "HINT")) {
03309          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03310       } else if (!strcmp(var, "HINTNAME")) {
03311          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03312       } else if (!strcmp(var, "EXTEN")) {
03313          s = c->exten;
03314       } else if (!strcmp(var, "CONTEXT")) {
03315          s = c->context;
03316       } else if (!strcmp(var, "PRIORITY")) {
03317          ast_str_set(str, maxlen, "%d", c->priority);
03318          s = ast_str_buffer(*str);
03319       } else if (!strcmp(var, "CHANNEL")) {
03320          s = ast_channel_name(c);
03321       } else if (!strcmp(var, "UNIQUEID")) {
03322          s = ast_channel_uniqueid(c);
03323       } else if (!strcmp(var, "HANGUPCAUSE")) {
03324          ast_str_set(str, maxlen, "%d", c->hangupcause);
03325          s = ast_str_buffer(*str);
03326       }
03327    }
03328    if (s == &not_found) { /* look for more */
03329       if (!strcmp(var, "EPOCH")) {
03330          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03331          s = ast_str_buffer(*str);
03332       } else if (!strcmp(var, "SYSTEMNAME")) {
03333          s = ast_config_AST_SYSTEM_NAME;
03334       } else if (!strcmp(var, "ASTETCDIR")) {
03335          s = ast_config_AST_CONFIG_DIR;
03336       } else if (!strcmp(var, "ASTMODDIR")) {
03337          s = ast_config_AST_MODULE_DIR;
03338       } else if (!strcmp(var, "ASTVARLIBDIR")) {
03339          s = ast_config_AST_VAR_DIR;
03340       } else if (!strcmp(var, "ASTDBDIR")) {
03341          s = ast_config_AST_DB;
03342       } else if (!strcmp(var, "ASTKEYDIR")) {
03343          s = ast_config_AST_KEY_DIR;
03344       } else if (!strcmp(var, "ASTDATADIR")) {
03345          s = ast_config_AST_DATA_DIR;
03346       } else if (!strcmp(var, "ASTAGIDIR")) {
03347          s = ast_config_AST_AGI_DIR;
03348       } else if (!strcmp(var, "ASTSPOOLDIR")) {
03349          s = ast_config_AST_SPOOL_DIR;
03350       } else if (!strcmp(var, "ASTRUNDIR")) {
03351          s = ast_config_AST_RUN_DIR;
03352       } else if (!strcmp(var, "ASTLOGDIR")) {
03353          s = ast_config_AST_LOG_DIR;
03354       } else if (!strcmp(var, "ENTITYID")) {
03355          char workspace[20];
03356          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03357          s = workspace;
03358       }
03359    }
03360    /* if not found, look into chanvars or global vars */
03361    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03362       struct ast_var_t *variables;
03363       if (!places[i])
03364          continue;
03365       if (places[i] == &globals)
03366          ast_rwlock_rdlock(&globalslock);
03367       AST_LIST_TRAVERSE(places[i], variables, entries) {
03368          if (!strcasecmp(ast_var_name(variables), var)) {
03369             s = ast_var_value(variables);
03370             break;
03371          }
03372       }
03373       if (places[i] == &globals)
03374          ast_rwlock_unlock(&globalslock);
03375    }
03376    if (s == &not_found || s == NULL) {
03377       ast_debug(5, "Result of '%s' is NULL\n", var);
03378       ret = NULL;
03379    } else {
03380       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03381       if (s != ast_str_buffer(*str)) {
03382          ast_str_set(str, maxlen, "%s", s);
03383       }
03384       ret = ast_str_buffer(*str);
03385       if (need_substring) {
03386          ret = ast_str_substring(*str, offset, length);
03387          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03388       }
03389    }
03390 
03391    if (c) {
03392       ast_channel_unlock(c);
03393    }
03394    return ret;
03395 }

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 4069 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(), do_notify(), 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(), strreplace(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().

04070 {
04071    size_t used;
04072    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04073 }

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

03891 {
03892    /* Substitutes variables into buf, based on string templ */
03893    char *cp4 = NULL;
03894    const char *whereweare;
03895    int orig_size = 0;
03896    int offset, offset2, isfunction;
03897    const char *nextvar, *nextexp, *nextthing;
03898    const char *vars, *vare;
03899    char *finalvars;
03900    int pos, brackets, needsub, len;
03901    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
03902 
03903    ast_str_reset(*buf);
03904    whereweare = templ;
03905    while (!ast_strlen_zero(whereweare)) {
03906       /* reset our buffer */
03907       ast_str_reset(substr3);
03908 
03909       /* Assume we're copying the whole remaining string */
03910       pos = strlen(whereweare);
03911       nextvar = NULL;
03912       nextexp = NULL;
03913       nextthing = strchr(whereweare, '$');
03914       if (nextthing) {
03915          switch (nextthing[1]) {
03916          case '{':
03917             nextvar = nextthing;
03918             pos = nextvar - whereweare;
03919             break;
03920          case '[':
03921             nextexp = nextthing;
03922             pos = nextexp - whereweare;
03923             break;
03924          default:
03925             pos = 1;
03926          }
03927       }
03928 
03929       if (pos) {
03930          /* Copy that many bytes */
03931          ast_str_append_substr(buf, maxlen, whereweare, pos);
03932 
03933          templ += pos;
03934          whereweare += pos;
03935       }
03936 
03937       if (nextvar) {
03938          /* We have a variable.  Find the start and end, and determine
03939             if we are going to have to recursively call ourselves on the
03940             contents */
03941          vars = vare = nextvar + 2;
03942          brackets = 1;
03943          needsub = 0;
03944 
03945          /* Find the end of it */
03946          while (brackets && *vare) {
03947             if ((vare[0] == '$') && (vare[1] == '{')) {
03948                needsub++;
03949             } else if (vare[0] == '{') {
03950                brackets++;
03951             } else if (vare[0] == '}') {
03952                brackets--;
03953             } else if ((vare[0] == '$') && (vare[1] == '['))
03954                needsub++;
03955             vare++;
03956          }
03957          if (brackets)
03958             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03959          len = vare - vars - 1;
03960 
03961          /* Skip totally over variable string */
03962          whereweare += (len + 3);
03963 
03964          /* Store variable name (and truncate) */
03965          ast_str_set_substr(&substr1, 0, vars, len);
03966          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
03967 
03968          /* Substitute if necessary */
03969          if (needsub) {
03970             size_t used;
03971             if (!substr2) {
03972                substr2 = ast_str_create(16);
03973             }
03974 
03975             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03976             finalvars = ast_str_buffer(substr2);
03977          } else {
03978             finalvars = ast_str_buffer(substr1);
03979          }
03980 
03981          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
03982          if (isfunction) {
03983             /* Evaluate function */
03984             if (c || !headp) {
03985                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03986             } else {
03987                struct varshead old;
03988                struct ast_channel *bogus = ast_dummy_channel_alloc();
03989                if (bogus) {
03990                   memcpy(&old, &bogus->varshead, sizeof(old));
03991                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03992                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03993                   /* Don't deallocate the varshead that was passed in */
03994                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03995                   ast_channel_unref(bogus);
03996                } else {
03997                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03998                }
03999             }
04000             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04001          } else {
04002             /* Retrieve variable value */
04003             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04004             cp4 = ast_str_buffer(substr3);
04005          }
04006          if (cp4) {
04007             ast_str_substring(substr3, offset, offset2);
04008             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04009          }
04010       } else if (nextexp) {
04011          /* We have an expression.  Find the start and end, and determine
04012             if we are going to have to recursively call ourselves on the
04013             contents */
04014          vars = vare = nextexp + 2;
04015          brackets = 1;
04016          needsub = 0;
04017 
04018          /* Find the end of it */
04019          while (brackets && *vare) {
04020             if ((vare[0] == '$') && (vare[1] == '[')) {
04021                needsub++;
04022                brackets++;
04023                vare++;
04024             } else if (vare[0] == '[') {
04025                brackets++;
04026             } else if (vare[0] == ']') {
04027                brackets--;
04028             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04029                needsub++;
04030                vare++;
04031             }
04032             vare++;
04033          }
04034          if (brackets)
04035             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04036          len = vare - vars - 1;
04037 
04038          /* Skip totally over expression */
04039          whereweare += (len + 3);
04040 
04041          /* Store variable name (and truncate) */
04042          ast_str_set_substr(&substr1, 0, vars, len);
04043 
04044          /* Substitute if necessary */
04045          if (needsub) {
04046             size_t used;
04047             if (!substr2) {
04048                substr2 = ast_str_create(16);
04049             }
04050 
04051             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04052             finalvars = ast_str_buffer(substr2);
04053          } else {
04054             finalvars = ast_str_buffer(substr1);
04055          }
04056 
04057          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04058             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04059          }
04060          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04061       }
04062    }
04063    *used = ast_str_strlen(*buf) - orig_size;
04064    ast_free(substr1);
04065    ast_free(substr2);
04066    ast_free(substr3);
04067 }

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

04076 {
04077    size_t used;
04078    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04079 }

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

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

03187 {
03188    int lr;  /* length of the input string after the copy */
03189 
03190    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
03191 
03192    /* Quick check if no need to do anything */
03193    if (offset == 0 && length >= lr) /* take the whole string */
03194       return ast_str_buffer(value);
03195 
03196    if (offset < 0)   {  /* translate negative offset into positive ones */
03197       offset = lr + offset;
03198       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03199          offset = 0;
03200    }
03201 
03202    /* too large offset result in empty string so we know what to return */
03203    if (offset >= lr) {
03204       ast_str_reset(value);
03205       return ast_str_buffer(value);
03206    }
03207 
03208    if (offset > 0) {
03209       /* Go ahead and chop off the beginning */
03210       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
03211       lr -= offset;
03212    }
03213 
03214    if (length >= 0 && length < lr) {   /* truncate if necessary */
03215       char *tmp = ast_str_buffer(value);
03216       tmp[length] = '\0';
03217       ast_str_update(value);
03218    } else if (length < 0) {
03219       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
03220          char *tmp = ast_str_buffer(value);
03221          tmp[lr + length] = '\0';
03222          ast_str_update(value);
03223       } else {
03224          ast_str_reset(value);
03225       }
03226    } else {
03227       /* Nothing to do, but update the buffer length */
03228       ast_str_update(value);
03229    }
03230 
03231    return ast_str_buffer(value);
03232 }

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 7303 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(), load_module(), and unload_module().

07304 {
07305    struct ast_app *tmp;
07306 
07307    AST_RWLIST_WRLOCK(&apps);
07308    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
07309       if (!strcasecmp(app, tmp->name)) {
07310          unreference_cached_app(tmp);
07311          AST_RWLIST_REMOVE_CURRENT(list);
07312          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
07313          ast_string_field_free_memory(tmp);
07314          ast_free(tmp);
07315          break;
07316       }
07317    }
07318    AST_RWLIST_TRAVERSE_SAFE_END;
07319    AST_RWLIST_UNLOCK(&apps);
07320 
07321    return tmp ? 0 : -1;
07322 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __unload_module(), and unload_module().

06076 {
06077    AST_RWLIST_WRLOCK(&switches);
06078    AST_RWLIST_REMOVE(&switches, sw, list);
06079    AST_RWLIST_UNLOCK(&switches);
06080 }

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

Definition at line 10621 of file pbx.c.

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

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

10623 {
10624    if (!exten)
10625       return con ? con->root : NULL;
10626    else
10627       return exten->next;
10628 }

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

Definition at line 10654 of file pbx.c.

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

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

10656 {
10657    if (!ip)
10658       return con ? con->ignorepats : NULL;
10659    else
10660       return ip->next;
10661 }

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

References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.

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

10632 {
10633    if (!sw)
10634       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10635    else
10636       return AST_LIST_NEXT(sw, list);
10637 }

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

10641 {
10642    return priority ? priority->peer : exten;
10643 }

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

10498 {
10499    return ast_rwlock_wrlock(&con->lock);
10500 }

int ast_wrlock_contexts ( void   ) 

Write locks the context list.

Return values:
0 on success
-1 on error

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

10480 {
10481    return ast_mutex_lock(&conlock);
10482 }

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

Definition at line 8850 of file pbx.c.

References ast_channel::_state, async_stat::app, async_stat::appdata, ast_channel_name(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_free, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), AST_STATE_UP, ast_strlen_zero(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, 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().

08851 {
08852    struct async_stat *as = data;
08853    struct ast_channel *chan = as->chan;
08854    int timeout = as->timeout;
08855    int res;
08856    struct ast_frame *f;
08857    struct ast_app *app;
08858 
08859    while (timeout && (chan->_state != AST_STATE_UP)) {
08860       res = ast_waitfor(chan, timeout);
08861       if (res < 1)
08862          break;
08863       if (timeout > -1)
08864          timeout = res;
08865       f = ast_read(chan);
08866       if (!f)
08867          break;
08868       if (f->frametype == AST_FRAME_CONTROL) {
08869          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
08870              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
08871             ast_frfree(f);
08872             break;
08873          }
08874       }
08875       ast_frfree(f);
08876    }
08877    if (chan->_state == AST_STATE_UP) {
08878       if (!ast_strlen_zero(as->app)) {
08879          app = pbx_findapp(as->app);
08880          if (app) {
08881             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, ast_channel_name(chan));
08882             pbx_exec(chan, app, as->appdata);
08883          } else
08884             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
08885       } else {
08886          if (!ast_strlen_zero(as->context))
08887             ast_copy_string(chan->context, as->context, sizeof(chan->context));
08888          if (!ast_strlen_zero(as->exten))
08889             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
08890          if (as->priority > 0)
08891             chan->priority = as->priority;
08892          /* Run the PBX */
08893          if (ast_pbx_run(chan)) {
08894             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
08895          } else {
08896             /* PBX will have taken care of this */
08897             chan = NULL;
08898          }
08899       }
08900    }
08901    ast_free(as);
08902    if (chan)
08903       ast_hangup(chan);
08904    return NULL;
08905 }

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

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

01730 {
01731    char extenstr[40];
01732    struct ast_str *my_prefix = ast_str_alloca(1024);
01733 
01734    extenstr[0] = '\0';
01735 
01736    if (node && node->exten)
01737       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01738 
01739    if (strlen(node->x) > 1) {
01740       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01741          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01742          node->exten ? node->exten->exten : "", extenstr);
01743    } else {
01744       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01745          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01746          node->exten ? node->exten->exten : "", extenstr);
01747    }
01748 
01749    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01750 
01751    if (node->next_char)
01752       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01753 
01754    if (node->alt_char)
01755       cli_match_char_tree(node->alt_char, prefix, fd);
01756 }

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

05073 {
05074    int digit;
05075 
05076    buf[pos] = '\0';  /* make sure it is properly terminated */
05077    while (ast_matchmore_extension(c, c->context, buf, 1,
05078       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05079       /* As long as we're willing to wait, and as long as it's not defined,
05080          keep reading digits until we can't possibly get a right answer anymore.  */
05081       digit = ast_waitfordigit(c, waittime);
05082       if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05083          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05084       } else {
05085          if (!digit) /* No entry */
05086             break;
05087          if (digit < 0) /* Error, maybe a  hangup */
05088             return -1;
05089          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
05090             buf[pos++] = digit;
05091             buf[pos] = '\0';
05092          }
05093          waittime = c->pbx->dtimeoutms;
05094       }
05095    }
05096    return 0;
05097 }

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

Definition at line 1177 of file pbx.c.

Referenced by get_pattern_node().

01178 {
01179    const unsigned char *ac = a;
01180    const unsigned char *bc = b;
01181 
01182    return *ac - *bc;
01183 }

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

06263 {
06264    struct ast_hint *hint;
06265    char *ret = NULL;
06266    int which = 0;
06267    int wordlen;
06268    struct ao2_iterator i;
06269 
06270    if (pos != 3)
06271       return NULL;
06272 
06273    wordlen = strlen(word);
06274 
06275    /* walk through all hints */
06276    i = ao2_iterator_init(hints, 0);
06277    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06278       ao2_lock(hint);
06279       if (!hint->exten) {
06280          /* The extension has already been destroyed */
06281          ao2_unlock(hint);
06282          continue;
06283       }
06284       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
06285          ret = ast_strdup(ast_get_extension_name(hint->exten));
06286          ao2_unlock(hint);
06287          ao2_ref(hint, -1);
06288          break;
06289       }
06290       ao2_unlock(hint);
06291    }
06292    ao2_iterator_destroy(&i);
06293 
06294    return ret;
06295 }

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

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

06474 {
06475    struct ast_context *c = NULL;
06476    char *ret = NULL;
06477    int which = 0;
06478    int wordlen;
06479 
06480    /* we are do completion of [exten@]context on second position only */
06481    if (pos != 2)
06482       return NULL;
06483 
06484    ast_rdlock_contexts();
06485 
06486    wordlen = strlen(word);
06487 
06488    /* walk through all contexts and return the n-th match */
06489    while ( (c = ast_walk_contexts(c)) ) {
06490       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
06491          ret = ast_strdup(ast_get_context_name(c));
06492          break;
06493       }
06494    }
06495 
06496    ast_unlock_contexts();
06497 
06498    return ret;
06499 }

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

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

07445 {
07446    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
07447    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
07448    struct ast_hashtab_iter *exten_iter;
07449    struct ast_hashtab_iter *prio_iter;
07450    int insert_count = 0;
07451    int first = 1;
07452 
07453    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
07454       the current registrar, and copy them to the new context. If the new context does not
07455       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
07456       only create the empty matching context if the old one meets the criteria */
07457 
07458    if (context->root_table) {
07459       exten_iter = ast_hashtab_start_traversal(context->root_table);
07460       while ((exten_item=ast_hashtab_next(exten_iter))) {
07461          if (new) {
07462             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
07463          } else {
07464             new_exten_item = NULL;
07465          }
07466          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
07467          while ((prio_item=ast_hashtab_next(prio_iter))) {
07468             int res1;
07469             char *dupdstr;
07470 
07471             if (new_exten_item) {
07472                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
07473             } else {
07474                new_prio_item = NULL;
07475             }
07476             if (strcmp(prio_item->registrar,registrar) == 0) {
07477                continue;
07478             }
07479             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
07480             if (!new) {
07481                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 */
07482             }
07483 
07484             /* copy in the includes, switches, and ignorepats */
07485             if (first) { /* but, only need to do this once */
07486                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07487                first = 0;
07488             }
07489 
07490             if (!new) {
07491                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
07492                return; /* no sense continuing. */
07493             }
07494             /* we will not replace existing entries in the new context with stuff from the old context.
07495                but, if this is because of some sort of registrar conflict, we ought to say something... */
07496 
07497             dupdstr = ast_strdup(prio_item->data);
07498 
07499             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
07500                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
07501             if (!res1 && new_exten_item && new_prio_item){
07502                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
07503                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
07504             } else {
07505                /* 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,
07506                 and no double frees take place, either! */
07507                insert_count++;
07508             }
07509          }
07510          ast_hashtab_end_traversal(prio_iter);
07511       }
07512       ast_hashtab_end_traversal(exten_iter);
07513    }
07514 
07515    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
07516         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
07517       /* we could have given it the registrar of the other module who incremented the refcount,
07518          but that's not available, so we give it the registrar we know about */
07519       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
07520 
07521       /* copy in the includes, switches, and ignorepats */
07522       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07523    }
07524 }

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

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

07412 {
07413    struct ast_include *i;
07414    struct ast_ignorepat *ip;
07415    struct ast_sw *sw;
07416 
07417    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);
07418    /* copy in the includes, switches, and ignorepats */
07419    /* walk through includes */
07420    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
07421       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
07422          continue; /* not mine */
07423       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
07424    }
07425 
07426    /* walk through switches */
07427    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
07428       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
07429          continue; /* not mine */
07430       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));
07431    }
07432 
07433    /* walk thru ignorepats ... */
07434    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
07435       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
07436          continue; /* not mine */
07437       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
07438    }
07439 }

static void create_match_char_tree ( struct ast_context con  )  [static]

Definition at line 2350 of file pbx.c.

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

Referenced by pbx_find_extension().

02351 {
02352    struct ast_hashtab_iter *t1;
02353    struct ast_exten *e1;
02354 #ifdef NEED_DEBUG
02355    int biggest_bucket, resizes, numobjs, numbucks;
02356 
02357    ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con);
02358    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02359    ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02360          numobjs, numbucks, biggest_bucket, resizes);
02361 #endif
02362    t1 = ast_hashtab_start_traversal(con->root_table);
02363    while ((e1 = ast_hashtab_next(t1))) {
02364       if (e1->exten) {
02365          add_exten_to_pattern_tree(con, e1, 0);
02366       } else {
02367          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02368       }
02369    }
02370    ast_hashtab_end_traversal(t1);
02371 }

static void decrease_call_count ( void   )  [static]

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

05453 {
05454    ast_mutex_lock(&maxcalllock);
05455    if (countcalls > 0)
05456       countcalls--;
05457    ast_mutex_unlock(&maxcalllock);
05458 }

static void destroy_exten ( struct ast_exten e  )  [static]

static void destroy_hint ( void *  obj  )  [static]

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

04825 {
04826    struct ast_hint *hint = obj;
04827 
04828    if (hint->callbacks) {
04829       struct ast_state_cb *state_cb;
04830       const char *context_name;
04831       const char *exten_name;
04832 
04833       if (hint->exten) {
04834          context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
04835          exten_name = ast_get_extension_name(hint->exten);
04836          hint->exten = NULL;
04837       } else {
04838          /* The extension has already been destroyed */
04839          context_name = hint->context_name;
04840          exten_name = hint->exten_name;
04841       }
04842       while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
04843          /* Notify with -1 and remove all callbacks */
04844          state_cb->change_cb(context_name, exten_name, AST_EXTENSION_DEACTIVATED,
04845             state_cb->data);
04846          ao2_ref(state_cb, -1);
04847       }
04848       ao2_ref(hint->callbacks, -1);
04849    }
04850 }

static void destroy_pattern_tree ( struct match_char pattern_tree  )  [static]

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

02374 {
02375    /* destroy all the alternates */
02376    if (pattern_tree->alt_char) {
02377       destroy_pattern_tree(pattern_tree->alt_char);
02378       pattern_tree->alt_char = 0;
02379    }
02380    /* destroy all the nexts */
02381    if (pattern_tree->next_char) {
02382       destroy_pattern_tree(pattern_tree->next_char);
02383       pattern_tree->next_char = 0;
02384    }
02385    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02386    ast_free(pattern_tree);
02387 }

static void destroy_state_cb ( void *  doomed  )  [static]

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

04656 {
04657    struct ast_state_cb *state_cb = doomed;
04658 
04659    if (state_cb->destroy_cb) {
04660       state_cb->destroy_cb(state_cb->id, state_cb->data);
04661    }
04662 }

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

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

10375 {
10376    const char *device;
10377    struct statechange *sc;
10378 
10379    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
10380    if (ast_strlen_zero(device)) {
10381       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
10382       return;
10383    }
10384 
10385    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
10386       return;
10387    strcpy(sc->dev, device);
10388    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
10389       ast_free(sc);
10390    }
10391 }

static void exception_store_free ( void *  data  )  [static]

Definition at line 3397 of file pbx.c.

References ast_free, and ast_string_field_free_memory.

03398 {
03399    struct pbx_exception *exception = data;
03400    ast_string_field_free_memory(exception);
03401    ast_free(exception);
03402 }

static int ext_cmp ( const char *  a,
const char *  b 
) [static]

the full routine to compare extensions in rules.

Definition at line 2523 of file pbx.c.

References ext_cmp1().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

02524 {
02525    /* make sure non-patterns come first.
02526     * If a is not a pattern, it either comes first or
02527     * we do a more complex pattern comparison.
02528     */
02529    int ret = 0;
02530 
02531    if (a[0] != '_')
02532       return (b[0] == '_') ? -1 : strcmp(a, b);
02533 
02534    /* Now we know a is a pattern; if b is not, a comes first */
02535    if (b[0] != '_')
02536       return 1;
02537 
02538    /* ok we need full pattern sorting routine.
02539     * skip past the underscores */
02540    ++a; ++b;
02541    do {
02542       unsigned char bitwise[2][32] = { { 0, } };
02543       ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
02544       if (ret == 0) {
02545          /* Are the classes different, even though they score the same? */
02546          ret = memcmp(bitwise[0], bitwise[1], 32);
02547       }
02548    } while (!ret && a && b);
02549    if (ret == 0) {
02550       return 0;
02551    } else {
02552       return (ret > 0) ? 1 : -1;
02553    }
02554 }

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

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

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

Note:
If two patterns score the same, the one with the lowest ascii values will compare as coming first.

Definition at line 2443 of file pbx.c.

References ast_log(), and LOG_WARNING.

Referenced by ext_cmp().

02444 {
02445    int c, cmin = 0xff, count = 0;
02446    const char *end;
02447 
02448    /* load value and advance pointer */
02449    c = *(*p)++;
02450 
02451    /* always return unless we have a set of chars */
02452    switch (toupper(c)) {
02453    default: /* ordinary character */
02454       bitwise[c / 8] = 1 << (c % 8);
02455       return 0x0100 | (c & 0xff);
02456 
02457    case 'N':   /* 2..9 */
02458       bitwise[6] = 0xfc;
02459       bitwise[7] = 0x03;
02460       return 0x0800 | '2';
02461 
02462    case 'X':   /* 0..9 */
02463       bitwise[6] = 0xff;
02464       bitwise[7] = 0x03;
02465       return 0x0A00 | '0';
02466 
02467    case 'Z':   /* 1..9 */
02468       bitwise[6] = 0xfe;
02469       bitwise[7] = 0x03;
02470       return 0x0900 | '1';
02471 
02472    case '.':   /* wildcard */
02473       return 0x18000;
02474 
02475    case '!':   /* earlymatch */
02476       return 0x28000;   /* less specific than NULL */
02477 
02478    case '\0':  /* empty string */
02479       *p = NULL;
02480       return 0x30000;
02481 
02482    case '[':   /* pattern */
02483       break;
02484    }
02485    /* locate end of set */
02486    end = strchr(*p, ']');
02487 
02488    if (end == NULL) {
02489       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02490       return 0x40000;   /* XXX make this entry go last... */
02491    }
02492 
02493    for (; *p < end  ; (*p)++) {
02494       unsigned char c1, c2;   /* first-last char in range */
02495       c1 = (unsigned char)((*p)[0]);
02496       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02497          c2 = (unsigned char)((*p)[2]);
02498          *p += 2;    /* skip a total of 3 chars */
02499       } else {        /* individual character */
02500          c2 = c1;
02501       }
02502       if (c1 < cmin) {
02503          cmin = c1;
02504       }
02505       for (; c1 <= c2; c1++) {
02506          unsigned char mask = 1 << (c1 % 8);
02507          /*!\note If two patterns score the same, the one with the lowest
02508           * ascii values will compare as coming first. */
02509          /* Flag the character as included (used) and count it. */
02510          if (!(bitwise[ c1 / 8 ] & mask)) {
02511             bitwise[ c1 / 8 ] |= mask;
02512             count += 0x100;
02513          }
02514       }
02515    }
02516    (*p)++;
02517    return count == 0 ? 0x30000 : (count | cmin);
02518 }

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

copy a string skipping whitespace

Definition at line 8407 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

08408 {
08409    int count = 0;
08410    int insquares = 0;
08411 
08412    while (*src && (count < len - 1)) {
08413       if (*src == '[') {
08414          insquares = 1;
08415       } else if (*src == ']') {
08416          insquares = 0;
08417       } else if (*src == ' ' && !insquares) {
08418          src++;
08419          continue;
08420       }
08421       *dst = *src;
08422       dst++;
08423       src++;
08424       count++;
08425    }
08426    *dst = '\0';
08427 
08428    return count;
08429 }

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

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

02737 {
02738    int i;
02739    static int prof_id = -2;   /* marker for 'unallocated' id */
02740    if (prof_id == -2) {
02741       prof_id = ast_add_profile("ext_match", 0);
02742    }
02743    ast_mark(prof_id, 1);
02744    i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
02745    ast_mark(prof_id, 0);
02746    return i;
02747 }

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

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

05587 {
05588    struct fake_context item;
05589 
05590    ast_copy_string(item.name, context, sizeof(item.name));
05591 
05592    return ast_hashtab_lookup(contexts_table, &item);
05593 }

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

05601 {
05602    struct ast_context *c;
05603    struct fake_context item;
05604 
05605    ast_copy_string(item.name, context, sizeof(item.name));
05606 
05607    ast_rdlock_contexts();
05608    c = ast_hashtab_lookup(contexts_table, &item);
05609    if (!c) {
05610       ast_unlock_contexts();
05611    }
05612 
05613    return c;
05614 }

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

Find Hint by callback id.

Definition at line 4759 of file pbx.c.

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

Referenced by ast_extension_state_del().

04760 {
04761    struct ast_state_cb *state_cb;
04762    const struct ast_hint *hint = obj;
04763    int *id = arg;
04764 
04765    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
04766       ao2_ref(state_cb, -1);
04767       return CMP_MATCH | CMP_STOP;
04768    }
04769 
04770    return 0;
04771 }

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

References args, ast_log(), and LOG_WARNING.

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

03767 {
03768    char *args = strchr(function, '(');
03769 
03770    if (!args) {
03771       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
03772    } else {
03773       char *p;
03774       *args++ = '\0';
03775       if ((p = strrchr(args, ')'))) {
03776          *p = '\0';
03777       } else {
03778          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
03779       }
03780    }
03781    return args;
03782 }

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

Definition at line 1758 of file pbx.c.

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

01759 {
01760    /* find the exten at the end of the rope */
01761    struct match_char *node2 = node;
01762 
01763    for (node2 = node; node2; node2 = node2->next_char) {
01764       if (node2->exten) {
01765 #ifdef NEED_DEBUG_HERE
01766          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01767 #endif
01768          return node2->exten;
01769       }
01770    }
01771 #ifdef NEED_DEBUG_HERE
01772    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01773 #endif
01774    return 0;
01775 }

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

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

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

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

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

Referenced by ast_build_timing().

07764 {
07765    int start, end; /* start and ending position */
07766    unsigned int mask = 0;
07767    char *part;
07768 
07769    /* Check for whole range */
07770    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
07771       return (1 << max) - 1;
07772    }
07773 
07774    while ((part = strsep(&src, "&"))) {
07775       /* Get start and ending position */
07776       char *endpart = strchr(part, '-');
07777       if (endpart) {
07778          *endpart++ = '\0';
07779       }
07780       /* Find the start */
07781       if ((start = lookup_name(part, names, max)) < 0) {
07782          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
07783          continue;
07784       }
07785       if (endpart) { /* find end of range */
07786          if ((end = lookup_name(endpart, names, max)) < 0) {
07787             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
07788             continue;
07789          }
07790       } else {
07791          end = start;
07792       }
07793       /* Fill the mask. Remember that ranges are cyclic */
07794       mask |= (1 << end);   /* initialize with last element */
07795       while (start != end) {
07796          mask |= (1 << start);
07797          if (++start >= max) {
07798             start = 0;
07799          }
07800       }
07801    }
07802    return mask;
07803 }

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

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

Referenced by ast_build_timing().

07807 {
07808    char *endpart, *part;
07809    int x;
07810    int st_h, st_m;
07811    int endh, endm;
07812    int minute_start, minute_end;
07813 
07814    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
07815    memset(i->minmask, 0, sizeof(i->minmask));
07816 
07817    /* 1-minute per bit */
07818    /* Star is all times */
07819    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
07820       /* 48, because each hour takes 2 integers; 30 bits each */
07821       for (x = 0; x < 48; x++) {
07822          i->minmask[x] = 0x3fffffff; /* 30 bits */
07823       }
07824       return;
07825    }
07826    /* Otherwise expect a range */
07827    while ((part = strsep(&times, "&"))) {
07828       if (!(endpart = strchr(part, '-'))) {
07829          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07830             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
07831             continue;
07832          }
07833          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
07834          continue;
07835       }
07836       *endpart++ = '\0';
07837       /* why skip non digits? Mostly to skip spaces */
07838       while (*endpart && !isdigit(*endpart)) {
07839          endpart++;
07840       }
07841       if (!*endpart) {
07842          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
07843          continue;
07844       }
07845       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07846          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
07847          continue;
07848       }
07849       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
07850          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
07851          continue;
07852       }
07853       minute_start = st_h * 60 + st_m;
07854       minute_end = endh * 60 + endm;
07855       /* Go through the time and enable each appropriate bit */
07856       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
07857          i->minmask[x / 30] |= (1 << (x % 30));
07858       }
07859       /* Do the last one */
07860       i->minmask[x / 30] |= (1 << (x % 30));
07861    }
07862    /* All done */
07863    return;
07864 }

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

Send ack once.

Definition at line 6797 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(), strsep(), dialplan_counters::total_context, ast_cli_entry::usage, and ast_cli_args::word.

06798 {
06799    char *exten = NULL, *context = NULL;
06800    /* Variables used for different counters */
06801    struct dialplan_counters counters;
06802    const char *incstack[AST_PBX_MAX_STACK];
06803 
06804    switch (cmd) {
06805    case CLI_INIT:
06806       e->command = "dialplan debug";
06807       e->usage =
06808          "Usage: dialplan debug [context]\n"
06809          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
06810       return NULL;
06811    case CLI_GENERATE:
06812       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06813    }
06814 
06815    memset(&counters, 0, sizeof(counters));
06816 
06817    if (a->argc != 2 && a->argc != 3)
06818       return CLI_SHOWUSAGE;
06819 
06820    /* we obtain [exten@]context? if yes, split them ... */
06821    /* note: we ignore the exten totally here .... */
06822    if (a->argc == 3) {
06823       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06824          context = ast_strdupa(a->argv[2]);
06825          exten = strsep(&context, "@");
06826          /* change empty strings to NULL */
06827          if (ast_strlen_zero(exten))
06828             exten = NULL;
06829       } else { /* no '@' char, only context given */
06830          context = ast_strdupa(a->argv[2]);
06831       }
06832       if (ast_strlen_zero(context))
06833          context = NULL;
06834    }
06835    /* else Show complete dial plan, context and exten are NULL */
06836    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06837 
06838    /* check for input failure and throw some error messages */
06839    if (context && !counters.context_existence) {
06840       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06841       return CLI_FAILURE;
06842    }
06843 
06844 
06845    ast_cli(a->fd,"-= %d %s. =-\n",
06846          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06847 
06848    /* everything ok */
06849    return CLI_SUCCESS;
06850 }

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

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

07168 {
07169    struct ast_channel *chan;
07170    const char *chan_name, *var_name, *var_value;
07171 
07172    switch (cmd) {
07173    case CLI_INIT:
07174       e->command = "dialplan set chanvar";
07175       e->usage =
07176          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
07177          "       Set channel variable <varname> to <value>\n";
07178       return NULL;
07179    case CLI_GENERATE:
07180       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07181    }
07182 
07183    if (a->argc != e->args + 3)
07184       return CLI_SHOWUSAGE;
07185 
07186    chan_name = a->argv[e->args];
07187    var_name = a->argv[e->args + 1];
07188    var_value = a->argv[e->args + 2];
07189 
07190    if (!(chan = ast_channel_get_by_name(chan_name))) {
07191       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
07192       return CLI_FAILURE;
07193    }
07194 
07195    pbx_builtin_setvar_helper(chan, var_name, var_value);
07196 
07197    chan = ast_channel_unref(chan);
07198 
07199    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
07200 
07201    return CLI_SUCCESS;
07202 }

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

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

07205 {
07206    int oldval = 0;
07207 
07208    switch (cmd) {
07209    case CLI_INIT:
07210       e->command = "dialplan set extenpatternmatchnew true";
07211       e->usage =
07212          "Usage: dialplan set extenpatternmatchnew true|false\n"
07213          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07214       return NULL;
07215    case CLI_GENERATE:
07216       return NULL;
07217    }
07218 
07219    if (a->argc != 4)
07220       return CLI_SHOWUSAGE;
07221 
07222    oldval =  pbx_set_extenpatternmatchnew(1);
07223 
07224    if (oldval)
07225       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
07226    else
07227       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
07228 
07229    return CLI_SUCCESS;
07230 }

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

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

07146 {
07147    switch (cmd) {
07148    case CLI_INIT:
07149       e->command = "dialplan set global";
07150       e->usage =
07151          "Usage: dialplan set global <name> <value>\n"
07152          "       Set global dialplan variable <name> to <value>\n";
07153       return NULL;
07154    case CLI_GENERATE:
07155       return NULL;
07156    }
07157 
07158    if (a->argc != e->args + 2)
07159       return CLI_SHOWUSAGE;
07160 
07161    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
07162    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
07163 
07164    return CLI_SUCCESS;
07165 }

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

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

06162 {
06163    struct ast_app *aa;
06164    int app, no_registered_app = 1;
06165 
06166    switch (cmd) {
06167    case CLI_INIT:
06168       e->command = "core show application";
06169       e->usage =
06170          "Usage: core show application <application> [<application> [<application> [...]]]\n"
06171          "       Describes a particular application.\n";
06172       return NULL;
06173    case CLI_GENERATE:
06174       /*
06175        * There is a possibility to show informations about more than one
06176        * application at one time. You can type 'show application Dial Echo' and
06177        * you will see informations about these two applications ...
06178        */
06179       return ast_complete_applications(a->line, a->word, a->n);
06180    }
06181 
06182    if (a->argc < 4) {
06183       return CLI_SHOWUSAGE;
06184    }
06185 
06186    AST_RWLIST_RDLOCK(&apps);
06187    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06188       /* Check for each app that was supplied as an argument */
06189       for (app = 3; app < a->argc; app++) {
06190          if (strcasecmp(aa->name, a->argv[app])) {
06191             continue;
06192          }
06193 
06194          /* We found it! */
06195          no_registered_app = 0;
06196 
06197          print_app_docs(aa, a->fd);
06198       }
06199    }
06200    AST_RWLIST_UNLOCK(&apps);
06201 
06202    /* we found at least one app? no? */
06203    if (no_registered_app) {
06204       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
06205       return CLI_FAILURE;
06206    }
06207 
06208    return CLI_SUCCESS;
06209 }

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

Definition at line 6386 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, strcasestr(), ast_app::synopsis, ast_cli_entry::usage, and ast_cli_args::word.

06387 {
06388    struct ast_app *aa;
06389    int like = 0, describing = 0;
06390    int total_match = 0;    /* Number of matches in like clause */
06391    int total_apps = 0;     /* Number of apps registered */
06392    static const char * const choices[] = { "like", "describing", NULL };
06393 
06394    switch (cmd) {
06395    case CLI_INIT:
06396       e->command = "core show applications [like|describing]";
06397       e->usage =
06398          "Usage: core show applications [{like|describing} <text>]\n"
06399          "       List applications which are currently available.\n"
06400          "       If 'like', <text> will be a substring of the app name\n"
06401          "       If 'describing', <text> will be a substring of the description\n";
06402       return NULL;
06403    case CLI_GENERATE:
06404       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
06405    }
06406 
06407    AST_RWLIST_RDLOCK(&apps);
06408 
06409    if (AST_RWLIST_EMPTY(&apps)) {
06410       ast_cli(a->fd, "There are no registered applications\n");
06411       AST_RWLIST_UNLOCK(&apps);
06412       return CLI_SUCCESS;
06413    }
06414 
06415    /* core list applications like <keyword> */
06416    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
06417       like = 1;
06418    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
06419       describing = 1;
06420    }
06421 
06422    /* core list applications describing <keyword1> [<keyword2>] [...] */
06423    if ((!like) && (!describing)) {
06424       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
06425    } else {
06426       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
06427    }
06428 
06429    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06430       int printapp = 0;
06431       total_apps++;
06432       if (like) {
06433          if (strcasestr(aa->name, a->argv[4])) {
06434             printapp = 1;
06435             total_match++;
06436          }
06437       } else if (describing) {
06438          if (aa->description) {
06439             /* Match all words on command line */
06440             int i;
06441             printapp = 1;
06442             for (i = 4; i < a->argc; i++) {
06443                if (!strcasestr(aa->description, a->argv[i])) {
06444                   printapp = 0;
06445                } else {
06446                   total_match++;
06447                }
06448             }
06449          }
06450       } else {
06451          printapp = 1;
06452       }
06453 
06454       if (printapp) {
06455          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
06456       }
06457    }
06458    if ((!like) && (!describing)) {
06459       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
06460    } else {
06461       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
06462    }
06463 
06464    AST_RWLIST_UNLOCK(&apps);
06465 
06466    return CLI_SUCCESS;
06467 }

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

07111 {
07112    struct ast_channel *chan = NULL;
07113    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
07114 
07115    switch (cmd) {
07116    case CLI_INIT:
07117       e->command = "dialplan show chanvar";
07118       e->usage =
07119          "Usage: dialplan show chanvar <channel>\n"
07120          "       List current channel variables and their values\n";
07121       return NULL;
07122    case CLI_GENERATE:
07123       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07124    }
07125 
07126    if (a->argc != e->args + 1)
07127       return CLI_SHOWUSAGE;
07128 
07129    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
07130       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
07131       return CLI_FAILURE;
07132    }
07133 
07134    pbx_builtin_serialize_variables(chan, &vars);
07135 
07136    if (ast_str_strlen(vars)) {
07137       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
07138    }
07139 
07140    chan = ast_channel_unref(chan);
07141 
07142    return CLI_SUCCESS;
07143 }

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

Definition at line 6730 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(), strsep(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, ast_cli_entry::usage, and ast_cli_args::word.

06731 {
06732    char *exten = NULL, *context = NULL;
06733    /* Variables used for different counters */
06734    struct dialplan_counters counters;
06735    const char *incstack[AST_PBX_MAX_STACK];
06736 
06737    switch (cmd) {
06738    case CLI_INIT:
06739       e->command = "dialplan show";
06740       e->usage =
06741          "Usage: dialplan show [[exten@]context]\n"
06742          "       Show dialplan\n";
06743       return NULL;
06744    case CLI_GENERATE:
06745       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06746    }
06747 
06748    memset(&counters, 0, sizeof(counters));
06749 
06750    if (a->argc != 2 && a->argc != 3)
06751       return CLI_SHOWUSAGE;
06752 
06753    /* we obtain [exten@]context? if yes, split them ... */
06754    if (a->argc == 3) {
06755       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06756          context = ast_strdupa(a->argv[2]);
06757          exten = strsep(&context, "@");
06758          /* change empty strings to NULL */
06759          if (ast_strlen_zero(exten))
06760             exten = NULL;
06761       } else { /* no '@' char, only context given */
06762          context = ast_strdupa(a->argv[2]);
06763       }
06764       if (ast_strlen_zero(context))
06765          context = NULL;
06766    }
06767    /* else Show complete dial plan, context and exten are NULL */
06768    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06769 
06770    /* check for input failure and throw some error messages */
06771    if (context && !counters.context_existence) {
06772       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06773       return CLI_FAILURE;
06774    }
06775 
06776    if (exten && !counters.extension_existence) {
06777       if (context)
06778          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
06779             exten, context);
06780       else
06781          ast_cli(a->fd,
06782             "There is no existence of '%s' extension in all contexts\n",
06783             exten);
06784       return CLI_FAILURE;
06785    }
06786 
06787    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
06788             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
06789             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
06790             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06791 
06792    /* everything ok */
06793    return CLI_SUCCESS;
06794 }

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

Definition at line 3519 of file pbx.c.

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

03520 {
03521    struct ast_custom_function *acf;
03522    /* Maximum number of characters added by terminal coloring is 22 */
03523    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03524    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03525    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03526    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03527    char *ret = NULL;
03528    int which = 0;
03529    int wordlen;
03530 
03531    switch (cmd) {
03532    case CLI_INIT:
03533       e->command = "core show function";
03534       e->usage =
03535          "Usage: core show function <function>\n"
03536          "       Describe a particular dialplan function.\n";
03537       return NULL;
03538    case CLI_GENERATE:
03539       wordlen = strlen(a->word);
03540       /* case-insensitive for convenience in this 'complete' function */
03541       AST_RWLIST_RDLOCK(&acf_root);
03542       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03543          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03544             ret = ast_strdup(acf->name);
03545             break;
03546          }
03547       }
03548       AST_RWLIST_UNLOCK(&acf_root);
03549 
03550       return ret;
03551    }
03552 
03553    if (a->argc < 4) {
03554       return CLI_SHOWUSAGE;
03555    }
03556 
03557    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03558       ast_cli(a->fd, "No function by that name registered.\n");
03559       return CLI_FAILURE;
03560    }
03561 
03562    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03563    if (!(syntax = ast_malloc(syntax_size))) {
03564       ast_cli(a->fd, "Memory allocation failure!\n");
03565       return CLI_FAILURE;
03566    }
03567 
03568    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03569    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03570    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03571    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03572    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03573    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03574    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03575    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03576 #ifdef AST_XML_DOCS
03577    if (acf->docsrc == AST_XML_DOC) {
03578       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03579       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03580       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03581       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03582    } else
03583 #endif
03584    {
03585       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03586       synopsis = ast_malloc(synopsis_size);
03587 
03588       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03589       description = ast_malloc(description_size);
03590 
03591       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03592       arguments = ast_malloc(arguments_size);
03593 
03594       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03595       seealso = ast_malloc(seealso_size);
03596 
03597       /* check allocated memory. */
03598       if (!synopsis || !description || !arguments || !seealso) {
03599          ast_free(synopsis);
03600          ast_free(description);
03601          ast_free(arguments);
03602          ast_free(seealso);
03603          ast_free(syntax);
03604          return CLI_FAILURE;
03605       }
03606 
03607       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03608       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03609       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03610       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03611    }
03612 
03613    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03614          infotitle, syntitle, synopsis, destitle, description,
03615          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03616 
03617    ast_free(arguments);
03618    ast_free(synopsis);
03619    ast_free(description);
03620    ast_free(seealso);
03621    ast_free(syntax);
03622 
03623    return CLI_SUCCESS;
03624 }

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

Definition at line 3477 of file pbx.c.

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

03478 {
03479    struct ast_custom_function *acf;
03480    int count_acf = 0;
03481    int like = 0;
03482 
03483    switch (cmd) {
03484    case CLI_INIT:
03485       e->command = "core show functions [like]";
03486       e->usage =
03487          "Usage: core show functions [like <text>]\n"
03488          "       List builtin functions, optionally only those matching a given string\n";
03489       return NULL;
03490    case CLI_GENERATE:
03491       return NULL;
03492    }
03493 
03494    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03495       like = 1;
03496    } else if (a->argc != 3) {
03497       return CLI_SHOWUSAGE;
03498    }
03499 
03500    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03501 
03502    AST_RWLIST_RDLOCK(&acf_root);
03503    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03504       if (!like || strstr(acf->name, a->argv[4])) {
03505          count_acf++;
03506          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03507             S_OR(acf->name, ""),
03508             S_OR(acf->syntax, ""),
03509             S_OR(acf->synopsis, ""));
03510       }
03511    }
03512    AST_RWLIST_UNLOCK(&acf_root);
03513 
03514    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03515 
03516    return CLI_SUCCESS;
03517 }

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

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

07053 {
07054    int i = 0;
07055    struct ast_var_t *newvariable;
07056 
07057    switch (cmd) {
07058    case CLI_INIT:
07059       e->command = "dialplan show globals";
07060       e->usage =
07061          "Usage: dialplan show globals\n"
07062          "       List current global dialplan variables and their values\n";
07063       return NULL;
07064    case CLI_GENERATE:
07065       return NULL;
07066    }
07067 
07068    ast_rwlock_rdlock(&globalslock);
07069    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
07070       i++;
07071       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
07072    }
07073    ast_rwlock_unlock(&globalslock);
07074    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
07075 
07076    return CLI_SUCCESS;
07077 }

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

06299 {
06300    struct ast_hint *hint;
06301    int watchers;
06302    int num = 0, extenlen;
06303    struct ao2_iterator i;
06304 
06305    switch (cmd) {
06306    case CLI_INIT:
06307       e->command = "core show hint";
06308       e->usage =
06309          "Usage: core show hint <exten>\n"
06310          "       List registered hint\n";
06311       return NULL;
06312    case CLI_GENERATE:
06313       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
06314    }
06315 
06316    if (a->argc < 4)
06317       return CLI_SHOWUSAGE;
06318 
06319    if (ao2_container_count(hints) == 0) {
06320       ast_cli(a->fd, "There are no registered dialplan hints\n");
06321       return CLI_SUCCESS;
06322    }
06323 
06324    extenlen = strlen(a->argv[3]);
06325    i = ao2_iterator_init(hints, 0);
06326    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06327       ao2_lock(hint);
06328       if (!hint->exten) {
06329          /* The extension has already been destroyed */
06330          ao2_unlock(hint);
06331          continue;
06332       }
06333       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
06334          watchers = ao2_container_count(hint->callbacks);
06335          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06336             ast_get_extension_name(hint->exten),
06337             ast_get_context_name(ast_get_extension_context(hint->exten)),
06338             ast_get_extension_app(hint->exten),
06339             ast_extension_state2str(hint->laststate), watchers);
06340          num++;
06341       }
06342       ao2_unlock(hint);
06343    }
06344    ao2_iterator_destroy(&i);
06345    if (!num)
06346       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
06347    else
06348       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
06349    return CLI_SUCCESS;
06350 }

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

06213 {
06214    struct ast_hint *hint;
06215    int num = 0;
06216    int watchers;
06217    struct ao2_iterator i;
06218 
06219    switch (cmd) {
06220    case CLI_INIT:
06221       e->command = "core show hints";
06222       e->usage =
06223          "Usage: core show hints\n"
06224          "       List registered hints\n";
06225       return NULL;
06226    case CLI_GENERATE:
06227       return NULL;
06228    }
06229 
06230    if (ao2_container_count(hints) == 0) {
06231       ast_cli(a->fd, "There are no registered dialplan hints\n");
06232       return CLI_SUCCESS;
06233    }
06234    /* ... we have hints ... */
06235    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
06236 
06237    i = ao2_iterator_init(hints, 0);
06238    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06239       ao2_lock(hint);
06240       if (!hint->exten) {
06241          /* The extension has already been destroyed */
06242          ao2_unlock(hint);
06243          continue;
06244       }
06245       watchers = ao2_container_count(hint->callbacks);
06246       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06247          ast_get_extension_name(hint->exten),
06248          ast_get_context_name(ast_get_extension_context(hint->exten)),
06249          ast_get_extension_app(hint->exten),
06250          ast_extension_state2str(hint->laststate), watchers);
06251       ao2_unlock(hint);
06252       num++;
06253    }
06254    ao2_iterator_destroy(&i);
06255 
06256    ast_cli(a->fd, "----------------\n");
06257    ast_cli(a->fd, "- %d hints registered\n", num);
06258    return CLI_SUCCESS;
06259 }

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

06355 {
06356    struct ast_switch *sw;
06357 
06358    switch (cmd) {
06359    case CLI_INIT:
06360       e->command = "core show switches";
06361       e->usage =
06362          "Usage: core show switches\n"
06363          "       List registered switches\n";
06364       return NULL;
06365    case CLI_GENERATE:
06366       return NULL;
06367    }
06368 
06369    AST_RWLIST_RDLOCK(&switches);
06370 
06371    if (AST_RWLIST_EMPTY(&switches)) {
06372       AST_RWLIST_UNLOCK(&switches);
06373       ast_cli(a->fd, "There are no registered alternative switches\n");
06374       return CLI_SUCCESS;
06375    }
06376 
06377    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
06378    AST_RWLIST_TRAVERSE(&switches, sw, list)
06379       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
06380 
06381    AST_RWLIST_UNLOCK(&switches);
06382 
06383    return CLI_SUCCESS;
06384 }

static int handle_statechange ( void *  datap  )  [static]

Definition at line 4541 of file pbx.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_callback, ao2_t_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_create(), ast_str_set(), ast_hint::callbacks, ast_state_cb::change_cb, context_merge_lock, ast_state_cb::data, statechange::dev, ast_hint::exten, ast_hintdevice::hint, ast_hintdevice::hintdevice, hintdevice_cmp_multiple(), ast_hint::laststate, OBJ_MULTIPLE, OBJ_POINTER, and statecbs.

04542 {
04543    struct ast_hint *hint;
04544    struct ast_str *hint_app;
04545    struct ast_hintdevice *device;
04546    struct ast_hintdevice *cmpdevice;
04547    struct statechange *sc = datap;
04548    struct ao2_iterator *dev_iter;
04549    struct ao2_iterator cb_iter;
04550    char context_name[AST_MAX_CONTEXT];
04551    char exten_name[AST_MAX_EXTENSION];
04552 
04553    if (ao2_container_count(hintdevices) == 0) {
04554       /* There are no hints monitoring devices. */
04555       ast_free(sc);
04556       return 0;
04557    }
04558 
04559    hint_app = ast_str_create(1024);
04560    if (!hint_app) {
04561       ast_free(sc);
04562       return -1;
04563    }
04564 
04565    cmpdevice = alloca(sizeof(*cmpdevice) + strlen(sc->dev));
04566    strcpy(cmpdevice->hintdevice, sc->dev);
04567 
04568    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
04569    dev_iter = ao2_t_callback(hintdevices,
04570       OBJ_POINTER | OBJ_MULTIPLE,
04571       hintdevice_cmp_multiple,
04572       cmpdevice,
04573       "find devices in container");
04574    if (!dev_iter) {
04575       ast_mutex_unlock(&context_merge_lock);
04576       ast_free(hint_app);
04577       ast_free(sc);
04578       return -1;
04579    }
04580 
04581    for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
04582       struct ast_state_cb *state_cb;
04583       int state;
04584 
04585       if (!device->hint) {
04586          /* Should never happen. */
04587          continue;
04588       }
04589       hint = device->hint;
04590 
04591       ao2_lock(hint);
04592       if (!hint->exten) {
04593          /* The extension has already been destroyed */
04594          ao2_unlock(hint);
04595          continue;
04596       }
04597 
04598       /*
04599        * Save off strings in case the hint extension gets destroyed
04600        * while we are notifying the watchers.
04601        */
04602       ast_copy_string(context_name,
04603          ast_get_context_name(ast_get_extension_context(hint->exten)),
04604          sizeof(context_name));
04605       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
04606          sizeof(exten_name));
04607       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04608       ao2_unlock(hint);
04609 
04610       /*
04611        * Get device state for this hint.
04612        *
04613        * NOTE: We cannot hold any locks while determining the hint
04614        * device state or notifying the watchers without causing a
04615        * deadlock.  (conlock, hints, and hint)
04616        */
04617       state = ast_extension_state3(hint_app);
04618       if (state == hint->laststate) {
04619          continue;
04620       }
04621 
04622       /* Device state changed since last check - notify the watchers. */
04623       hint->laststate = state;   /* record we saw the change */
04624 
04625       /* For general callbacks */
04626       cb_iter = ao2_iterator_init(statecbs, 0);
04627       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04628          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04629       }
04630       ao2_iterator_destroy(&cb_iter);
04631 
04632       /* For extension callbacks */
04633       cb_iter = ao2_iterator_init(hint->callbacks, 0);
04634       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04635          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04636       }
04637       ao2_iterator_destroy(&cb_iter);
04638    }
04639    ast_mutex_unlock(&context_merge_lock);
04640 
04641    ao2_iterator_destroy(dev_iter);
04642    ast_free(hint_app);
04643    ast_free(sc);
04644    return 0;
04645 }

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

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

07233 {
07234    int oldval = 0;
07235 
07236    switch (cmd) {
07237    case CLI_INIT:
07238       e->command = "dialplan set extenpatternmatchnew false";
07239       e->usage =
07240          "Usage: dialplan set extenpatternmatchnew true|false\n"
07241          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07242       return NULL;
07243    case CLI_GENERATE:
07244       return NULL;
07245    }
07246 
07247    if (a->argc != 4)
07248       return CLI_SHOWUSAGE;
07249 
07250    oldval =  pbx_set_extenpatternmatchnew(0);
07251 
07252    if (!oldval)
07253       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
07254    else
07255       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
07256 
07257    return CLI_SUCCESS;
07258 }

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

Definition at line 1222 of file pbx.c.

References ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

01223 {
01224    const struct ast_exten *ac = ah_a;
01225    const struct ast_exten *bc = ah_b;
01226    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01227 }

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

Definition at line 1215 of file pbx.c.

References ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01216 {
01217    const struct ast_exten *ac = ah_a;
01218    const struct ast_exten *bc = ah_b;
01219    return ac->priority != bc->priority;
01220 }

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

Definition at line 1196 of file pbx.c.

References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.

Referenced by ast_add_extension2_lockopt().

01197 {
01198    const struct ast_exten *ac = ah_a;
01199    const struct ast_exten *bc = ah_b;
01200    int x = strcmp(ac->exten, bc->exten);
01201    if (x) { /* if exten names are diff, then return */
01202       return x;
01203    }
01204 
01205    /* but if they are the same, do the cidmatch values match? */
01206    if (ac->matchcid && bc->matchcid) {
01207       return strcmp(ac->cidmatch,bc->cidmatch);
01208    } else if (!ac->matchcid && !bc->matchcid) {
01209       return 0; /* if there's no matchcid on either side, then this is a match */
01210    } else {
01211       return 1; /* if there's matchcid on one but not the other, they are different */
01212    }
01213 }

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

Definition at line 1235 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01236 {
01237    const struct ast_exten *ac = obj;
01238    unsigned int x = ast_hashtab_hash_string(ac->exten);
01239    unsigned int y = 0;
01240    if (ac->matchcid)
01241       y = ast_hashtab_hash_string(ac->cidmatch);
01242    return x+y;
01243 }

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

Definition at line 1251 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

01252 {
01253    const struct ast_exten *ac = obj;
01254    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01255 }

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

Definition at line 1245 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

01246 {
01247    const struct ast_exten *ac = obj;
01248    return ast_hashtab_hash_int(ac->priority);
01249 }

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

Definition at line 10817 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_hint::exten.

Referenced by ast_pbx_init().

10818 {
10819    const struct ast_hint *hint = obj;
10820    const struct ast_exten *exten = arg;
10821 
10822    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
10823 }

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

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

10798 {
10799    const struct ast_hint *hint = obj;
10800    const char *exten_name;
10801    int res;
10802 
10803    exten_name = ast_get_extension_name(hint->exten);
10804    if (ast_strlen_zero(exten_name)) {
10805       /*
10806        * If the exten or extension name isn't set, return 0 so that
10807        * the ao2_find() search will start in the first bucket.
10808        */
10809       res = 0;
10810    } else {
10811       res = ast_str_case_hash(exten_name);
10812    }
10813 
10814    return res;
10815 }

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

Definition at line 4808 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

04809 {
04810    const struct ast_state_cb *cb = obj;
04811    int *id = arg;
04812 
04813    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
04814 }

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

Note:
Devices on hints are not unique so no CMP_STOP is returned Dont use ao2_find against hintdevices container cause there always could be more than one result.

Definition at line 999 of file pbx.c.

References CMP_MATCH, ext, and ast_hintdevice::hintdevice.

Referenced by ast_pbx_init(), and handle_statechange().

01000 {
01001    struct ast_hintdevice *ext = obj, *ext2 = arg;
01002 
01003    return !strcasecmp(ext->hintdevice, ext2->hintdevice) ? CMP_MATCH  : 0;
01004 }

static void hintdevice_destroy ( void *  obj  )  [static]

Definition at line 1035 of file pbx.c.

References ao2_ref, and ast_hintdevice::hint.

Referenced by add_hintdevice().

01036 {
01037    struct ast_hintdevice *doomed = obj;
01038 
01039    if (doomed->hint) {
01040       ao2_ref(doomed->hint, -1);
01041       doomed->hint = NULL;
01042    }
01043 }

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

Note:
Using the device for hash

Definition at line 988 of file pbx.c.

References ast_str_case_hash(), ext, and ast_hintdevice::hintdevice.

Referenced by ast_pbx_init().

00989 {
00990    const struct ast_hintdevice *ext = obj;
00991 
00992    return ast_str_case_hash(ext->hintdevice);
00993 }

static int hintdevice_remove_cb ( void *  deviceobj,
void *  arg,
int  flags 
) [static]

Definition at line 1010 of file pbx.c.

References CMP_MATCH, and ast_hintdevice::hint.

Referenced by remove_hintdevice().

01011 {
01012    struct ast_hintdevice *device = deviceobj;
01013    struct ast_hint *hint = arg;
01014 
01015    return (device->hint == hint) ? CMP_MATCH : 0;
01016 }

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

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

10399 {
10400    struct ast_data *data_hint;
10401    struct ast_hint *hint;
10402    int watchers;
10403    struct ao2_iterator i;
10404 
10405    if (ao2_container_count(hints) == 0) {
10406       return 0;
10407    }
10408 
10409    i = ao2_iterator_init(hints, 0);
10410    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
10411       watchers = ao2_container_count(hint->callbacks);
10412       data_hint = ast_data_add_node(data_root, "hint");
10413       if (!data_hint) {
10414          continue;
10415       }
10416       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
10417       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
10418       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
10419       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
10420       ast_data_add_int(data_hint, "watchers", watchers);
10421 
10422       if (!ast_data_search_match(search, data_hint)) {
10423          ast_data_remove_node(data_root, data_hint);
10424       }
10425    }
10426    ao2_iterator_destroy(&i);
10427 
10428    return 0;
10429 }

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

Definition at line 1595 of file pbx.c.

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

Referenced by pbx_find_extension().

01596 {
01597    if (!i->hastime)
01598       return 1;
01599 
01600    return ast_check_timing(&(i->timing));
01601 }

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

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

Referenced by ast_pbx_run_args(), and ast_pbx_start().

05406 {
05407    int failed = 0;
05408    double curloadavg;
05409 #if defined(HAVE_SYSINFO)
05410    long curfreemem;
05411    struct sysinfo sys_info;
05412 #endif
05413 
05414    ast_mutex_lock(&maxcalllock);
05415    if (option_maxcalls) {
05416       if (countcalls >= option_maxcalls) {
05417          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, ast_channel_name(c));
05418          failed = -1;
05419       }
05420    }
05421    if (option_maxload) {
05422       getloadavg(&curloadavg, 1);
05423       if (curloadavg >= option_maxload) {
05424          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, ast_channel_name(c), curloadavg);
05425          failed = -1;
05426       }
05427    }
05428 #if defined(HAVE_SYSINFO)
05429    if (option_minmemfree) {
05430       if (!sysinfo(&sys_info)) {
05431          /* make sure that the free system memory is above the configured low watermark
05432           * convert the amount of freeram from mem_units to MB */
05433          curfreemem = sys_info.freeram * sys_info.mem_unit;
05434          curfreemem /= 1024 * 1024;
05435          if (curfreemem < option_minmemfree) {
05436             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
05437             failed = -1;
05438          }
05439       }
05440    }
05441 #endif
05442 
05443    if (!failed) {
05444       countcalls++;
05445       totalcalls++;
05446    }
05447    ast_mutex_unlock(&maxcalllock);
05448 
05449    return failed;
05450 }

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

Definition at line 2012 of file pbx.c.

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

Referenced by add_pattern_node().

02013 {
02014    struct match_char *curr, *lcurr;
02015 
02016    /* insert node into the tree at "current", so the alt_char list from current is
02017       sorted in increasing value as you go to the leaves */
02018    if (!(*parent_ptr)) {
02019       *parent_ptr = node;
02020       return;
02021    }
02022 
02023    if ((*parent_ptr)->specificity > node->specificity) {
02024       /* insert at head */
02025       node->alt_char = (*parent_ptr);
02026       *parent_ptr = node;
02027       return;
02028    } 
02029 
02030    lcurr = *parent_ptr;
02031    for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
02032       if (curr->specificity > node->specificity) {
02033          node->alt_char = curr;
02034          lcurr->alt_char = node;
02035          break;
02036       }
02037       lcurr = curr;
02038    }
02039 
02040    if (!curr) {
02041       lcurr->alt_char = node;
02042    }
02043 
02044 }

int load_pbx ( void   ) 

Provided by pbx.c

Definition at line 10440 of file pbx.c.

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

Referenced by main().

10441 {
10442    int x;
10443 
10444    /* Initialize the PBX */
10445    ast_verb(1, "Asterisk PBX Core Initializing\n");
10446    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
10447       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
10448    }
10449 
10450    ast_verb(1, "Registering builtin applications:\n");
10451    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
10452    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
10453    __ast_custom_function_register(&exception_function, NULL);
10454    __ast_custom_function_register(&testtime_function, NULL);
10455 
10456    /* Register builtin applications */
10457    for (x = 0; x < ARRAY_LEN(builtins); x++) {
10458       ast_verb(1, "[%s]\n", builtins[x].name);
10459       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
10460          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
10461          return -1;
10462       }
10463    }
10464 
10465    /* Register manager application */
10466    ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
10467 
10468    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
10469          AST_EVENT_IE_END))) {
10470       return -1;
10471    }
10472 
10473    return 0;
10474 }

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

Referenced by get_range().

07741 {
07742    int i;
07743 
07744    if (names && *s > '9') {
07745       for (i = 0; names[i]; i++) {
07746          if (!strcasecmp(s, names[i])) {
07747             return i;
07748          }
07749       }
07750    }
07751 
07752    /* Allow months and weekdays to be specified as numbers, as well */
07753    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
07754       /* What the array offset would have been: "1" would be at offset 0 */
07755       return i - 1;
07756    }
07757    return -1; /* error return */
07758 }

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

Send ack once.

Definition at line 6853 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan_helper().

06854 {
06855    astman_send_listack(s, m, "DialPlan list will follow", "start");
06856 }

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

Manager listing of dial plan.

Definition at line 6999 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_show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by load_pbx().

07000 {
07001    const char *exten, *context;
07002    const char *id = astman_get_header(m, "ActionID");
07003    char idtext[256];
07004 
07005    /* Variables used for different counters */
07006    struct dialplan_counters counters;
07007 
07008    if (!ast_strlen_zero(id))
07009       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
07010    else
07011       idtext[0] = '\0';
07012 
07013    memset(&counters, 0, sizeof(counters));
07014 
07015    exten = astman_get_header(m, "Extension");
07016    context = astman_get_header(m, "Context");
07017 
07018    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
07019 
07020    if (context && !counters.context_existence) {
07021       char errorbuf[BUFSIZ];
07022 
07023       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
07024       astman_send_error(s, m, errorbuf);
07025       return 0;
07026    }
07027    if (exten && !counters.extension_existence) {
07028       char errorbuf[BUFSIZ];
07029 
07030       if (context)
07031          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
07032       else
07033          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
07034       astman_send_error(s, m, errorbuf);
07035       return 0;
07036    }
07037 
07038    astman_append(s, "Event: ShowDialPlanComplete\r\n"
07039       "EventList: Complete\r\n"
07040       "ListItems: %d\r\n"
07041       "ListExtensions: %d\r\n"
07042       "ListPriorities: %d\r\n"
07043       "ListContexts: %d\r\n"
07044       "%s"
07045       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
07046 
07047    /* everything ok */
07048    return 0;
07049 }

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

06866 {
06867    struct ast_context *c;
06868    int res = 0, old_total_exten = dpc->total_exten;
06869 
06870    if (ast_strlen_zero(exten))
06871       exten = NULL;
06872    if (ast_strlen_zero(context))
06873       context = NULL;
06874 
06875    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
06876 
06877    /* try to lock contexts */
06878    if (ast_rdlock_contexts()) {
06879       astman_send_error(s, m, "Failed to lock contexts");
06880       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
06881       return -1;
06882    }
06883 
06884    c = NULL;      /* walk all contexts ... */
06885    while ( (c = ast_walk_contexts(c)) ) {
06886       struct ast_exten *e;
06887       struct ast_include *i;
06888       struct ast_ignorepat *ip;
06889 
06890       if (context && strcmp(ast_get_context_name(c), context) != 0)
06891          continue;   /* not the name we want */
06892 
06893       dpc->context_existence = 1;
06894 
06895       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
06896 
06897       if (ast_rdlock_context(c)) {  /* failed to lock */
06898          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
06899          continue;
06900       }
06901 
06902       /* XXX note- an empty context is not printed */
06903       e = NULL;      /* walk extensions in context  */
06904       while ( (e = ast_walk_context_extensions(c, e)) ) {
06905          struct ast_exten *p;
06906 
06907          /* looking for extension? is this our extension? */
06908          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
06909             /* not the one we are looking for, continue */
06910             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
06911             continue;
06912          }
06913          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
06914 
06915          dpc->extension_existence = 1;
06916 
06917          /* may we print context info? */
06918          dpc->total_context++;
06919          dpc->total_exten++;
06920 
06921          p = NULL;      /* walk next extension peers */
06922          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06923             int prio = ast_get_extension_priority(p);
06924 
06925             dpc->total_prio++;
06926             if (!dpc->total_items++)
06927                manager_dpsendack(s, m);
06928             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06929             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
06930 
06931             /* XXX maybe make this conditional, if p != e ? */
06932             if (ast_get_extension_label(p))
06933                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
06934 
06935             if (prio == PRIORITY_HINT) {
06936                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
06937             } else {
06938                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));
06939             }
06940             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
06941          }
06942       }
06943 
06944       i = NULL;      /* walk included and write info ... */
06945       while ( (i = ast_walk_context_includes(c, i)) ) {
06946          if (exten) {
06947             /* Check all includes for the requested extension */
06948             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
06949          } else {
06950             if (!dpc->total_items++)
06951                manager_dpsendack(s, m);
06952             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06953             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));
06954             astman_append(s, "\r\n");
06955             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
06956          }
06957       }
06958 
06959       ip = NULL;  /* walk ignore patterns and write info ... */
06960       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06961          const char *ipname = ast_get_ignorepat_name(ip);
06962          char ignorepat[AST_MAX_EXTENSION];
06963 
06964          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06965          if (!exten || ast_extension_match(ignorepat, exten)) {
06966             if (!dpc->total_items++)
06967                manager_dpsendack(s, m);
06968             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06969             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
06970             astman_append(s, "\r\n");
06971          }
06972       }
06973       if (!rinclude) {
06974          struct ast_sw *sw = NULL;
06975          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06976             if (!dpc->total_items++)
06977                manager_dpsendack(s, m);
06978             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06979             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));
06980             astman_append(s, "\r\n");
06981             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
06982          }
06983       }
06984 
06985       ast_unlock_context(c);
06986    }
06987    ast_unlock_contexts();
06988 
06989    if (dpc->total_exten == old_total_exten) {
06990       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
06991       /* Nothing new under the sun */
06992       return -1;
06993    } else {
06994       return res;
06995    }
06996 }

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

Definition at line 2807 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

02808 {
02809    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02810       failing to get a number should count as a match, otherwise not */
02811 
02812    if (ast_strlen_zero(callerid)) {
02813       return ast_strlen_zero(cidpattern) ? 1 : 0;
02814    }
02815 
02816    return ast_extension_match(cidpattern, callerid);
02817 }

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

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

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

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

03118 {
03119    int parens = 0;
03120 
03121    *offset = 0;
03122    *length = INT_MAX;
03123    *isfunc = 0;
03124    for (; *var; var++) {
03125       if (*var == '(') {
03126          (*isfunc)++;
03127          parens++;
03128       } else if (*var == ')') {
03129          parens--;
03130       } else if (*var == ':' && parens == 0) {
03131          *var++ = '\0';
03132          sscanf(var, "%30d:%30d", offset, length);
03133          return 1; /* offset:length valid */
03134       }
03135    }
03136    return 0;
03137 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 10273 of file pbx.c.

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

Referenced by handle_cli_dialplan_reload(), and reload().

10274 {
10275    struct ast_var_t *vardata;
10276 
10277    ast_rwlock_wrlock(&globalslock);
10278    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10279       ast_var_delete(vardata);
10280    ast_rwlock_unlock(&globalslock);
10281 }

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 10035 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(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), manager_mixmonitor(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), setsubstate(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().

10036 {
10037    struct ast_var_t *variables;
10038    const char *ret = NULL;
10039    int i;
10040    struct varshead *places[2] = { NULL, &globals };
10041 
10042    if (!name)
10043       return NULL;
10044 
10045    if (chan) {
10046       ast_channel_lock(chan);
10047       places[0] = &chan->varshead;
10048    }
10049 
10050    for (i = 0; i < 2; i++) {
10051       if (!places[i])
10052          continue;
10053       if (places[i] == &globals)
10054          ast_rwlock_rdlock(&globalslock);
10055       AST_LIST_TRAVERSE(places[i], variables, entries) {
10056          if (!strcmp(name, ast_var_name(variables))) {
10057             ret = ast_var_value(variables);
10058             break;
10059          }
10060       }
10061       if (places[i] == &globals)
10062          ast_rwlock_unlock(&globalslock);
10063       if (ret)
10064          break;
10065    }
10066 
10067    if (chan)
10068       ast_channel_unlock(chan);
10069 
10070    return ret;
10071 }

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

Definition at line 10295 of file pbx.c.

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

10296 {
10297    char *condition, *branch1, *branch2, *branch;
10298    char *stringp;
10299 
10300    if (ast_strlen_zero(data)) {
10301       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
10302       return 0;
10303    }
10304 
10305    stringp = ast_strdupa(data);
10306    condition = strsep(&stringp,"?");
10307    branch1 = strsep(&stringp,":");
10308    branch2 = strsep(&stringp,"");
10309    branch = pbx_checkcondition(condition) ? branch1 : branch2;
10310 
10311    if (ast_strlen_zero(branch)) {
10312       ast_debug(1, "Not taking any branch\n");
10313       return 0;
10314    }
10315 
10316    return pbx_builtin_goto(chan, branch);
10317 }

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

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

10232 {
10233    char *name;
10234    char *value;
10235    char *channel;
10236    char tmp[VAR_BUF_SIZE];
10237    static int deprecation_warning = 0;
10238 
10239    if (ast_strlen_zero(data)) {
10240       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
10241       return 0;
10242    }
10243    tmp[0] = 0;
10244    if (!deprecation_warning) {
10245       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
10246       deprecation_warning = 1;
10247    }
10248 
10249    value = ast_strdupa(data);
10250    name = strsep(&value,"=");
10251    channel = strsep(&value,",");
10252    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
10253       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
10254       if (chan2) {
10255          char *s = alloca(strlen(value) + 4);
10256          if (s) {
10257             sprintf(s, "${%s}", value);
10258             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
10259          }
10260          chan2 = ast_channel_unref(chan2);
10261       }
10262       pbx_builtin_setvar_helper(chan, name, tmp);
10263    }
10264 
10265    return(0);
10266 }

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

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

09562 {
09563    const char *options = data;
09564    int answer = 1;
09565 
09566    /* Some channels can receive DTMF in unanswered state; some cannot */
09567    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
09568       answer = 0;
09569    }
09570 
09571    /* If the channel is hungup, stop waiting */
09572    if (ast_check_hangup(chan)) {
09573       return -1;
09574    } else if (chan->_state != AST_STATE_UP && answer) {
09575       __ast_answer(chan, 0, 1);
09576    }
09577 
09578    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
09579 
09580    return AST_PBX_INCOMPLETE;
09581 }

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

Definition at line 10268 of file pbx.c.

10269 {
10270    return 0;
10271 }

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

10074 {
10075    struct ast_var_t *newvariable;
10076    struct varshead *headp;
10077 
10078    if (name[strlen(name)-1] == ')') {
10079       char *function = ast_strdupa(name);
10080 
10081       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10082       ast_func_write(chan, function, value);
10083       return;
10084    }
10085 
10086    if (chan) {
10087       ast_channel_lock(chan);
10088       headp = &chan->varshead;
10089    } else {
10090       ast_rwlock_wrlock(&globalslock);
10091       headp = &globals;
10092    }
10093 
10094    if (value) {
10095       if (headp == &globals)
10096          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10097       newvariable = ast_var_assign(name, value);
10098       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10099    }
10100 
10101    if (chan)
10102       ast_channel_unlock(chan);
10103    else
10104       ast_rwlock_unlock(&globalslock);
10105 }

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

Definition at line 3446 of file pbx.c.

References raise_exception().

03447 {
03448    /* Priority will become 1, next time through the AUTOLOOP */
03449    return raise_exception(chan, reason, 0);
03450 }

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

Definition at line 10356 of file pbx.c.

References ast_channel_language(), and ast_say_character_str().

10357 {
10358    int res = 0;
10359 
10360    if (data)
10361       res = ast_say_character_str(chan, data, "", ast_channel_language(chan));
10362    return res;
10363 }

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

Definition at line 10347 of file pbx.c.

References ast_channel_language(), and ast_say_digit_str().

10348 {
10349    int res = 0;
10350 
10351    if (data)
10352       res = ast_say_digit_str(chan, data, "", ast_channel_language(chan));
10353    return res;
10354 }

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

Definition at line 10319 of file pbx.c.

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

10320 {
10321    char tmp[256];
10322    char *number = tmp;
10323    char *options;
10324 
10325    if (ast_strlen_zero(data)) {
10326       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
10327       return -1;
10328    }
10329    ast_copy_string(tmp, data, sizeof(tmp));
10330    strsep(&number, ",");
10331    options = strsep(&number, ",");
10332    if (options) {
10333       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
10334          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
10335          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
10336          return -1;
10337       }
10338    }
10339 
10340    if (ast_say_number(chan, atoi(tmp), "", ast_channel_language(chan), options)) {
10341       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
10342    }
10343 
10344    return 0;
10345 }

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

Definition at line 10365 of file pbx.c.

References ast_channel_language(), and ast_say_phonetic_str().

10366 {
10367    int res = 0;
10368 
10369    if (data)
10370       res = ast_say_phonetic_str(chan, data, "", ast_channel_language(chan));
10371    return res;
10372 }

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

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

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

10005 {
10006    struct ast_var_t *variables;
10007    const char *var, *val;
10008    int total = 0;
10009 
10010    if (!chan)
10011       return 0;
10012 
10013    ast_str_reset(*buf);
10014 
10015    ast_channel_lock(chan);
10016 
10017    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10018       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10019          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10020          ) {
10021          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10022             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10023             break;
10024          } else
10025             total++;
10026       } else
10027          break;
10028    }
10029 
10030    ast_channel_unlock(chan);
10031 
10032    return total;
10033 }

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

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

Referenced by ast_compile_ael2(), and rpt_exec().

10166 {
10167    char *name, *value, *mydata;
10168 
10169    if (ast_compat_app_set) {
10170       return pbx_builtin_setvar_multiple(chan, data);
10171    }
10172 
10173    if (ast_strlen_zero(data)) {
10174       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10175       return 0;
10176    }
10177 
10178    mydata = ast_strdupa(data);
10179    name = strsep(&mydata, "=");
10180    value = mydata;
10181    if (!value) {
10182       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10183       return 0;
10184    }
10185 
10186    if (strchr(name, ' ')) {
10187       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10188    }
10189 
10190    pbx_builtin_setvar_helper(chan, name, value);
10191 
10192    return 0;
10193 }

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

References ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), 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(), calendar_write_exec(), 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_notify(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), fax_detect_framehook(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), launch_monitor_thread(), 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(), msg_send_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), setsubstate(), 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().

10108 {
10109    struct ast_var_t *newvariable;
10110    struct varshead *headp;
10111    const char *nametail = name;
10112 
10113    if (name[strlen(name) - 1] == ')') {
10114       char *function = ast_strdupa(name);
10115 
10116       return ast_func_write(chan, function, value);
10117    }
10118 
10119    if (chan) {
10120       ast_channel_lock(chan);
10121       headp = &chan->varshead;
10122    } else {
10123       ast_rwlock_wrlock(&globalslock);
10124       headp = &globals;
10125    }
10126 
10127    /* For comparison purposes, we have to strip leading underscores */
10128    if (*nametail == '_') {
10129       nametail++;
10130       if (*nametail == '_')
10131          nametail++;
10132    }
10133 
10134    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10135       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10136          /* there is already such a variable, delete it */
10137          AST_LIST_REMOVE_CURRENT(entries);
10138          ast_var_delete(newvariable);
10139          break;
10140       }
10141    }
10142    AST_LIST_TRAVERSE_SAFE_END;
10143 
10144    if (value) {
10145       if (headp == &globals)
10146          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10147       newvariable = ast_var_assign(name, value);
10148       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10149       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
10150          "Channel: %s\r\n"
10151          "Variable: %s\r\n"
10152          "Value: %s\r\n"
10153          "Uniqueid: %s\r\n",
10154          chan ? ast_channel_name(chan) : "none", name, value,
10155          chan ? ast_channel_uniqueid(chan) : "none");
10156    }
10157 
10158    if (chan)
10159       ast_channel_unlock(chan);
10160    else
10161       ast_rwlock_unlock(&globalslock);
10162    return 0;
10163 }

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

10196 {
10197    char *data;
10198    int x;
10199    AST_DECLARE_APP_ARGS(args,
10200       AST_APP_ARG(pair)[24];
10201    );
10202    AST_DECLARE_APP_ARGS(pair,
10203       AST_APP_ARG(name);
10204       AST_APP_ARG(value);
10205    );
10206 
10207    if (ast_strlen_zero(vdata)) {
10208       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10209       return 0;
10210    }
10211 
10212    data = ast_strdupa(vdata);
10213    AST_STANDARD_APP_ARGS(args, data);
10214 
10215    for (x = 0; x < args.argc; x++) {
10216       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10217       if (pair.argc == 2) {
10218          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10219          if (strchr(pair.name, ' '))
10220             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);
10221       } else if (!chan) {
10222          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10223       } else {
10224          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10225       }
10226    }
10227 
10228    return 0;
10229 }

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

10284 {
10285    int res;
10286    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10287       return 0;
10288    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10289       return res;
10290    } else {                                         /* Strings are true */
10291       return 1;
10292    }
10293 }

static void pbx_destroy ( struct ast_pbx p  )  [static]

Definition at line 1603 of file pbx.c.

References ast_free.

Referenced by __ast_pbx_run().

01604 {
01605    ast_free(p);
01606 }

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

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

Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), record_thread(), try_calling(), and tryexec_exec().

01526 {
01527    int res;
01528    struct ast_module_user *u = NULL;
01529    const char *saved_c_appl;
01530    const char *saved_c_data;
01531 
01532    if (c->cdr && !ast_check_hangup(c))
01533       ast_cdr_setapp(c->cdr, app->name, data);
01534 
01535    /* save channel values */
01536    saved_c_appl= c->appl;
01537    saved_c_data= c->data;
01538 
01539    c->appl = app->name;
01540    c->data = data;
01541    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01542 
01543    if (app->module)
01544       u = __ast_module_user_add(app->module, c);
01545    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01546          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01547       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01548          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01549          app->name, (char *) data);
01550    }
01551    res = app->execute(c, S_OR(data, ""));
01552    if (app->module && u)
01553       __ast_module_user_remove(app->module, u);
01554    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01555    /* restore channel values */
01556    c->appl = saved_c_appl;
01557    c->data = saved_c_data;
01558    return res;
01559 }

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

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

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

04329 {
04330    struct ast_exten *e;
04331    struct ast_app *app;
04332    int res;
04333    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04334    char passdata[EXT_DATA_SIZE];
04335 
04336    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04337 
04338    ast_rdlock_contexts();
04339    if (found)
04340       *found = 0;
04341 
04342    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04343    if (e) {
04344       if (found)
04345          *found = 1;
04346       if (matching_action) {
04347          ast_unlock_contexts();
04348          return -1;  /* success, we found it */
04349       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04350          res = e->priority;
04351          ast_unlock_contexts();
04352          return res; /* the priority we were looking for */
04353       } else { /* spawn */
04354          if (!e->cached_app)
04355             e->cached_app = pbx_findapp(e->app);
04356          app = e->cached_app;
04357          ast_unlock_contexts();
04358          if (!app) {
04359             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04360             return -1;
04361          }
04362          if (c->context != context)
04363             ast_copy_string(c->context, context, sizeof(c->context));
04364          if (c->exten != exten)
04365             ast_copy_string(c->exten, exten, sizeof(c->exten));
04366          c->priority = priority;
04367          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
04368 #ifdef CHANNEL_TRACE
04369          ast_channel_trace_update(c);
04370 #endif
04371          ast_debug(1, "Launching '%s'\n", app->name);
04372          if (VERBOSITY_ATLEAST(3)) {
04373             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
04374             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
04375                exten, context, priority,
04376                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
04377                term_color(tmp2, ast_channel_name(c), COLOR_BRMAGENTA, 0, sizeof(tmp2)),
04378                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
04379                "in new stack");
04380          }
04381          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
04382                "Channel: %s\r\n"
04383                "Context: %s\r\n"
04384                "Extension: %s\r\n"
04385                "Priority: %d\r\n"
04386                "Application: %s\r\n"
04387                "AppData: %s\r\n"
04388                "Uniqueid: %s\r\n",
04389                ast_channel_name(c), c->context, c->exten, c->priority, app->name, passdata, ast_channel_uniqueid(c));
04390          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04391       }
04392    } else if (q.swo) {  /* not found here, but in another switch */
04393       if (found)
04394          *found = 1;
04395       ast_unlock_contexts();
04396       if (matching_action) {
04397          return -1;
04398       } else {
04399          if (!q.swo->exec) {
04400             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04401             res = -1;
04402          }
04403          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04404       }
04405    } else { /* not found anywhere, see what happened */
04406       ast_unlock_contexts();
04407       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04408       switch (q.status) {
04409       case STATUS_NO_CONTEXT:
04410          if (!matching_action && !combined_find_spawn)
04411             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04412          break;
04413       case STATUS_NO_EXTENSION:
04414          if (!matching_action && !combined_find_spawn)
04415             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04416          break;
04417       case STATUS_NO_PRIORITY:
04418          if (!matching_action && !combined_find_spawn)
04419             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04420          break;
04421       case STATUS_NO_LABEL:
04422          if (context && !combined_find_spawn)
04423             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04424          break;
04425       default:
04426          ast_debug(1, "Shouldn't happen!\n");
04427       }
04428 
04429       return (matching_action) ? 0 : -1;
04430    }
04431 }

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

References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_debug, 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_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, strsep(), switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().

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

02823 {
02824    int x, res;
02825    struct ast_context *tmp = NULL;
02826    struct ast_exten *e = NULL, *eroot = NULL;
02827    struct ast_include *i = NULL;
02828    struct ast_sw *sw = NULL;
02829    struct ast_exten pattern = {NULL, };
02830    struct scoreboard score = {0, };
02831    struct ast_str *tmpdata = NULL;
02832 
02833    pattern.label = label;
02834    pattern.priority = priority;
02835 #ifdef NEED_DEBUG_HERE
02836    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02837 #endif
02838 
02839    /* Initialize status if appropriate */
02840    if (q->stacklen == 0) {
02841       q->status = STATUS_NO_CONTEXT;
02842       q->swo = NULL;
02843       q->data = NULL;
02844       q->foundcontext = NULL;
02845    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02846       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02847       return NULL;
02848    }
02849 
02850    /* Check first to see if we've already been checked */
02851    for (x = 0; x < q->stacklen; x++) {
02852       if (!strcasecmp(q->incstack[x], context))
02853          return NULL;
02854    }
02855 
02856    if (bypass) { /* bypass means we only look there */
02857       tmp = bypass;
02858    } else {      /* look in contexts */
02859       tmp = find_context(context);
02860       if (!tmp) {
02861          return NULL;
02862       }
02863    }
02864 
02865    if (q->status < STATUS_NO_EXTENSION)
02866       q->status = STATUS_NO_EXTENSION;
02867 
02868    /* Do a search for matching extension */
02869 
02870    eroot = NULL;
02871    score.total_specificity = 0;
02872    score.exten = 0;
02873    score.total_length = 0;
02874    if (!tmp->pattern_tree && tmp->root_table) {
02875       create_match_char_tree(tmp);
02876 #ifdef NEED_DEBUG
02877       ast_debug(1, "Tree Created in context %s:\n", context);
02878       log_match_char_tree(tmp->pattern_tree," ");
02879 #endif
02880    }
02881 #ifdef NEED_DEBUG
02882    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
02883    log_match_char_tree(tmp->pattern_tree, "::  ");
02884 #endif
02885 
02886    do {
02887       if (!ast_strlen_zero(overrideswitch)) {
02888          char *osw = ast_strdupa(overrideswitch), *name;
02889          struct ast_switch *asw;
02890          ast_switch_f *aswf = NULL;
02891          char *datap;
02892          int eval = 0;
02893 
02894          name = strsep(&osw, "/");
02895          asw = pbx_findswitch(name);
02896 
02897          if (!asw) {
02898             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
02899             break;
02900          }
02901 
02902          if (osw && strchr(osw, '$')) {
02903             eval = 1;
02904          }
02905 
02906          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02907             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
02908             break;
02909          } else if (eval) {
02910             /* Substitute variables now */
02911             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02912             datap = ast_str_buffer(tmpdata);
02913          } else {
02914             datap = osw;
02915          }
02916 
02917          /* equivalent of extension_match_core() at the switch level */
02918          if (action == E_CANMATCH)
02919             aswf = asw->canmatch;
02920          else if (action == E_MATCHMORE)
02921             aswf = asw->matchmore;
02922          else /* action == E_MATCH */
02923             aswf = asw->exists;
02924          if (!aswf) {
02925             res = 0;
02926          } else {
02927             if (chan) {
02928                ast_autoservice_start(chan);
02929             }
02930             res = aswf(chan, context, exten, priority, callerid, datap);
02931             if (chan) {
02932                ast_autoservice_stop(chan);
02933             }
02934          }
02935          if (res) {  /* Got a match */
02936             q->swo = asw;
02937             q->data = datap;
02938             q->foundcontext = context;
02939             /* XXX keep status = STATUS_NO_CONTEXT ? */
02940             return NULL;
02941          }
02942       }
02943    } while (0);
02944 
02945    if (extenpatternmatchnew) {
02946       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
02947       eroot = score.exten;
02948 
02949       if (score.last_char == '!' && action == E_MATCHMORE) {
02950          /* We match an extension ending in '!'.
02951           * The decision in this case is final and is NULL (no match).
02952           */
02953 #ifdef NEED_DEBUG_HERE
02954          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
02955 #endif
02956          return NULL;
02957       }
02958 
02959       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
02960          q->status = STATUS_SUCCESS;
02961 #ifdef NEED_DEBUG_HERE
02962          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
02963 #endif
02964          return score.canmatch_exten;
02965       }
02966 
02967       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
02968          if (score.node) {
02969             struct ast_exten *z = trie_find_next_match(score.node);
02970             if (z) {
02971 #ifdef NEED_DEBUG_HERE
02972                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
02973 #endif
02974             } else {
02975                if (score.canmatch_exten) {
02976 #ifdef NEED_DEBUG_HERE
02977                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
02978 #endif
02979                   return score.canmatch_exten;
02980                } else {
02981 #ifdef NEED_DEBUG_HERE
02982                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
02983 #endif
02984                }
02985             }
02986             return z;
02987          }
02988 #ifdef NEED_DEBUG_HERE
02989          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
02990 #endif
02991          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
02992       }
02993 
02994       if (eroot) {
02995          /* found entry, now look for the right priority */
02996          if (q->status < STATUS_NO_PRIORITY)
02997             q->status = STATUS_NO_PRIORITY;
02998          e = NULL;
02999          if (action == E_FINDLABEL && label ) {
03000             if (q->status < STATUS_NO_LABEL)
03001                q->status = STATUS_NO_LABEL;
03002             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03003          } else {
03004             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03005          }
03006          if (e) { /* found a valid match */
03007             q->status = STATUS_SUCCESS;
03008             q->foundcontext = context;
03009 #ifdef NEED_DEBUG_HERE
03010             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
03011 #endif
03012             return e;
03013          }
03014       }
03015    } else {   /* the old/current default exten pattern match algorithm */
03016 
03017       /* scan the list trying to match extension and CID */
03018       eroot = NULL;
03019       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
03020          int match = extension_match_core(eroot->exten, exten, action);
03021          /* 0 on fail, 1 on match, 2 on earlymatch */
03022 
03023          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
03024             continue;   /* keep trying */
03025          if (match == 2 && action == E_MATCHMORE) {
03026             /* We match an extension ending in '!'.
03027              * The decision in this case is final and is NULL (no match).
03028              */
03029             return NULL;
03030          }
03031          /* found entry, now look for the right priority */
03032          if (q->status < STATUS_NO_PRIORITY)
03033             q->status = STATUS_NO_PRIORITY;
03034          e = NULL;
03035          if (action == E_FINDLABEL && label ) {
03036             if (q->status < STATUS_NO_LABEL)
03037                q->status = STATUS_NO_LABEL;
03038             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03039          } else {
03040             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03041          }
03042          if (e) { /* found a valid match */
03043             q->status = STATUS_SUCCESS;
03044             q->foundcontext = context;
03045             return e;
03046          }
03047       }
03048    }
03049 
03050    /* Check alternative switches */
03051    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
03052       struct ast_switch *asw = pbx_findswitch(sw->name);
03053       ast_switch_f *aswf = NULL;
03054       char *datap;
03055 
03056       if (!asw) {
03057          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
03058          continue;
03059       }
03060 
03061       /* Substitute variables now */
03062       if (sw->eval) {
03063          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03064             ast_log(LOG_WARNING, "Can't evaluate switch?!");
03065             continue;
03066          }
03067          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03068       }
03069 
03070       /* equivalent of extension_match_core() at the switch level */
03071       if (action == E_CANMATCH)
03072          aswf = asw->canmatch;
03073       else if (action == E_MATCHMORE)
03074          aswf = asw->matchmore;
03075       else /* action == E_MATCH */
03076          aswf = asw->exists;
03077       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
03078       if (!aswf)
03079          res = 0;
03080       else {
03081          if (chan)
03082             ast_autoservice_start(chan);
03083          res = aswf(chan, context, exten, priority, callerid, datap);
03084          if (chan)
03085             ast_autoservice_stop(chan);
03086       }
03087       if (res) {  /* Got a match */
03088          q->swo = asw;
03089          q->data = datap;
03090          q->foundcontext = context;
03091          /* XXX keep status = STATUS_NO_CONTEXT ? */
03092          return NULL;
03093       }
03094    }
03095    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
03096    /* Now try any includes we have in this context */
03097    for (i = tmp->includes; i; i = i->next) {
03098       if (include_valid(i)) {
03099          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
03100 #ifdef NEED_DEBUG_HERE
03101             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
03102 #endif
03103             return e;
03104          }
03105          if (q->swo)
03106             return NULL;
03107       }
03108    }
03109    return NULL;
03110 }

struct ast_app* pbx_findapp ( const char *  app  )  [read]

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

Definition at line 1581 of file pbx.c.

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

Referenced by pbx_find_extension().

01582 {
01583    struct ast_switch *asw;
01584 
01585    AST_RWLIST_RDLOCK(&switches);
01586    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01587       if (!strcasecmp(asw->name, sw))
01588          break;
01589    }
01590    AST_RWLIST_UNLOCK(&switches);
01591 
01592    return asw;
01593 }

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

Definition at line 10713 of file pbx.c.

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

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

10714 {
10715    char *exten, *pri, *context;
10716    char *stringp;
10717    int ipri;
10718    int mode = 0;
10719 
10720    if (ast_strlen_zero(goto_string)) {
10721       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
10722       return -1;
10723    }
10724    stringp = ast_strdupa(goto_string);
10725    context = strsep(&stringp, ","); /* guaranteed non-null */
10726    exten = strsep(&stringp, ",");
10727    pri = strsep(&stringp, ",");
10728    if (!exten) {  /* Only a priority in this one */
10729       pri = context;
10730       exten = NULL;
10731       context = NULL;
10732    } else if (!pri) {   /* Only an extension and priority in this one */
10733       pri = exten;
10734       exten = context;
10735       context = NULL;
10736    }
10737    if (*pri == '+') {
10738       mode = 1;
10739       pri++;
10740    } else if (*pri == '-') {
10741       mode = -1;
10742       pri++;
10743    }
10744    if (sscanf(pri, "%30d", &ipri) != 1) {
10745       ipri = ast_findlabel_extension(chan, context ? context : chan->context,
10746          exten ? exten : chan->exten, pri,
10747          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
10748       if (ipri < 1) {
10749          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
10750          return -1;
10751       } else
10752          mode = 0;
10753    }
10754    /* At this point we have a priority and maybe an extension and a context */
10755 
10756    if (mode)
10757       ipri = chan->priority + (ipri * mode);
10758 
10759    if (async)
10760       ast_async_goto(chan, context, exten, ipri);
10761    else
10762       ast_explicit_goto(chan, context, exten, ipri);
10763 
10764    return 0;
10765 
10766 }

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

03241 {
03242    struct ast_str *str = ast_str_create(16);
03243    const char *cret;
03244 
03245    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03246    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03247    *ret = cret ? workspace : NULL;
03248    ast_free(str);
03249 }

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

References autofallthrough.

Referenced by pbx_load_module().

05557 {
05558    int oldval = autofallthrough;
05559    autofallthrough = newval;
05560    return oldval;
05561 }

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

References extenpatternmatchnew.

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

05564 {
05565    int oldval = extenpatternmatchnew;
05566    extenpatternmatchnew = newval;
05567    return oldval;
05568 }

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

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

Referenced by pbx_load_module().

05571 {
05572    if (overrideswitch) {
05573       ast_free(overrideswitch);
05574    }
05575    if (!ast_strlen_zero(newval)) {
05576       overrideswitch = ast_strdup(newval);
05577    } else {
05578       overrideswitch = NULL;
05579    }
05580 }

static void pbx_substitute_variables ( char *  passdata,
int  datalen,
struct ast_channel c,
struct ast_exten e 
) [static]

Definition at line 4289 of file pbx.c.

References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().

Referenced by pbx_extension_helper().

04290 {
04291    const char *tmp;
04292 
04293    /* Nothing more to do */
04294    if (!e->data) {
04295       *passdata = '\0';
04296       return;
04297    }
04298 
04299    /* No variables or expressions in e->data, so why scan it? */
04300    if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
04301       ast_copy_string(passdata, e->data, datalen);
04302       return;
04303    }
04304 
04305    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
04306 }

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

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

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

04082 {
04083    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04084    char *cp4 = NULL;
04085    const char *whereweare, *orig_cp2 = cp2;
04086    int length, offset, offset2, isfunction;
04087    char *workspace = NULL;
04088    char *ltmp = NULL, *var = NULL;
04089    char *nextvar, *nextexp, *nextthing;
04090    char *vars, *vare;
04091    int pos, brackets, needsub, len;
04092 
04093    *cp2 = 0; /* just in case nothing ends up there */
04094    whereweare = cp1;
04095    while (!ast_strlen_zero(whereweare) && count) {
04096       /* Assume we're copying the whole remaining string */
04097       pos = strlen(whereweare);
04098       nextvar = NULL;
04099       nextexp = NULL;
04100       nextthing = strchr(whereweare, '$');
04101       if (nextthing) {
04102          switch (nextthing[1]) {
04103          case '{':
04104             nextvar = nextthing;
04105             pos = nextvar - whereweare;
04106             break;
04107          case '[':
04108             nextexp = nextthing;
04109             pos = nextexp - whereweare;
04110             break;
04111          default:
04112             pos = 1;
04113          }
04114       }
04115 
04116       if (pos) {
04117          /* Can't copy more than 'count' bytes */
04118          if (pos > count)
04119             pos = count;
04120 
04121          /* Copy that many bytes */
04122          memcpy(cp2, whereweare, pos);
04123 
04124          count -= pos;
04125          cp2 += pos;
04126          whereweare += pos;
04127          *cp2 = 0;
04128       }
04129 
04130       if (nextvar) {
04131          /* We have a variable.  Find the start and end, and determine
04132             if we are going to have to recursively call ourselves on the
04133             contents */
04134          vars = vare = nextvar + 2;
04135          brackets = 1;
04136          needsub = 0;
04137 
04138          /* Find the end of it */
04139          while (brackets && *vare) {
04140             if ((vare[0] == '$') && (vare[1] == '{')) {
04141                needsub++;
04142             } else if (vare[0] == '{') {
04143                brackets++;
04144             } else if (vare[0] == '}') {
04145                brackets--;
04146             } else if ((vare[0] == '$') && (vare[1] == '['))
04147                needsub++;
04148             vare++;
04149          }
04150          if (brackets)
04151             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04152          len = vare - vars - 1;
04153 
04154          /* Skip totally over variable string */
04155          whereweare += (len + 3);
04156 
04157          if (!var)
04158             var = alloca(VAR_BUF_SIZE);
04159 
04160          /* Store variable name (and truncate) */
04161          ast_copy_string(var, vars, len + 1);
04162 
04163          /* Substitute if necessary */
04164          if (needsub) {
04165             size_t used;
04166             if (!ltmp)
04167                ltmp = alloca(VAR_BUF_SIZE);
04168 
04169             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04170             vars = ltmp;
04171          } else {
04172             vars = var;
04173          }
04174 
04175          if (!workspace)
04176             workspace = alloca(VAR_BUF_SIZE);
04177 
04178          workspace[0] = '\0';
04179 
04180          parse_variable_name(vars, &offset, &offset2, &isfunction);
04181          if (isfunction) {
04182             /* Evaluate function */
04183             if (c || !headp)
04184                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04185             else {
04186                struct varshead old;
04187                struct ast_channel *c = ast_dummy_channel_alloc();
04188                if (c) {
04189                   memcpy(&old, &c->varshead, sizeof(old));
04190                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04191                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04192                   /* Don't deallocate the varshead that was passed in */
04193                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04194                   c = ast_channel_unref(c);
04195                } else {
04196                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04197                }
04198             }
04199             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04200          } else {
04201             /* Retrieve variable value */
04202             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04203          }
04204          if (cp4) {
04205             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04206 
04207             length = strlen(cp4);
04208             if (length > count)
04209                length = count;
04210             memcpy(cp2, cp4, length);
04211             count -= length;
04212             cp2 += length;
04213             *cp2 = 0;
04214          }
04215       } else if (nextexp) {
04216          /* We have an expression.  Find the start and end, and determine
04217             if we are going to have to recursively call ourselves on the
04218             contents */
04219          vars = vare = nextexp + 2;
04220          brackets = 1;
04221          needsub = 0;
04222 
04223          /* Find the end of it */
04224          while (brackets && *vare) {
04225             if ((vare[0] == '$') && (vare[1] == '[')) {
04226                needsub++;
04227                brackets++;
04228                vare++;
04229             } else if (vare[0] == '[') {
04230                brackets++;
04231             } else if (vare[0] == ']') {
04232                brackets--;
04233             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04234                needsub++;
04235                vare++;
04236             }
04237             vare++;
04238          }
04239          if (brackets)
04240             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04241          len = vare - vars - 1;
04242 
04243          /* Skip totally over expression */
04244          whereweare += (len + 3);
04245 
04246          if (!var)
04247             var = alloca(VAR_BUF_SIZE);
04248 
04249          /* Store variable name (and truncate) */
04250          ast_copy_string(var, vars, len + 1);
04251 
04252          /* Substitute if necessary */
04253          if (needsub) {
04254             size_t used;
04255             if (!ltmp)
04256                ltmp = alloca(VAR_BUF_SIZE);
04257 
04258             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04259             vars = ltmp;
04260          } else {
04261             vars = var;
04262          }
04263 
04264          length = ast_expr(vars, cp2, count, c);
04265 
04266          if (length) {
04267             ast_debug(1, "Expression result is '%s'\n", cp2);
04268             count -= length;
04269             cp2 += length;
04270             *cp2 = 0;
04271          }
04272       }
04273    }
04274    *used = cp2 - orig_cp2;
04275 }

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

Definition at line 4283 of file pbx.c.

References pbx_substitute_variables_helper_full().

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

04284 {
04285    size_t used;
04286    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04287 }

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

Definition at line 5474 of file pbx.c.

References __ast_pbx_run(), and decrease_call_count().

Referenced by ast_pbx_start().

05475 {
05476    /* Oh joyeous kernel, we're a new thread, with nothing to do but
05477       answer this channel and get it going.
05478    */
05479    /* NOTE:
05480       The launcher of this function _MUST_ increment 'countcalls'
05481       before invoking the function; it will be decremented when the
05482       PBX has finished running on the channel
05483     */
05484    struct ast_channel *c = data;
05485 
05486    __ast_pbx_run(c, NULL);
05487    decrease_call_count();
05488 
05489    pthread_exit(NULL);
05490 
05491    return NULL;
05492 }

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

Definition at line 6086 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, COLOR_CYAN, COLOR_MAGENTA, ast_app::description, ast_switch::description, ast_app::name, S_OR, ast_app::seealso, ast_app::synopsis, synopsis, ast_app::syntax, and term_color().

Referenced by handle_show_application().

06087 {
06088    /* Maximum number of characters added by terminal coloring is 22 */
06089    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
06090    char seealsotitle[40];
06091    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
06092    char *seealso = NULL;
06093    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
06094 
06095    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
06096    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
06097 
06098    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
06099    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
06100    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
06101    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
06102    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
06103 
06104 #ifdef AST_XML_DOCS
06105    if (aa->docsrc == AST_XML_DOC) {
06106       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
06107       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
06108       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
06109       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
06110 
06111       if (!synopsis || !description || !arguments || !seealso) {
06112          goto return_cleanup;
06113       }
06114    } else
06115 #endif
06116    {
06117       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06118       synopsis = ast_malloc(synopsis_size);
06119 
06120       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06121       description = ast_malloc(description_size);
06122 
06123       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06124       arguments = ast_malloc(arguments_size);
06125 
06126       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06127       seealso = ast_malloc(seealso_size);
06128 
06129       if (!synopsis || !description || !arguments || !seealso) {
06130          goto return_cleanup;
06131       }
06132 
06133       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
06134       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
06135       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
06136       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
06137    }
06138 
06139    /* Handle the syntax the same for both XML and raw docs */
06140    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
06141    if (!(syntax = ast_malloc(syntax_size))) {
06142       goto return_cleanup;
06143    }
06144    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
06145 
06146    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
06147          infotitle, syntitle, synopsis, destitle, description,
06148          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
06149 
06150 return_cleanup:
06151    ast_free(description);
06152    ast_free(arguments);
06153    ast_free(synopsis);
06154    ast_free(seealso);
06155    ast_free(syntax);
06156 }

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

helper function to print an extension

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

06513 {
06514    int prio = ast_get_extension_priority(e);
06515    if (prio == PRIORITY_HINT) {
06516       snprintf(buf, buflen, "hint: %s",
06517          ast_get_extension_app(e));
06518    } else {
06519       snprintf(buf, buflen, "%d. %s(%s)",
06520          prio, ast_get_extension_app(e),
06521          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06522    }
06523 }

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

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

03421 {
03422    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03423    struct pbx_exception *exception = NULL;
03424 
03425    if (!ds) {
03426       ds = ast_datastore_alloc(&exception_store_info, NULL);
03427       if (!ds)
03428          return -1;
03429       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03430          ast_datastore_free(ds);
03431          return -1;
03432       }
03433       ds->data = exception;
03434       ast_channel_datastore_add(chan, ds);
03435    } else
03436       exception = ds->data;
03437 
03438    ast_string_field_set(exception, reason, reason);
03439    ast_string_field_set(exception, context, chan->context);
03440    ast_string_field_set(exception, exten, chan->exten);
03441    exception->priority = chan->priority;
03442    set_ext_pri(chan, "e", priority);
03443    return 0;
03444 }

static int remove_hintdevice ( struct ast_hint hint  )  [static]

Definition at line 1018 of file pbx.c.

References ao2_t_callback, hintdevice_remove_cb(), OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by ast_change_hint(), and ast_remove_hint().

01019 {
01020    /* iterate through all devices and remove the devices which are linked to this hint */
01021    ao2_t_callback(hintdevices, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
01022       hintdevice_remove_cb, hint,
01023       "callback to remove all devices which are linked to a hint");
01024    return 0;
01025 }

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

05058 {
05059    ast_channel_lock(c);
05060    ast_copy_string(c->exten, exten, sizeof(c->exten));
05061    c->priority = pri;
05062    ast_channel_unlock(c);
05063 }

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

06678 {
06679    struct ast_context *c = NULL;
06680    int res = 0, old_total_exten = dpc->total_exten;
06681 
06682    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
06683 
06684    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
06685    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
06686    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
06687    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
06688    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
06689    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
06690    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
06691    ast_rdlock_contexts();
06692 
06693    /* walk all contexts ... */
06694    while ( (c = ast_walk_contexts(c)) ) {
06695       int context_info_printed = 0;
06696 
06697       if (context && strcmp(ast_get_context_name(c), context))
06698          continue;   /* skip this one, name doesn't match */
06699 
06700       dpc->context_existence = 1;
06701 
06702       if (!c->pattern_tree)
06703          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
06704 
06705       ast_rdlock_context(c);
06706 
06707       dpc->total_context++;
06708       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06709          ast_get_context_name(c), ast_get_context_registrar(c));
06710       context_info_printed = 1;
06711 
06712       if (c->pattern_tree)
06713       {
06714          cli_match_char_tree(c->pattern_tree, " ", fd);
06715       } else {
06716          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
06717       }
06718 
06719       ast_unlock_context(c);
06720 
06721       /* if we print something in context, make an empty line */
06722       if (context_info_printed)
06723          ast_cli(fd, "\n");
06724    }
06725    ast_unlock_contexts();
06726 
06727    return (dpc->total_exten == old_total_exten) ? -1 : res;
06728 }

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

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

Referenced by handle_show_dialplan().

06527 {
06528    struct ast_context *c = NULL;
06529    int res = 0, old_total_exten = dpc->total_exten;
06530 
06531    ast_rdlock_contexts();
06532 
06533    /* walk all contexts ... */
06534    while ( (c = ast_walk_contexts(c)) ) {
06535       struct ast_exten *e;
06536       struct ast_include *i;
06537       struct ast_ignorepat *ip;
06538       char buf[256], buf2[256];
06539       int context_info_printed = 0;
06540 
06541       if (context && strcmp(ast_get_context_name(c), context))
06542          continue;   /* skip this one, name doesn't match */
06543 
06544       dpc->context_existence = 1;
06545 
06546       ast_rdlock_context(c);
06547 
06548       /* are we looking for exten too? if yes, we print context
06549        * only if we find our extension.
06550        * Otherwise print context even if empty ?
06551        * XXX i am not sure how the rinclude is handled.
06552        * I think it ought to go inside.
06553        */
06554       if (!exten) {
06555          dpc->total_context++;
06556          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06557             ast_get_context_name(c), ast_get_context_registrar(c));
06558          context_info_printed = 1;
06559       }
06560 
06561       /* walk extensions ... */
06562       e = NULL;
06563       while ( (e = ast_walk_context_extensions(c, e)) ) {
06564          struct ast_exten *p;
06565 
06566          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
06567             continue;   /* skip, extension match failed */
06568 
06569          dpc->extension_existence = 1;
06570 
06571          /* may we print context info? */
06572          if (!context_info_printed) {
06573             dpc->total_context++;
06574             if (rinclude) { /* TODO Print more info about rinclude */
06575                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
06576                   ast_get_context_name(c), ast_get_context_registrar(c));
06577             } else {
06578                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06579                   ast_get_context_name(c), ast_get_context_registrar(c));
06580             }
06581             context_info_printed = 1;
06582          }
06583          dpc->total_prio++;
06584 
06585          /* write extension name and first peer */
06586          if (e->matchcid)
06587             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
06588          else
06589             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
06590 
06591          print_ext(e, buf2, sizeof(buf2));
06592 
06593          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
06594             ast_get_extension_registrar(e));
06595 
06596          dpc->total_exten++;
06597          /* walk next extension peers */
06598          p = e;   /* skip the first one, we already got it */
06599          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06600             const char *el = ast_get_extension_label(p);
06601             dpc->total_prio++;
06602             if (el)
06603                snprintf(buf, sizeof(buf), "   [%s]", el);
06604             else
06605                buf[0] = '\0';
06606             print_ext(p, buf2, sizeof(buf2));
06607 
06608             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
06609                ast_get_extension_registrar(p));
06610          }
06611       }
06612 
06613       /* walk included and write info ... */
06614       i = NULL;
06615       while ( (i = ast_walk_context_includes(c, i)) ) {
06616          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
06617          if (exten) {
06618             /* Check all includes for the requested extension */
06619             if (includecount >= AST_PBX_MAX_STACK) {
06620                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
06621             } else {
06622                int dupe = 0;
06623                int x;
06624                for (x = 0; x < includecount; x++) {
06625                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
06626                      dupe++;
06627                      break;
06628                   }
06629                }
06630                if (!dupe) {
06631                   includes[includecount] = ast_get_include_name(i);
06632                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
06633                } else {
06634                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
06635                }
06636             }
06637          } else {
06638             ast_cli(fd, "  Include =>        %-45s [%s]\n",
06639                buf, ast_get_include_registrar(i));
06640          }
06641       }
06642 
06643       /* walk ignore patterns and write info ... */
06644       ip = NULL;
06645       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06646          const char *ipname = ast_get_ignorepat_name(ip);
06647          char ignorepat[AST_MAX_EXTENSION];
06648          snprintf(buf, sizeof(buf), "'%s'", ipname);
06649          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06650          if (!exten || ast_extension_match(ignorepat, exten)) {
06651             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
06652                buf, ast_get_ignorepat_registrar(ip));
06653          }
06654       }
06655       if (!rinclude) {
06656          struct ast_sw *sw = NULL;
06657          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06658             snprintf(buf, sizeof(buf), "'%s/%s'",
06659                ast_get_switch_name(sw),
06660                ast_get_switch_data(sw));
06661             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
06662                buf, ast_get_switch_registrar(sw));
06663          }
06664       }
06665 
06666       ast_unlock_context(c);
06667 
06668       /* if we print something in context, make an empty line */
06669       if (context_info_printed)
06670          ast_cli(fd, "\n");
06671    }
06672    ast_unlock_contexts();
06673 
06674    return (dpc->total_exten == old_total_exten) ? -1 : res;
06675 }

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

Definition at line 10825 of file pbx.c.

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

10826 {
10827    const struct ast_state_cb *state_cb = obj;
10828    ast_state_cb_type change_cb = arg;
10829 
10830    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
10831 }

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

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

03151 {
03152    char *ret = workspace;
03153    int lr;  /* length of the input string after the copy */
03154 
03155    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
03156 
03157    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
03158 
03159    /* Quick check if no need to do anything */
03160    if (offset == 0 && length >= lr) /* take the whole string */
03161       return ret;
03162 
03163    if (offset < 0)   {  /* translate negative offset into positive ones */
03164       offset = lr + offset;
03165       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03166          offset = 0;
03167    }
03168 
03169    /* too large offset result in empty string so we know what to return */
03170    if (offset >= lr)
03171       return ret + lr;  /* the final '\0' */
03172 
03173    ret += offset;    /* move to the start position */
03174    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
03175       ret[length] = '\0';
03176    else if (length < 0) {
03177       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
03178          ret[lr + length - offset] = '\0';
03179       else
03180          ret[0] = '\0';
03181    }
03182 
03183    return ret;
03184 }

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

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

01778 {
01779    struct match_char *m3;
01780    struct match_char *m4;
01781    struct ast_exten *e3;
01782 
01783    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01784       return node->exten;
01785    }
01786 
01787    if (node && node->x[0] == '!' && !node->x[1]) {
01788       return node->exten;
01789    }
01790 
01791    if (!node || !node->next_char) {
01792       return NULL;
01793    }
01794 
01795    m3 = node->next_char;
01796 
01797    if (m3->exten) {
01798       return m3->exten;
01799    }
01800    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01801       if (m4->exten) {
01802          return m4->exten;
01803       }
01804    }
01805    for (m4 = m3; m4; m4 = m4->alt_char) {
01806       e3 = trie_find_next_match(m3);
01807       if (e3) {
01808          return e3;
01809       }
01810    }
01811 
01812    return NULL;
01813 }

static void unreference_cached_app ( struct ast_app app  )  [static]

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

07285 {
07286    struct ast_context *context = NULL;
07287    struct ast_exten *eroot = NULL, *e = NULL;
07288 
07289    ast_rdlock_contexts();
07290    while ((context = ast_walk_contexts(context))) {
07291       while ((eroot = ast_walk_context_extensions(context, eroot))) {
07292          while ((e = ast_walk_extension_priorities(eroot, e))) {
07293             if (e->cached_app == app)
07294                e->cached_app = NULL;
07295          }
07296       }
07297    }
07298    ast_unlock_contexts();
07299 
07300    return;
07301 }

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

01683 {
01684    /* if this extension is marked as deleted, then skip this -- if it never shows
01685       on the scoreboard, it will never be found, nor will halt the traversal. */
01686    if (deleted)
01687       return;
01688    board->total_specificity = spec;
01689    board->total_length = length;
01690    board->exten = exten;
01691    board->last_char = last;
01692    board->node = node;
01693 #ifdef NEED_DEBUG_HERE
01694    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01695 #endif
01696 }

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

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

09446 {
09447    int res;
09448    struct ast_frame *f;
09449    double waitsec;
09450    int waittime;
09451 
09452    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
09453       waitsec = -1;
09454    if (waitsec > -1) {
09455       waittime = waitsec * 1000.0;
09456       ast_safe_sleep(chan, waittime);
09457    } else do {
09458       res = ast_waitfor(chan, -1);
09459       if (res < 0)
09460          return;
09461       f = ast_read(chan);
09462       if (f)
09463          ast_frfree(f);
09464    } while(f);
09465 }


Variable Documentation

int autofallthrough = 1 [static]

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

Referenced by pbx_builtin_background().

struct pbx_builtin builtins[] [static]

Declaration of builtin applications.

Referenced by load_pbx().

ast_mutex_t conlock = { PTHREAD_MUTEX_INITIALIZER , 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 1320 of file pbx.c.

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

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

Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.

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

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

const char* const days[] [static]

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

Definition at line 804 of file pbx.c.

Initial value:

 {
   .name = "EXCEPTION",
   .read = acf_exception_read,
}

Definition at line 3472 of file pbx.c.

Referenced by load_pbx().

Initial value:

 {
   .type = "EXCEPTION",
   .destroy = exception_store_free,
}

Definition at line 3404 of file pbx.c.

Referenced by acf_exception_read(), and raise_exception().

int extenpatternmatchnew = 0 [static]

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

Referenced by ast_extension_state2().

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static]

Definition at line 1259 of file pbx.c.

ast_rwlock_t globalslock = { {0} , NULL, 1 } [static]

struct ast_threadstorage hintdevice_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_hintdevice_data , .custom_init = NULL , } [static]

Definition at line 957 of file pbx.c.

Referenced by add_hintdevice().

struct ao2_container* hintdevices [static]

Container for hint devices.

Definition at line 968 of file pbx.c.

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 1340 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(), hints_data_provider_get(), and lua_register_hints().

Initial value:

Definition at line 10431 of file pbx.c.

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

Definition at line 1268 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

const char* const months[] [static]

Definition at line 7878 of file pbx.c.

Referenced by ast_build_timing().

char* overrideswitch = NULL [static]

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

Referenced by load_pbx().

Initial value:

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

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

Referenced by pbx_builtin_resetcdr().

struct ao2_container* statecbs [static]

int stateid = 1 [static]

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

Referenced by pbx_find_extension().

Initial value:

 {
   .name = "TESTTIME",
   .write = testtime_write,
}

Definition at line 9679 of file pbx.c.

Referenced by load_pbx().

int totalcalls [static]

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

Referenced by pbx_builtin_waitexten().


Generated on Fri Feb 10 06:36:55 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6